@flowgram.ai/free-layout-core 0.1.12 → 0.1.14

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 +157 -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 +203 -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
@@ -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
@@ -1099,7 +1104,7 @@ import {
1099
1104
  delay as delay2
1100
1105
  } from "@flowgram.ai/utils";
1101
1106
  import {
1102
- FlowNodeTransformData as FlowNodeTransformData5,
1107
+ FlowNodeTransformData as FlowNodeTransformData6,
1103
1108
  FlowOperationBaseService
1104
1109
  } from "@flowgram.ai/document";
1105
1110
  import { FlowNodeBaseType as FlowNodeBaseType2 } from "@flowgram.ai/document";
@@ -1114,12 +1119,12 @@ import {
1114
1119
  import { last } from "lodash-es";
1115
1120
  import { inject as inject3, injectable as injectable3 } from "inversify";
1116
1121
  import { Disposable as Disposable2, DisposableCollection, Emitter as Emitter3 } from "@flowgram.ai/utils";
1117
- import { FlowNodeTransformData as FlowNodeTransformData2 } from "@flowgram.ai/document";
1122
+ import { FlowNodeRenderData as FlowNodeRenderData2, FlowNodeTransformData as FlowNodeTransformData3 } from "@flowgram.ai/document";
1118
1123
  import { EntityManager as EntityManager2, PlaygroundConfigEntity as PlaygroundConfigEntity2, TransformData as TransformData6 } from "@flowgram.ai/core";
1119
1124
 
1120
1125
  // src/workflow-document-option.ts
1121
1126
  import { FlowNodeErrorData } from "@flowgram.ai/form-core";
1122
- import { FlowNodeTransformData } from "@flowgram.ai/document";
1127
+ import { FlowNodeTransformData as FlowNodeTransformData2 } from "@flowgram.ai/document";
1123
1128
  import { TransformData as TransformData5 } from "@flowgram.ai/core";
1124
1129
 
1125
1130
  // src/utils/flow-node-form-data.ts
@@ -1170,7 +1175,7 @@ var WorkflowDocumentOptionsDefault = {
1170
1175
  const nodeMeta = node.getNodeMeta();
1171
1176
  const subCanvas = nodeMeta.subCanvas?.(node);
1172
1177
  if (subCanvas?.isCanvas === false) {
1173
- const canvasNodeTransform = subCanvas.canvasNode.getData(FlowNodeTransformData);
1178
+ const canvasNodeTransform = subCanvas.canvasNode.getData(FlowNodeTransformData2);
1174
1179
  const { x, y } = canvasNodeTransform.transform.position;
1175
1180
  metaData.canvasPosition = { x, y };
1176
1181
  }
@@ -1468,12 +1473,12 @@ var WorkflowLinesManager = class {
1468
1473
  * @param pos - 鼠标位置
1469
1474
  */
1470
1475
  getNodeFromMousePos(pos) {
1471
- const allNodes = this.document.getAllNodes();
1476
+ const allNodes = this.document.getAllNodes().sort((a, b) => this.getNodeIndex(a) - this.getNodeIndex(b));
1472
1477
  const containNodes = [];
1473
1478
  const { selection } = this.selectService;
1474
1479
  const zoom = this.entityManager.getEntity(PlaygroundConfigEntity2)?.config?.zoom || 1;
1475
1480
  allNodes.forEach((node) => {
1476
- const { bounds } = node.getData(FlowNodeTransformData2);
1481
+ const { bounds } = node.getData(FlowNodeTransformData3);
1477
1482
  if (bounds.clone().pad(4 / zoom).contains(pos.x, pos.y)) {
1478
1483
  containNodes.push(node);
1479
1484
  }
@@ -1495,6 +1500,10 @@ var WorkflowLinesManager = class {
1495
1500
  registerData(line) {
1496
1501
  line.addData(WorkflowLineRenderData);
1497
1502
  }
1503
+ getNodeIndex(node) {
1504
+ const nodeRenderData = node.getData(FlowNodeRenderData2);
1505
+ return nodeRenderData.stackIndex;
1506
+ }
1498
1507
  };
1499
1508
  __decorateClass([
1500
1509
  inject3(WorkflowHoverService)
@@ -1517,7 +1526,7 @@ import { customAlphabet } from "nanoid";
1517
1526
  import { inject as inject5, injectable as injectable5, optional, postConstruct } from "inversify";
1518
1527
  import { Disposable as Disposable3, Emitter as Emitter4 } from "@flowgram.ai/utils";
1519
1528
  import { NodeEngineContext } from "@flowgram.ai/form-core";
1520
- import { FlowDocument, FlowNodeBaseType, FlowNodeTransformData as FlowNodeTransformData4 } from "@flowgram.ai/document";
1529
+ import { FlowDocument, FlowNodeBaseType, FlowNodeTransformData as FlowNodeTransformData5 } from "@flowgram.ai/document";
1521
1530
  import {
1522
1531
  injectPlaygroundContext,
1523
1532
  PlaygroundConfigEntity as PlaygroundConfigEntity4,
@@ -1529,7 +1538,7 @@ import {
1529
1538
  import { inject as inject4, injectable as injectable4 } from "inversify";
1530
1539
  import {
1531
1540
  FlowDocumentProvider,
1532
- FlowNodeTransformData as FlowNodeTransformData3
1541
+ FlowNodeTransformData as FlowNodeTransformData4
1533
1542
  } from "@flowgram.ai/document";
1534
1543
  import { PlaygroundConfigEntity as PlaygroundConfigEntity3, TransformData as TransformData7 } from "@flowgram.ai/core";
1535
1544
  import {
@@ -1549,12 +1558,12 @@ var FreeLayout = class {
1549
1558
  * 更新布局
1550
1559
  */
1551
1560
  update() {
1552
- if (this.document.root.getData(FlowNodeTransformData3)?.localDirty) {
1561
+ if (this.document.root.getData(FlowNodeTransformData4)?.localDirty) {
1553
1562
  this.document.root.clearMemoGlobal();
1554
1563
  }
1555
1564
  }
1556
1565
  syncTransform(node) {
1557
- const transform = node.getData(FlowNodeTransformData3);
1566
+ const transform = node.getData(FlowNodeTransformData4);
1558
1567
  if (!transform.localDirty) {
1559
1568
  return;
1560
1569
  }
@@ -1568,7 +1577,7 @@ var FreeLayout = class {
1568
1577
  }
1569
1578
  node.parent.clearMemoGlobal();
1570
1579
  node.parent.clearMemoLocal();
1571
- const parentTransform = node.parent.getData(FlowNodeTransformData3);
1580
+ const parentTransform = node.parent.getData(FlowNodeTransformData4);
1572
1581
  parentTransform.transform.fireChange();
1573
1582
  }
1574
1583
  /**
@@ -1577,7 +1586,7 @@ var FreeLayout = class {
1577
1586
  */
1578
1587
  getPadding(node) {
1579
1588
  const { padding } = node.getNodeMeta();
1580
- const transform = node.getData(FlowNodeTransformData3);
1589
+ const transform = node.getData(FlowNodeTransformData4);
1581
1590
  if (padding) {
1582
1591
  return typeof padding === "function" ? padding(transform) : padding;
1583
1592
  }
@@ -1723,7 +1732,7 @@ var WorkflowDocument = class extends FlowDocument {
1723
1732
  const { formMeta } = registry;
1724
1733
  const meta = node.getNodeMeta();
1725
1734
  const formData = getFlowNodeFormData(node);
1726
- const transform = node.getData(FlowNodeTransformData4);
1735
+ const transform = node.getData(FlowNodeTransformData5);
1727
1736
  const freeLayout = this.layout;
1728
1737
  transform.onDataChange(() => {
1729
1738
  freeLayout.syncTransform(node);
@@ -1774,7 +1783,7 @@ var WorkflowDocument = class extends FlowDocument {
1774
1783
  if (!node.parent || node.parent.flowNodeType === FlowNodeBaseType.ROOT) {
1775
1784
  return;
1776
1785
  }
1777
- const parentTransform = node.parent.getData(FlowNodeTransformData4);
1786
+ const parentTransform = node.parent.getData(FlowNodeTransformData5);
1778
1787
  setTimeout(() => {
1779
1788
  parentTransform.fireChange();
1780
1789
  }, 0);
@@ -1841,6 +1850,7 @@ var WorkflowDocument = class extends FlowDocument {
1841
1850
  }
1842
1851
  return this.createWorkflowNode(
1843
1852
  {
1853
+ ...json,
1844
1854
  id,
1845
1855
  type,
1846
1856
  meta: { position, ...json?.meta },
@@ -1874,8 +1884,8 @@ var WorkflowDocument = class extends FlowDocument {
1874
1884
  }));
1875
1885
  const startNodeId = allNode.find((node) => node.isStart).id;
1876
1886
  const endNodeId = allNode.find((node) => node.isNodeEnd).id;
1877
- const nodeInSubCanvas = allNode.filter((node) => node.parent?.flowNodeType === FlowNodeBaseType.SUB_CANVAS).map((node) => node.id);
1878
- const associatedCache = /* @__PURE__ */ new Set([endNodeId, ...nodeInSubCanvas]);
1887
+ const nodeInContainer = allNode.filter((node) => node.parent?.getNodeMeta().isContainer).map((node) => node.id);
1888
+ const associatedCache = /* @__PURE__ */ new Set([endNodeId, ...nodeInContainer]);
1879
1889
  const bfs = (nodeId) => {
1880
1890
  if (associatedCache.has(nodeId)) {
1881
1891
  return;
@@ -2150,7 +2160,7 @@ var WorkflowDocument = class extends FlowDocument {
2150
2160
  }
2151
2161
  toLineJSON(line) {
2152
2162
  const lineJSON = line.toJSON();
2153
- if (!line.to || !line.info.to || !line.toPort) {
2163
+ if (!line.from || !line.info.from || !line.fromPort || !line.to || !line.info.to || !line.toPort) {
2154
2164
  return;
2155
2165
  }
2156
2166
  const fromSubCanvas = this.getNodeSubCanvas(line.from);
@@ -2268,18 +2278,19 @@ var WorkflowDragService = class {
2268
2278
  }
2269
2279
  /**
2270
2280
  * 拖拽选中节点
2271
- * @param event
2281
+ * @param triggerEvent
2272
2282
  */
2273
- startDragSelectedNodes(event) {
2283
+ startDragSelectedNodes(triggerEvent) {
2274
2284
  let { selectedNodes } = this.selectService;
2275
- if (selectedNodes.length === 0 || this.playgroundConfig.readonly || this.playgroundConfig.disabled) {
2285
+ if (selectedNodes.length === 0 || this.playgroundConfig.readonly || this.playgroundConfig.disabled || this.isDragging) {
2276
2286
  return Promise.resolve(false);
2277
2287
  }
2288
+ this.isDragging = true;
2278
2289
  const sameParent = this.childrenOfContainer(selectedNodes);
2279
2290
  if (sameParent && sameParent.flowNodeType !== FlowNodeBaseType2.ROOT) {
2280
2291
  selectedNodes = [sameParent];
2281
2292
  }
2282
- const { altKey } = event;
2293
+ const { altKey } = triggerEvent;
2283
2294
  let startPosition = this.getNodesPosition(selectedNodes);
2284
2295
  let startPositions = selectedNodes.map((node) => {
2285
2296
  const transform = node.getData(TransformData9);
@@ -2288,11 +2299,19 @@ var WorkflowDragService = class {
2288
2299
  let dragSuccess = false;
2289
2300
  const startTime = Date.now();
2290
2301
  const dragger = new PlaygroundDrag({
2291
- onDragStart: () => {
2292
- this.isDragging = true;
2302
+ onDragStart: (dragEvent) => {
2303
+ this._nodesDragEmitter.fire({
2304
+ type: "onDragStart",
2305
+ nodes: selectedNodes,
2306
+ startPositions,
2307
+ altKey,
2308
+ dragEvent,
2309
+ triggerEvent,
2310
+ dragger
2311
+ });
2293
2312
  },
2294
- onDrag: (e) => {
2295
- if (!dragSuccess && checkDragSuccess(Date.now() - startTime, e)) {
2313
+ onDrag: (dragEvent) => {
2314
+ if (!dragSuccess && checkDragSuccess(Date.now() - startTime, dragEvent)) {
2296
2315
  dragSuccess = true;
2297
2316
  if (altKey) {
2298
2317
  const tryCopyNodes = selectedNodes;
@@ -2315,10 +2334,11 @@ var WorkflowDragService = class {
2315
2334
  }
2316
2335
  }
2317
2336
  const offset = this.getDragPosOffset({
2318
- event: e,
2337
+ event: dragEvent,
2319
2338
  selectedNodes,
2320
2339
  startPosition
2321
2340
  });
2341
+ const positions = [];
2322
2342
  selectedNodes.forEach((node, index) => {
2323
2343
  const transform = node.getData(TransformData9);
2324
2344
  const nodeStartPosition = startPositions[index];
@@ -2328,26 +2348,40 @@ var WorkflowDragService = class {
2328
2348
  };
2329
2349
  if (node.collapsedChildren?.length > 0) {
2330
2350
  node.collapsedChildren.forEach((childNode) => {
2331
- const childNodeTransformData = childNode.getData(FlowNodeTransformData5);
2351
+ const childNodeTransformData = childNode.getData(FlowNodeTransformData6);
2332
2352
  childNodeTransformData.fireChange();
2333
2353
  });
2334
2354
  }
2335
2355
  transform.update({
2336
2356
  position: newPosition
2337
2357
  });
2358
+ positions.push(newPosition);
2359
+ });
2360
+ this._nodesDragEmitter.fire({
2361
+ type: "onDragging",
2362
+ nodes: selectedNodes,
2363
+ startPositions,
2364
+ positions,
2365
+ altKey,
2366
+ dragEvent,
2367
+ triggerEvent,
2368
+ dragger
2338
2369
  });
2339
2370
  },
2340
- onDragEnd: () => {
2371
+ onDragEnd: (dragEvent) => {
2341
2372
  this.isDragging = false;
2342
2373
  this._nodesDragEmitter.fire({
2343
2374
  type: "onDragEnd",
2344
2375
  nodes: selectedNodes,
2345
2376
  startPositions,
2346
- altKey
2377
+ altKey,
2378
+ dragEvent,
2379
+ triggerEvent,
2380
+ dragger
2347
2381
  });
2348
2382
  }
2349
2383
  });
2350
- return dragger.start(event.clientX, event.clientY, this.playgroundConfig).then(() => dragSuccess);
2384
+ return dragger.start(triggerEvent.clientX, triggerEvent.clientY, this.playgroundConfig)?.then(() => dragSuccess);
2351
2385
  }
2352
2386
  /**
2353
2387
  * 通过拖入卡片添加
@@ -2419,6 +2453,13 @@ var WorkflowDragService = class {
2419
2453
  },
2420
2454
  onDragEnd: async (e) => {
2421
2455
  const dropNode = this._dropNode;
2456
+ const { allowDrop } = this.canDropToNode({
2457
+ dragNodeType: type,
2458
+ dropNode
2459
+ });
2460
+ if (!allowDrop) {
2461
+ return this.clearDrop();
2462
+ }
2422
2463
  const dragNode = await this.dropCard(type, e, data, dropNode);
2423
2464
  this.clearDrop();
2424
2465
  if (dragNode) {
@@ -2472,6 +2513,22 @@ var WorkflowDragService = class {
2472
2513
  dispose: () => this.posAdjusters.delete(adjuster)
2473
2514
  };
2474
2515
  }
2516
+ /**
2517
+ * 判断是否可以放置节点
2518
+ */
2519
+ canDropToNode(params) {
2520
+ const { dragNodeType, dropNode } = params;
2521
+ if (!dragNodeType) {
2522
+ return {
2523
+ allowDrop: false,
2524
+ message: "Please select a node to drop"
2525
+ };
2526
+ }
2527
+ return {
2528
+ allowDrop: true,
2529
+ dropNode
2530
+ };
2531
+ }
2475
2532
  /**
2476
2533
  * 获取拖拽偏移
2477
2534
  */
@@ -2502,23 +2559,24 @@ var WorkflowDragService = class {
2502
2559
  return offset;
2503
2560
  }
2504
2561
  updateDroppableTransforms() {
2505
- this._droppableTransforms = this.document.getRenderDatas(FlowNodeTransformData5, false).filter((transform) => {
2562
+ this._droppableTransforms = this.document.getRenderDatas(FlowNodeTransformData6, false).filter((transform) => {
2506
2563
  const { entity } = transform;
2507
2564
  if (entity.originParent) {
2508
2565
  return this.nodeSelectable(entity) && this.nodeSelectable(entity.originParent);
2509
2566
  }
2510
2567
  return this.nodeSelectable(entity);
2511
- }).filter((transform) => {
2512
- const { entity } = transform;
2513
- return entity.flowNodeType === FlowNodeBaseType2.SUB_CANVAS;
2514
- });
2568
+ }).filter((transform) => this.isContainer(transform.entity));
2569
+ }
2570
+ /** 是否容器节点 */
2571
+ isContainer(node) {
2572
+ return node?.getNodeMeta().isContainer ?? false;
2515
2573
  }
2516
2574
  /**
2517
2575
  * 获取节点整体位置
2518
2576
  */
2519
2577
  getNodesPosition(nodes) {
2520
2578
  const selectedBounds = Rectangle8.enlarge(
2521
- nodes.map((n) => n.getData(FlowNodeTransformData5).bounds)
2579
+ nodes.map((n) => n.getData(FlowNodeTransformData6).bounds)
2522
2580
  );
2523
2581
  const position = {
2524
2582
  x: selectedBounds.x,
@@ -2568,7 +2626,7 @@ var WorkflowDragService = class {
2568
2626
  return {
2569
2627
  hasError: false
2570
2628
  };
2571
- } else if (toNode.flowNodeType === FlowNodeBaseType2.SUB_CANVAS) {
2629
+ } else if (this.isContainer(toNode)) {
2572
2630
  return {
2573
2631
  hasError: false
2574
2632
  };
@@ -2603,6 +2661,7 @@ var WorkflowDragService = class {
2603
2661
  if (originLine?.disabled || isFromInActivePort || this.playgroundConfig.readonly || this.playgroundConfig.disabled) {
2604
2662
  return { dragSuccess: false, newLine: void 0 };
2605
2663
  }
2664
+ this.selectService.clear();
2606
2665
  const config = this.playgroundConfig;
2607
2666
  const deferred = new PromiseDeferred();
2608
2667
  const preCursor = config.cursor;
@@ -2648,7 +2707,7 @@ var WorkflowDragService = class {
2648
2707
  type: "onDrag"
2649
2708
  });
2650
2709
  this.setLineColor(line, this.linesManager.lineColor.drawing);
2651
- if (toNode && toNode.flowNodeType !== FlowNodeBaseType2.SUB_CANVAS) {
2710
+ if (toNode && !this.isContainer(toNode)) {
2652
2711
  const portsData = toNode.getData(WorkflowNodePortsData);
2653
2712
  toPort = portsData.inputPorts[0];
2654
2713
  const { hasError } = this.handleDragOnNode(toNode, fromPort, line, toPort, originLine);
@@ -2796,13 +2855,13 @@ import { EntityManager as EntityManager3 } from "@flowgram.ai/core";
2796
2855
  import { DisposableCollection as DisposableCollection3, Emitter as Emitter6 } from "@flowgram.ai/utils";
2797
2856
 
2798
2857
  // src/utils/layout-to-positions.ts
2799
- import { FlowNodeTransformData as FlowNodeTransformData6 } from "@flowgram.ai/document";
2858
+ import { FlowNodeTransformData as FlowNodeTransformData7 } from "@flowgram.ai/document";
2800
2859
  import { TransformData as TransformData10, startTween } from "@flowgram.ai/core";
2801
2860
  var layoutToPositions = async (nodes, nodePositionMap) => {
2802
2861
  const newNodePositionMap = {};
2803
2862
  nodes.forEach((node) => {
2804
2863
  const transform = node.getData(TransformData10);
2805
- const nodeTransform = node.getData(FlowNodeTransformData6);
2864
+ const nodeTransform = node.getData(FlowNodeTransformData7);
2806
2865
  newNodePositionMap[node.id] = {
2807
2866
  x: transform.position.x,
2808
2867
  y: transform.position.y + nodeTransform.bounds.height / 2
@@ -2820,7 +2879,7 @@ var layoutToPositions = async (nodes, nodePositionMap) => {
2820
2879
  const deltaY = (nodePositionMap[node.id].y - transform.bounds.height / 2 - transform.position.y) * v.d / 100;
2821
2880
  if (node.collapsedChildren?.length > 0) {
2822
2881
  node.collapsedChildren.forEach((childNode) => {
2823
- const childNodeTransformData = childNode.getData(FlowNodeTransformData6);
2882
+ const childNodeTransformData = childNode.getData(FlowNodeTransformData7);
2824
2883
  childNodeTransformData.fireChange();
2825
2884
  });
2826
2885
  }
@@ -2899,6 +2958,41 @@ WorkflowResetLayoutService = __decorateClass([
2899
2958
  injectable7()
2900
2959
  ], WorkflowResetLayoutService);
2901
2960
 
2961
+ // src/service/workflow-operation-base-service.ts
2962
+ import { inject as inject8 } from "inversify";
2963
+ import { Emitter as Emitter7 } from "@flowgram.ai/utils";
2964
+ import { FlowOperationBaseServiceImpl } from "@flowgram.ai/document";
2965
+ import { TransformData as TransformData11 } from "@flowgram.ai/core";
2966
+ var WorkflowOperationBaseServiceImpl = class extends FlowOperationBaseServiceImpl {
2967
+ constructor() {
2968
+ super(...arguments);
2969
+ this.onNodePostionUpdateEmitter = new Emitter7();
2970
+ this.onNodePostionUpdate = this.onNodePostionUpdateEmitter.event;
2971
+ }
2972
+ updateNodePosition(nodeOrId, position) {
2973
+ const node = this.toNodeEntity(nodeOrId);
2974
+ if (!node) {
2975
+ return;
2976
+ }
2977
+ const transformData = node.getData(TransformData11);
2978
+ const oldPosition = {
2979
+ x: transformData.position.x,
2980
+ y: transformData.position.y
2981
+ };
2982
+ transformData.update({
2983
+ position
2984
+ });
2985
+ this.onNodePostionUpdateEmitter.fire({
2986
+ node,
2987
+ oldPosition,
2988
+ newPosition: position
2989
+ });
2990
+ }
2991
+ };
2992
+ __decorateClass([
2993
+ inject8(WorkflowDocument)
2994
+ ], WorkflowOperationBaseServiceImpl.prototype, "document", 2);
2995
+
2902
2996
  // src/hooks/use-playground-readonly-state.ts
2903
2997
  import { useEffect } from "react";
2904
2998
  import { usePlayground, useRefresh } from "@flowgram.ai/core";
@@ -2921,7 +3015,7 @@ function checkTargetDraggable(el) {
2921
3015
  }
2922
3016
  function useNodeRender(nodeFromProps) {
2923
3017
  const node = nodeFromProps || useContext(PlaygroundEntityContext);
2924
- const renderData = node.getData(FlowNodeRenderData2);
3018
+ const renderData = node.getData(FlowNodeRenderData3);
2925
3019
  const portsData = node.getData(WorkflowNodePortsData);
2926
3020
  const readonly = usePlaygroundReadonlyState();
2927
3021
  const dragService = useService(WorkflowDragService);
@@ -2951,7 +3045,7 @@ function useNodeRender(nodeFromProps) {
2951
3045
  return;
2952
3046
  }
2953
3047
  isDragging.current = true;
2954
- dragService.startDragSelectedNodes(e).finally(
3048
+ dragService.startDragSelectedNodes(e)?.finally(
2955
3049
  () => setTimeout(() => {
2956
3050
  isDragging.current = false;
2957
3051
  })
@@ -2964,7 +3058,7 @@ function useNodeRender(nodeFromProps) {
2964
3058
  if (isDragging.current) {
2965
3059
  return;
2966
3060
  }
2967
- if (e.metaKey || e.shiftKey || e.ctrlKey) {
3061
+ if (e.shiftKey) {
2968
3062
  selectionService.toggleSelect(node);
2969
3063
  } else {
2970
3064
  selectionService.selectNode(node);
@@ -3033,11 +3127,11 @@ function useNodeRender(nodeFromProps) {
3033
3127
  }
3034
3128
 
3035
3129
  // src/hooks/use-current-dom-node.ts
3036
- import { FlowNodeRenderData as FlowNodeRenderData3 } from "@flowgram.ai/document";
3130
+ import { FlowNodeRenderData as FlowNodeRenderData4 } from "@flowgram.ai/document";
3037
3131
  import { useEntityFromContext } from "@flowgram.ai/core";
3038
3132
  function useCurrentDomNode() {
3039
3133
  const entity = useEntityFromContext();
3040
- const renderData = entity.getData(FlowNodeRenderData3);
3134
+ const renderData = entity.getData(FlowNodeRenderData4);
3041
3135
  return renderData.node;
3042
3136
  }
3043
3137
 
@@ -3067,20 +3161,20 @@ var InteractiveType = /* @__PURE__ */ ((InteractiveType2) => {
3067
3161
 
3068
3162
  // src/workflow-document-container-module.ts
3069
3163
  import { ContainerModule } from "inversify";
3070
- import { FlowDocument as FlowDocument2, FlowDocumentContribution } from "@flowgram.ai/document";
3071
3164
  import { bindContributions } from "@flowgram.ai/utils";
3165
+ import { FlowDocument as FlowDocument2, FlowDocumentContribution } from "@flowgram.ai/document";
3072
3166
 
3073
3167
  // src/workflow-document-contribution.ts
3074
- import { injectable as injectable8, inject as inject8 } from "inversify";
3168
+ import { injectable as injectable8, inject as inject9 } from "inversify";
3075
3169
  import {
3076
- FlowNodeRenderData as FlowNodeRenderData4,
3077
- FlowNodeTransformData as FlowNodeTransformData7
3170
+ FlowNodeRenderData as FlowNodeRenderData5,
3171
+ FlowNodeTransformData as FlowNodeTransformData8
3078
3172
  } from "@flowgram.ai/document";
3079
3173
  var WorkflowDocumentContribution = class {
3080
3174
  registerDocument(document2) {
3081
3175
  document2.registerNodeDatas(
3082
- FlowNodeTransformData7,
3083
- FlowNodeRenderData4,
3176
+ FlowNodeTransformData8,
3177
+ FlowNodeRenderData5,
3084
3178
  WorkflowNodePortsData,
3085
3179
  WorkflowNodeLinesData
3086
3180
  );
@@ -3088,7 +3182,7 @@ var WorkflowDocumentContribution = class {
3088
3182
  }
3089
3183
  };
3090
3184
  __decorateClass([
3091
- inject8(FreeLayout)
3185
+ inject9(FreeLayout)
3092
3186
  ], WorkflowDocumentContribution.prototype, "freeLayout", 2);
3093
3187
  WorkflowDocumentContribution = __decorateClass([
3094
3188
  injectable8()
@@ -3113,6 +3207,7 @@ var WorkflowDocumentContainerModule = new ContainerModule(
3113
3207
  bind(WorkflowSelectService).toSelf().inSingletonScope();
3114
3208
  bind(WorkflowHoverService).toSelf().inSingletonScope();
3115
3209
  bind(WorkflowResetLayoutService).toSelf().inSingletonScope();
3210
+ bind(WorkflowOperationBaseService).to(WorkflowOperationBaseServiceImpl).inSingletonScope();
3116
3211
  bind(URLParams).toDynamicValue(() => getUrlParams()).inSingletonScope();
3117
3212
  bindContributions(bind, WorkflowDocumentContribution, [FlowDocumentContribution]);
3118
3213
  bind(WorkflowDocumentOptions).toConstantValue({
@@ -3222,6 +3317,8 @@ export {
3222
3317
  WorkflowNodeEntity,
3223
3318
  WorkflowNodeLinesData,
3224
3319
  WorkflowNodePortsData,
3320
+ WorkflowOperationBaseService,
3321
+ WorkflowOperationBaseServiceImpl,
3225
3322
  WorkflowPortEntity,
3226
3323
  WorkflowResetLayoutService,
3227
3324
  WorkflowSelectService,