@flowgram.ai/free-snap-plugin 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.
package/dist/esm/index.js CHANGED
@@ -14,12 +14,12 @@ import { definePluginCreator } from "@flowgram.ai/core";
14
14
 
15
15
  // src/service.ts
16
16
  import { inject, injectable } from "inversify";
17
+ import { Emitter, Rectangle } from "@flowgram.ai/utils";
18
+ import { WorkflowNodeEntity, WorkflowDocument } from "@flowgram.ai/free-layout-core";
19
+ import { WorkflowDragService } from "@flowgram.ai/free-layout-core";
17
20
  import { FlowNodeTransformData } from "@flowgram.ai/document";
18
21
  import { FlowNodeBaseType } from "@flowgram.ai/document";
19
22
  import { EntityManager, PlaygroundConfigEntity, TransformData } from "@flowgram.ai/core";
20
- import { WorkflowNodeEntity, WorkflowDocument } from "@flowgram.ai/free-layout-core";
21
- import { WorkflowDragService } from "@flowgram.ai/free-layout-core";
22
- import { Emitter, Rectangle } from "@flowgram.ai/utils";
23
23
 
24
24
  // src/constant.ts
25
25
  var SnapDefaultOptions = {
@@ -65,6 +65,7 @@ var WorkflowSnapService = class {
65
65
  this.disposers = [];
66
66
  this.snapEmitter = new Emitter();
67
67
  this.onSnap = this.snapEmitter.event;
68
+ this._disabled = false;
68
69
  }
69
70
  init(params = {}) {
70
71
  this.options = {
@@ -76,15 +77,40 @@ var WorkflowSnapService = class {
76
77
  dispose() {
77
78
  this.disposers.forEach((disposer) => disposer.dispose());
78
79
  }
80
+ get disabled() {
81
+ return this._disabled;
82
+ }
83
+ disable() {
84
+ if (this._disabled) {
85
+ return;
86
+ }
87
+ this._disabled = true;
88
+ this.clear();
89
+ }
90
+ enable() {
91
+ if (!this._disabled) {
92
+ return;
93
+ }
94
+ this._disabled = false;
95
+ this.clear();
96
+ }
79
97
  mountListener() {
80
- const dragAdjusterDisposer = this.dragService.registerPosAdjuster(
81
- (params) => this.snapping({
82
- targetNodes: params.selectedNodes,
83
- position: params.position
84
- })
85
- );
98
+ const dragAdjusterDisposer = this.dragService.registerPosAdjuster((params) => {
99
+ const { selectedNodes: targetNodes, position } = params;
100
+ const isMultiSnapping = this.options.enableMultiSnapping ? false : targetNodes.length !== 1;
101
+ if (this._disabled || !this.options.enableEdgeSnapping || isMultiSnapping) {
102
+ return {
103
+ x: 0,
104
+ y: 0
105
+ };
106
+ }
107
+ return this.snapping({
108
+ targetNodes,
109
+ position
110
+ });
111
+ });
86
112
  const dragEndDisposer = this.dragService.onNodesDrag((event) => {
87
- if (event.type !== "onDragEnd") {
113
+ if (event.type !== "onDragEnd" || this._disabled) {
88
114
  return;
89
115
  }
90
116
  if (this.options.enableGridSnapping) {
@@ -101,19 +127,12 @@ var WorkflowSnapService = class {
101
127
  }
102
128
  snapping(params) {
103
129
  const { targetNodes, position } = params;
104
- const isMultiSnapping = this.options.enableMultiSnapping ? false : targetNodes.length !== 1;
105
- if (!this.options.enableEdgeSnapping || isMultiSnapping) {
106
- return {
107
- x: 0,
108
- y: 0
109
- };
110
- }
111
- const selectedBounds = this.getBounds(targetNodes);
130
+ const targetBounds = this.getBounds(targetNodes);
112
131
  const targetRect = new Rectangle(
113
132
  position.x,
114
133
  position.y,
115
- selectedBounds.width,
116
- selectedBounds.height
134
+ targetBounds.width,
135
+ targetBounds.height
117
136
  );
118
137
  const snapNodeRects = this.getSnapNodeRects({
119
138
  targetNodes,
@@ -580,10 +599,10 @@ WorkflowSnapService = __decorateClass([
580
599
  // src/layer.tsx
581
600
  import React from "react";
582
601
  import { inject as inject2, injectable as injectable2 } from "inversify";
602
+ import { domUtils } from "@flowgram.ai/utils";
603
+ import { WorkflowDocument as WorkflowDocument2 } from "@flowgram.ai/free-layout-core";
583
604
  import { FlowNodeTransformData as FlowNodeTransformData2 } from "@flowgram.ai/document";
584
605
  import { Layer } from "@flowgram.ai/core";
585
- import { WorkflowDocument as WorkflowDocument2 } from "@flowgram.ai/free-layout-core";
586
- import { domUtils } from "@flowgram.ai/utils";
587
606
  var WorkflowSnapLayer = class extends Layer {
588
607
  constructor() {
589
608
  super(...arguments);
@@ -621,7 +640,7 @@ var WorkflowSnapLayer = class extends Layer {
621
640
  className: `workflow-snap-edge-line ${className}`,
622
641
  "data-testid": "sdk.workflow.canvas.snap.edgeLine",
623
642
  "data-snap-line-id": id,
624
- "data-snap-line-sourceNode": sourceNode,
643
+ "data-snap-line-source-node": sourceNode,
625
644
  key: id,
626
645
  style: {
627
646
  top,
@@ -650,7 +669,7 @@ var WorkflowSnapLayer = class extends Layer {
650
669
  className: `workflow-snap-align-line ${renderLine.className}`,
651
670
  "data-testid": "sdk.workflow.canvas.snap.alignLine",
652
671
  "data-snap-line-id": id,
653
- "data-snap-line-sourceNode": renderLine.sourceNode,
672
+ "data-snap-line-source-node": renderLine.sourceNode,
654
673
  key: id,
655
674
  style: {
656
675
  position: "absolute"
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/create-plugin.ts","../../src/service.ts","../../src/constant.ts","../../src/utils.ts","../../src/layer.tsx"],"sourcesContent":["import { definePluginCreator } from '@flowgram.ai/core';\n\nimport {\n FreeSnapPluginOptions,\n WorkflowSnapLayerOptions,\n WorkflowSnapServiceOptions,\n} from './type';\nimport { WorkflowSnapService } from './service';\nimport { WorkflowSnapLayer } from './layer';\nimport { SnapDefaultOptions } from './constant';\n\nexport const createFreeSnapPlugin = definePluginCreator<FreeSnapPluginOptions>({\n onBind({ bind }) {\n bind(WorkflowSnapService).toSelf().inSingletonScope();\n },\n onInit(ctx, opts) {\n const options: WorkflowSnapServiceOptions & WorkflowSnapLayerOptions = {\n ...SnapDefaultOptions,\n ...opts,\n };\n ctx.playground.registerLayer(WorkflowSnapLayer, options);\n const snapService = ctx.get<WorkflowSnapService>(WorkflowSnapService);\n snapService.init(options);\n },\n onDispose(ctx) {\n const snapService = ctx.get<WorkflowSnapService>(WorkflowSnapService);\n snapService.dispose();\n },\n});\n","import { inject, injectable } from 'inversify';\nimport { FlowNodeTransformData } from '@flowgram.ai/document';\nimport { FlowNodeBaseType } from '@flowgram.ai/document';\nimport { EntityManager, PlaygroundConfigEntity, TransformData } from '@flowgram.ai/core';\nimport { WorkflowNodeEntity, WorkflowDocument } from '@flowgram.ai/free-layout-core';\nimport { WorkflowDragService } from '@flowgram.ai/free-layout-core';\nimport { Disposable, Emitter, Rectangle } from '@flowgram.ai/utils';\nimport { IPoint } from '@flowgram.ai/utils';\n\nimport { isEqual, isGreaterThan, isLessThan, isLessThanOrEqual, isNumber } from './utils';\nimport type {\n SnapEvent,\n SnapHorizontalLine,\n SnapLines,\n SnapMidHorizontalLine,\n SnapMidVerticalLine,\n SnapVerticalLine,\n WorkflowSnapServiceOptions,\n AlignRects,\n AlignRect,\n AlignSpacing,\n SnapNodeRect,\n SnapEdgeLines,\n} from './type';\nimport { SnapDefaultOptions } from './constant';\n\n@injectable()\nexport class WorkflowSnapService {\n @inject(WorkflowDocument) private readonly document: WorkflowDocument;\n\n @inject(EntityManager) private readonly entityManager: EntityManager;\n\n @inject(WorkflowDragService)\n private readonly dragService: WorkflowDragService;\n\n @inject(PlaygroundConfigEntity)\n private readonly playgroundConfig: PlaygroundConfigEntity;\n\n private disposers: Disposable[] = [];\n\n private options: WorkflowSnapServiceOptions;\n\n private snapEmitter = new Emitter<SnapEvent>();\n\n public readonly onSnap = this.snapEmitter.event;\n\n public init(params: Partial<WorkflowSnapServiceOptions> = {}): void {\n this.options = {\n ...SnapDefaultOptions,\n ...params,\n };\n this.mountListener();\n }\n\n public dispose(): void {\n this.disposers.forEach(disposer => disposer.dispose());\n }\n\n private mountListener(): void {\n const dragAdjusterDisposer = this.dragService.registerPosAdjuster(params =>\n this.snapping({\n targetNodes: params.selectedNodes,\n position: params.position,\n }),\n );\n const dragEndDisposer = this.dragService.onNodesDrag(event => {\n if (event.type !== 'onDragEnd') {\n return;\n }\n if (this.options.enableGridSnapping) {\n this.gridSnapping({\n targetNodes: event.nodes,\n gridSize: this.options.gridSize,\n });\n }\n if (this.options.enableEdgeSnapping) {\n this.clear();\n }\n });\n this.disposers.push(dragAdjusterDisposer, dragEndDisposer);\n }\n\n private snapping(params: { targetNodes: WorkflowNodeEntity[]; position: IPoint }): IPoint {\n const { targetNodes: targetNodes, position } = params;\n\n const isMultiSnapping = this.options.enableMultiSnapping ? false : targetNodes.length !== 1;\n\n if (!this.options.enableEdgeSnapping || isMultiSnapping) {\n return {\n x: 0,\n y: 0,\n };\n }\n\n const selectedBounds = this.getBounds(targetNodes);\n\n const targetRect = new Rectangle(\n position.x,\n position.y,\n selectedBounds.width,\n selectedBounds.height,\n );\n\n const snapNodeRects = this.getSnapNodeRects({\n targetNodes,\n targetRect,\n });\n\n const { alignOffset, alignRects, alignSpacing } = this.calcAlignOffset({\n targetRect,\n alignThreshold: this.options.edgeThreshold,\n snapNodeRects,\n });\n\n const { snapOffset, snapEdgeLines } = this.calcSnapOffset({\n targetRect,\n edgeThreshold: this.options.edgeThreshold,\n snapNodeRects,\n });\n\n const offset: IPoint = {\n x: snapOffset.x || alignOffset.x,\n y: snapOffset.y || alignOffset.y,\n };\n\n const snapRect = new Rectangle(\n position.x + offset.x,\n position.y + offset.y,\n targetRect.width,\n targetRect.height,\n );\n\n this.snapEmitter.fire({\n snapRect,\n snapEdgeLines,\n alignRects,\n alignSpacing,\n });\n\n return offset;\n }\n\n private calcSnapOffset(params: {\n snapNodeRects: SnapNodeRect[];\n targetRect: Rectangle;\n edgeThreshold: number;\n }): {\n snapOffset: IPoint;\n snapEdgeLines: SnapEdgeLines;\n } {\n const { snapNodeRects, edgeThreshold, targetRect } = params;\n\n const snapLines = this.getSnapLines({\n snapNodeRects,\n });\n\n // 找到最近的线条\n const topYClosestLine = snapLines.horizontal.find(line =>\n isLessThanOrEqual(Math.abs(line.y - targetRect.top), edgeThreshold),\n );\n const bottomYClosestLine = snapLines.horizontal.find(line =>\n isLessThanOrEqual(Math.abs(line.y - targetRect.bottom), edgeThreshold),\n );\n const leftXClosestLine = snapLines.vertical.find(line =>\n isLessThanOrEqual(Math.abs(line.x - targetRect.left), edgeThreshold),\n );\n const rightXClosestLine = snapLines.vertical.find(line =>\n isLessThanOrEqual(Math.abs(line.x - targetRect.right), edgeThreshold),\n );\n const midYClosestLine = snapLines.midHorizontal.find(line =>\n isLessThanOrEqual(Math.abs(line.y - targetRect.center.y), edgeThreshold),\n );\n const midXClosestLine = snapLines.midVertical.find(line =>\n isLessThanOrEqual(Math.abs(line.x - targetRect.center.x), edgeThreshold),\n );\n\n // 计算最近坐标\n const topYClosest = topYClosestLine?.y;\n const bottomYClosest = isNumber(bottomYClosestLine?.y)\n ? bottomYClosestLine!.y - targetRect.height\n : undefined;\n const leftXClosest = leftXClosestLine?.x;\n const rightXClosest = isNumber(rightXClosestLine?.x)\n ? rightXClosestLine!.x - targetRect.width\n : undefined;\n const midYClosest = isNumber(midYClosestLine?.y)\n ? midYClosestLine!.y - targetRect.height / 2\n : undefined;\n const midXClosest = isNumber(midXClosestLine?.x)\n ? midXClosestLine!.x - targetRect.width / 2\n : undefined;\n\n // 吸附后坐标,按优先级取值\n const snappingPosition = {\n x: midXClosest ?? leftXClosest ?? rightXClosest ?? targetRect.x,\n y: midYClosest ?? topYClosest ?? bottomYClosest ?? targetRect.y,\n };\n\n // 吸附修正偏移量\n const snapOffset: IPoint = {\n x: snappingPosition.x - targetRect.x,\n y: snappingPosition.y - targetRect.y,\n };\n\n // 生效的吸附线条\n const snapEdgeLines: SnapEdgeLines = {\n top: isEqual(topYClosest, snappingPosition.y) ? topYClosestLine : undefined,\n bottom: isEqual(bottomYClosest, snappingPosition.y) ? bottomYClosestLine : undefined,\n left: isEqual(leftXClosest, snappingPosition.x) ? leftXClosestLine : undefined,\n right: isEqual(rightXClosest, snappingPosition.x) ? rightXClosestLine : undefined,\n midVertical: isEqual(midXClosest, snappingPosition.x) ? midXClosestLine : undefined,\n midHorizontal: isEqual(midYClosest, snappingPosition.y) ? midYClosestLine : undefined,\n };\n\n return { snapOffset, snapEdgeLines };\n }\n\n private gridSnapping(params: { gridSize: number; targetNodes: WorkflowNodeEntity[] }): void {\n const { gridSize, targetNodes } = params;\n const rect = this.getBounds(targetNodes);\n const snap = (value: number) => Math.round(value / gridSize) * gridSize;\n const snappedPosition: IPoint = {\n x: snap(rect.x),\n y: snap(rect.y),\n };\n const offset: IPoint = {\n x: snappedPosition.x - rect.x,\n y: snappedPosition.y - rect.y,\n };\n targetNodes.forEach(node =>\n this.updateNodePositionWithOffset({\n node,\n offset,\n }),\n );\n }\n\n private clear() {\n this.snapEmitter.fire({\n snapEdgeLines: {},\n snapRect: Rectangle.EMPTY,\n alignRects: {\n top: [],\n bottom: [],\n left: [],\n right: [],\n },\n alignSpacing: {},\n });\n }\n\n private getSnapLines(params: { snapNodeRects: SnapNodeRect[] }): SnapLines {\n const { snapNodeRects } = params;\n const horizontalLines: SnapHorizontalLine[] = [];\n const verticalLines: SnapVerticalLine[] = [];\n const midHorizontalLines: SnapMidHorizontalLine[] = [];\n const midVerticalLines: SnapMidVerticalLine[] = [];\n\n snapNodeRects.forEach(snapNodeRect => {\n const nodeBounds = snapNodeRect.rect;\n const nodeCenter = nodeBounds.center;\n // 边缘横线\n const top: SnapHorizontalLine = {\n y: nodeBounds.top,\n sourceNodeId: snapNodeRect.id,\n };\n const bottom: SnapHorizontalLine = {\n y: nodeBounds.bottom,\n sourceNodeId: snapNodeRect.id,\n };\n // 边缘竖线\n const left: SnapVerticalLine = {\n x: nodeBounds.left,\n sourceNodeId: snapNodeRect.id,\n };\n const right: SnapVerticalLine = {\n x: nodeBounds.right,\n sourceNodeId: snapNodeRect.id,\n };\n // 中间横线\n const midHorizontal: SnapMidHorizontalLine = {\n y: nodeCenter.y,\n sourceNodeId: snapNodeRect.id,\n };\n // 中间竖线\n const midVertical: SnapMidVerticalLine = {\n x: nodeCenter.x,\n sourceNodeId: snapNodeRect.id,\n };\n horizontalLines.push(top, bottom);\n verticalLines.push(left, right);\n midHorizontalLines.push(midHorizontal);\n midVerticalLines.push(midVertical);\n });\n\n return {\n horizontal: horizontalLines,\n vertical: verticalLines,\n midHorizontal: midHorizontalLines,\n midVertical: midVerticalLines,\n };\n }\n\n private getAvailableNodes(params: {\n targetNodes: WorkflowNodeEntity[];\n targetRect: Rectangle;\n }): WorkflowNodeEntity[] {\n const { targetNodes, targetRect } = params;\n\n const targetCenter = targetRect.center;\n const targetContainerId = targetNodes[0].parent?.id ?? this.document.root.id;\n\n const disabledNodeIds = targetNodes.map(n => n.id);\n disabledNodeIds.push(FlowNodeBaseType.ROOT);\n const availableNodes = this.nodes\n .filter(n => n.parent?.id === targetContainerId)\n .filter(n => !disabledNodeIds.includes(n.id))\n .sort((nodeA, nodeB) => {\n const nodeCenterA = nodeA.getData(FlowNodeTransformData)!.bounds.center;\n const nodeCenterB = nodeB.getData(FlowNodeTransformData)!.bounds.center;\n // 距离越近优先级越高\n const distanceA =\n Math.abs(nodeCenterA.x - targetCenter.x) + Math.abs(nodeCenterA.y - targetCenter.y);\n const distanceB =\n Math.abs(nodeCenterB.x - targetCenter.x) + Math.abs(nodeCenterB.y - targetCenter.y);\n return distanceA - distanceB;\n });\n return availableNodes;\n }\n\n private viewRect(): Rectangle {\n const { width, height, scrollX, scrollY, zoom } = this.playgroundConfig.config;\n return new Rectangle(scrollX / zoom, scrollY / zoom, width / zoom, height / zoom);\n }\n\n private getSnapNodeRects(params: {\n targetNodes: WorkflowNodeEntity[];\n targetRect: Rectangle;\n }): SnapNodeRect[] {\n const availableNodes = this.getAvailableNodes(params);\n const viewRect = this.viewRect();\n return availableNodes\n .map(node => {\n const snapNodeRect: SnapNodeRect = {\n id: node.id,\n rect: node.getData(FlowNodeTransformData).bounds,\n entity: node,\n };\n if (\n this.options.enableOnlyViewportSnapping &&\n node.parent?.flowNodeType === FlowNodeBaseType.ROOT &&\n !Rectangle.intersects(viewRect, snapNodeRect.rect)\n ) {\n // 最外层节点仅包含当前可见节点\n return;\n }\n return snapNodeRect;\n })\n .filter(Boolean) as SnapNodeRect[];\n }\n\n private get nodes(): WorkflowNodeEntity[] {\n return this.entityManager.getEntities<WorkflowNodeEntity>(WorkflowNodeEntity);\n }\n\n private getBounds(nodes: WorkflowNodeEntity[]): Rectangle {\n if (nodes.length === 0) {\n return Rectangle.EMPTY;\n }\n return Rectangle.enlarge(nodes.map(n => n.getData(FlowNodeTransformData)!.bounds));\n }\n\n private updateNodePositionWithOffset(params: { node: WorkflowNodeEntity; offset: IPoint }): void {\n const { node, offset } = params;\n const transform = node.getData(TransformData);\n const positionWithOffset: IPoint = {\n x: transform.position.x + offset.x,\n y: transform.position.y + offset.y,\n };\n if (node.collapsedChildren?.length > 0) {\n // 嵌套情况下需将子节点 transform 设为 dirty\n node.collapsedChildren.forEach(childNode => {\n const childNodeTransformData =\n childNode.getData<FlowNodeTransformData>(FlowNodeTransformData);\n childNodeTransformData.fireChange();\n });\n }\n transform.update({\n position: positionWithOffset,\n });\n }\n\n private calcAlignOffset(params: {\n snapNodeRects: SnapNodeRect[];\n targetRect: Rectangle;\n alignThreshold: number;\n }): {\n alignOffset: IPoint;\n alignRects: AlignRects;\n alignSpacing: AlignSpacing;\n } {\n const { snapNodeRects, targetRect, alignThreshold } = params;\n\n const alignRects = this.getAlignRects({\n targetRect,\n snapNodeRects,\n });\n\n const alignSpacing = this.calcAlignSpacing({\n targetRect,\n alignRects,\n });\n\n let topY: number | undefined;\n let bottomY: number | undefined;\n let leftX: number | undefined;\n let rightX: number | undefined;\n let midY: number | undefined;\n let midX: number | undefined;\n\n if (alignSpacing.top) {\n const topAlignY = alignRects.top[0].rect.bottom + alignSpacing.top;\n const isAlignTop = isLessThanOrEqual(Math.abs(targetRect.top - topAlignY), alignThreshold);\n if (isAlignTop) {\n // 生效\n topY = topAlignY;\n } else {\n // 失效\n alignSpacing.top = undefined;\n }\n }\n if (alignSpacing.bottom) {\n const bottomAlignY = alignRects.bottom[0].rect.top - alignSpacing.bottom;\n const isAlignBottom = isLessThan(Math.abs(targetRect.bottom - bottomAlignY), alignThreshold);\n if (isAlignBottom) {\n bottomY = bottomAlignY - targetRect.height;\n } else {\n alignSpacing.bottom = undefined;\n }\n }\n if (alignSpacing.left) {\n const leftAlignX = alignRects.left[0].rect.right + alignSpacing.left;\n const isAlignLeft = isLessThanOrEqual(Math.abs(targetRect.left - leftAlignX), alignThreshold);\n if (isAlignLeft) {\n leftX = leftAlignX;\n } else {\n alignSpacing.left = undefined;\n }\n }\n if (alignSpacing.right) {\n const rightAlignX = alignRects.right[0].rect.left - alignSpacing.right;\n const isAlignRight = isLessThanOrEqual(\n Math.abs(targetRect.right - rightAlignX),\n alignThreshold,\n );\n if (isAlignRight) {\n rightX = rightAlignX - targetRect.width;\n } else {\n alignSpacing.right = undefined;\n }\n }\n if (alignSpacing.midHorizontal) {\n const leftAlignX = alignRects.left[0].rect.right + alignSpacing.midHorizontal;\n const isAlignMidHorizontal = isLessThanOrEqual(\n Math.abs(targetRect.left - leftAlignX),\n alignThreshold,\n );\n if (isAlignMidHorizontal) {\n midX = leftAlignX;\n } else {\n alignSpacing.midHorizontal = undefined;\n }\n }\n if (alignSpacing.midVertical) {\n const topAlignY = alignRects.top[0].rect.bottom + alignSpacing.midVertical;\n const isAlignMidVertical = isLessThanOrEqual(\n Math.abs(targetRect.top - topAlignY),\n alignThreshold,\n );\n if (isAlignMidVertical) {\n midY = topAlignY;\n } else {\n alignSpacing.midVertical = undefined;\n }\n }\n\n const alignPosition: IPoint = {\n x: midX ?? leftX ?? rightX ?? targetRect.x,\n y: midY ?? topY ?? bottomY ?? targetRect.y,\n };\n\n const alignOffset: IPoint = {\n x: alignPosition.x - targetRect.x,\n y: alignPosition.y - targetRect.y,\n };\n\n return { alignOffset, alignRects, alignSpacing };\n }\n\n private calcAlignSpacing(params: {\n targetRect: Rectangle;\n alignRects: AlignRects;\n }): AlignSpacing {\n const { targetRect, alignRects } = params;\n\n const topSpacing = this.getDirectionAlignSpacing({\n rects: alignRects.top,\n isHorizontal: false,\n });\n const bottomSpacing = this.getDirectionAlignSpacing({\n rects: alignRects.bottom,\n isHorizontal: false,\n });\n const leftSpacing = this.getDirectionAlignSpacing({\n rects: alignRects.left,\n isHorizontal: true,\n });\n const rightSpacing = this.getDirectionAlignSpacing({\n rects: alignRects.right,\n isHorizontal: true,\n });\n const midHorizontalSpacing = this.getMidAlignSpacing({\n rectA: alignRects.left[0]?.rect,\n rectB: alignRects.right[0]?.rect,\n targetRect,\n isHorizontal: true,\n });\n const midVerticalSpacing = this.getMidAlignSpacing({\n rectA: alignRects.top[0]?.rect,\n rectB: alignRects.bottom[0]?.rect,\n targetRect,\n isHorizontal: false,\n });\n return {\n top: topSpacing,\n bottom: bottomSpacing,\n left: leftSpacing,\n right: rightSpacing,\n midHorizontal: midHorizontalSpacing,\n midVertical: midVerticalSpacing,\n };\n }\n\n private getAlignRects(params: {\n targetRect: Rectangle;\n snapNodeRects: SnapNodeRect[];\n }): AlignRects {\n const { targetRect, snapNodeRects } = params;\n\n const topVerticalRects: AlignRect[] = [];\n const bottomVerticalRects: AlignRect[] = [];\n const leftHorizontalRects: AlignRect[] = [];\n const rightHorizontalRects: AlignRect[] = [];\n\n snapNodeRects.forEach(snapNodeRect => {\n const nodeRect = snapNodeRect.rect;\n const { isVerticalIntersection, isHorizontalIntersection, isIntersection } =\n this.intersection(nodeRect, targetRect);\n if (isIntersection) {\n // 忽略重叠的节点\n return;\n } else if (isVerticalIntersection) {\n // 垂直重合\n if (isGreaterThan(nodeRect.center.y, targetRect.center.y)) {\n // 下方\n bottomVerticalRects.push({\n rect: nodeRect,\n sourceNodeId: snapNodeRect.id,\n });\n } else {\n // 上方\n topVerticalRects.push({\n rect: nodeRect,\n sourceNodeId: snapNodeRect.id,\n });\n }\n } else if (isHorizontalIntersection) {\n // 水平重合\n if (isGreaterThan(nodeRect.center.x, targetRect.center.x)) {\n // 右方\n rightHorizontalRects.push({\n rect: nodeRect,\n sourceNodeId: snapNodeRect.id,\n });\n } else {\n // 左方\n leftHorizontalRects.push({\n rect: nodeRect,\n sourceNodeId: snapNodeRect.id,\n });\n }\n }\n });\n\n return {\n top: topVerticalRects,\n bottom: bottomVerticalRects,\n left: leftHorizontalRects,\n right: rightHorizontalRects,\n };\n }\n\n private getMidAlignSpacing(params: {\n rectA?: Rectangle;\n rectB?: Rectangle;\n targetRect: Rectangle;\n isHorizontal: boolean;\n }): number | undefined {\n const { rectA, rectB, targetRect, isHorizontal } = params;\n if (!rectA || !rectB) {\n return;\n }\n const { isVerticalIntersection, isHorizontalIntersection, isIntersection } = this.intersection(\n rectA,\n rectB,\n );\n if (isIntersection) {\n return;\n }\n if (isHorizontal && isHorizontalIntersection && !isVerticalIntersection) {\n const betweenSpacing = Math.min(\n Math.abs(rectA.left - rectB.right),\n Math.abs(rectA.right - rectB.left),\n );\n return (betweenSpacing - targetRect.width) / 2;\n } else if (!isHorizontal && isVerticalIntersection && !isHorizontalIntersection) {\n const betweenSpacing = Math.min(\n Math.abs(rectA.top - rectB.bottom),\n Math.abs(rectA.bottom - rectB.top),\n );\n return (betweenSpacing - targetRect.height) / 2;\n }\n }\n\n private getDirectionAlignSpacing(params: {\n rects: AlignRect[];\n isHorizontal: boolean;\n }): number | undefined {\n const { rects, isHorizontal } = params;\n if (rects.length < 2) {\n // 非法情况\n return;\n }\n const rectA = rects[0].rect;\n const rectB = rects[1].rect;\n\n const { isVerticalIntersection, isHorizontalIntersection, isIntersection } = this.intersection(\n rectA,\n rectB,\n );\n\n if (isIntersection) {\n // 非法情况:重叠\n return;\n }\n if (isHorizontal && isHorizontalIntersection && !isVerticalIntersection) {\n return Math.min(Math.abs(rectA.left - rectB.right), Math.abs(rectA.right - rectB.left));\n } else if (!isHorizontal && isVerticalIntersection && !isHorizontalIntersection) {\n return Math.min(Math.abs(rectA.top - rectB.bottom), Math.abs(rectA.bottom - rectB.top));\n }\n return;\n }\n\n private intersection(\n rectA: Rectangle,\n rectB: Rectangle,\n ): {\n isHorizontalIntersection: boolean;\n isVerticalIntersection: boolean;\n isIntersection: boolean;\n } {\n const isVerticalIntersection =\n isLessThan(rectA.left, rectB.right) && isGreaterThan(rectA.right, rectB.left);\n const isHorizontalIntersection =\n isLessThan(rectA.top, rectB.bottom) && isGreaterThan(rectA.bottom, rectB.top);\n const isIntersection = isHorizontalIntersection && isVerticalIntersection;\n\n return {\n isHorizontalIntersection,\n isVerticalIntersection,\n isIntersection,\n };\n }\n}\n","import type { WorkflowSnapLayerOptions, WorkflowSnapServiceOptions } from './type';\n\nexport const SnapDefaultOptions: WorkflowSnapServiceOptions & WorkflowSnapLayerOptions = {\n enableEdgeSnapping: true,\n edgeThreshold: 7,\n enableGridSnapping: false,\n gridSize: 20,\n enableMultiSnapping: false,\n enableOnlyViewportSnapping: true,\n edgeColor: '#4E40E5',\n alignColor: '#4E40E5',\n edgeLineWidth: 2,\n alignLineWidth: 2,\n alignCrossWidth: 16,\n};\n\nexport const Epsilon = 0.00001;\n","import { Epsilon } from './constant';\n\n/** 检查浮点数 a 是否等于 b */\nexport const isEqual = (a: number | undefined, b: number | undefined): boolean => {\n if (a === undefined || b === undefined) {\n return false;\n }\n // 检查 a 和 b 的差的绝对值是否小于 Epsilon\n return Math.abs(a - b) < Epsilon;\n};\n\n/** 检查浮点数 a 是否小于 b */\nexport const isLessThan = (a: number | undefined, b: number | undefined): boolean => {\n if (a === undefined || b === undefined) {\n return false;\n }\n // 检查 a 是否显著小于 b\n return b - a > Epsilon;\n};\n\n/** 检查浮点数 a 是否大于 b */\nexport const isGreaterThan = (a: number | undefined, b: number | undefined): boolean => {\n if (a === undefined || b === undefined) {\n return false;\n }\n return a - b > Epsilon;\n};\n\n/** 检查浮点数 a 是否小于等于 b */\nexport const isLessThanOrEqual = (a: number | undefined, b: number | undefined): boolean =>\n isEqual(a, b) || isLessThan(a, b);\n\n/** 检查浮点数 a 是否大于等于 b */\nexport const isGreaterThanOrEqual = (a: number | undefined, b: number | undefined): boolean =>\n isEqual(a, b) || isGreaterThan(a, b);\n\n/** 检查值是否是数字类型 */\nexport const isNumber = (value: unknown): value is number =>\n typeof value === 'number' && !isNaN(value);\n","import React from 'react';\n\nimport { inject, injectable } from 'inversify';\nimport { FlowNodeTransformData } from '@flowgram.ai/document';\nimport { Layer } from '@flowgram.ai/core';\nimport { WorkflowDocument } from '@flowgram.ai/free-layout-core';\nimport { domUtils } from '@flowgram.ai/utils';\nimport { Rectangle } from '@flowgram.ai/utils';\n\nimport { isEqual, isGreaterThan, isNumber } from './utils';\nimport { AlignRect, SnapEvent, WorkflowSnapLayerOptions } from './type';\nimport { WorkflowSnapService } from './service';\n\ninterface SnapRenderLine {\n className: string;\n sourceNode: string;\n top: number;\n left: number;\n width: number;\n height: number;\n dashed?: boolean;\n}\n\n@injectable()\nexport class WorkflowSnapLayer extends Layer<WorkflowSnapLayerOptions> {\n public static type = 'WorkflowSnapLayer';\n\n @inject(WorkflowDocument) private readonly document: WorkflowDocument;\n\n @inject(WorkflowSnapService) private readonly service: WorkflowSnapService;\n\n public readonly node = domUtils.createDivWithClass(\n 'gedit-playground-layer gedit-flow-snap-layer',\n );\n\n private edgeLines: SnapRenderLine[] = [];\n\n private alignLines: SnapRenderLine[] = [];\n\n public onReady(): void {\n this.node.style.zIndex = '9999';\n this.toDispose.pushAll([\n this.service.onSnap((event: SnapEvent) => {\n this.edgeLines = this.calcEdgeLines(event);\n this.alignLines = this.calcAlignLines(event);\n this.render();\n }),\n ]);\n }\n\n public render(): JSX.Element {\n return (\n <>\n {this.alignLines.length > 0 && (\n <div className=\"workflow-snap-align-lines\">{this.renderAlignLines()}</div>\n )}\n {this.edgeLines.length > 0 && (\n <div className=\"workflow-snap-edge-lines\">{this.renderEdgeLines()}</div>\n )}\n </>\n );\n }\n\n public onZoom(scale: number): void {\n this.node.style.transform = `scale(${scale})`;\n }\n\n private renderEdgeLines(): JSX.Element[] {\n return this.edgeLines.map((renderLine: SnapRenderLine) => {\n const { className, sourceNode, top, left, width, height, dashed } = renderLine;\n const id = `${className}-${sourceNode}-${top}-${left}-${width}-${height}`;\n const isHorizontal = width < height;\n const border = `${this.options.edgeLineWidth}px ${dashed ? 'dashed' : 'solid'} ${\n this.options.edgeColor\n }`;\n return (\n <div\n className={`workflow-snap-edge-line ${className}`}\n data-testid=\"sdk.workflow.canvas.snap.edgeLine\"\n data-snap-line-id={id}\n data-snap-line-sourceNode={sourceNode}\n key={id}\n style={{\n top,\n left,\n width,\n height,\n position: 'absolute',\n borderLeft: isHorizontal ? border : 'none',\n borderTop: !isHorizontal ? border : 'none',\n }}\n />\n );\n });\n }\n\n private renderAlignLines(): JSX.Element[] {\n return this.alignLines.map((renderLine: SnapRenderLine) => {\n const id = `${renderLine.className}-${renderLine.sourceNode}-${renderLine.top}-${renderLine.left}-${renderLine.width}-${renderLine.height}`;\n const isHorizontal = isGreaterThan(renderLine.width, renderLine.height);\n const alignLineWidth = this.options.alignLineWidth; // 整体线条粗细\n const alignCrossWidth = this.options.alignCrossWidth; // 工字形横线的长度\n\n // 调整渲染位置以保持居中\n const adjustedTop = isHorizontal ? renderLine.top - alignLineWidth / 2 : renderLine.top;\n const adjustedLeft = isHorizontal ? renderLine.left : renderLine.left - alignLineWidth / 2;\n\n return (\n <div\n className={`workflow-snap-align-line ${renderLine.className}`}\n data-testid=\"sdk.workflow.canvas.snap.alignLine\"\n data-snap-line-id={id}\n data-snap-line-sourceNode={renderLine.sourceNode}\n key={id}\n style={{\n position: 'absolute',\n }}\n >\n {/* 主线 */}\n <div\n style={{\n position: 'absolute',\n top: adjustedTop,\n left: adjustedLeft,\n width: isHorizontal ? renderLine.width : alignLineWidth,\n height: isHorizontal ? alignLineWidth : renderLine.height,\n backgroundColor: this.options.alignColor,\n }}\n />\n {/* 左端或上端横线 */}\n <div\n style={{\n position: 'absolute',\n top: isHorizontal\n ? adjustedTop - (alignCrossWidth - alignLineWidth) / 2\n : adjustedTop,\n left: isHorizontal\n ? adjustedLeft\n : adjustedLeft - (alignCrossWidth - alignLineWidth) / 2,\n width: isHorizontal ? alignLineWidth : alignCrossWidth,\n height: isHorizontal ? alignCrossWidth : alignLineWidth,\n backgroundColor: this.options.alignColor,\n }}\n />\n {/* 右端或下端横线 */}\n <div\n style={{\n position: 'absolute',\n top: isHorizontal\n ? adjustedTop - (alignCrossWidth - alignLineWidth) / 2\n : adjustedTop + renderLine.height - alignLineWidth,\n left: isHorizontal\n ? adjustedLeft + renderLine.width - alignLineWidth\n : adjustedLeft - (alignCrossWidth - alignLineWidth) / 2,\n width: isHorizontal ? alignLineWidth : alignCrossWidth,\n height: isHorizontal ? alignCrossWidth : alignLineWidth,\n backgroundColor: this.options.alignColor,\n }}\n />\n </div>\n );\n });\n }\n\n private calcEdgeLines(event: SnapEvent): SnapRenderLine[] {\n const { alignRects, snapRect, snapEdgeLines } = event;\n const edgeLines: SnapRenderLine[] = [];\n\n const topFullAlign = this.directionFullAlign({\n alignRects: alignRects.top,\n targetRect: snapRect,\n isVertical: true,\n });\n const bottomFullAlign = this.directionFullAlign({\n alignRects: alignRects.bottom,\n targetRect: snapRect,\n isVertical: true,\n });\n const leftFullAlign = this.directionFullAlign({\n alignRects: alignRects.left,\n targetRect: snapRect,\n isVertical: false,\n });\n const rightFullAlign = this.directionFullAlign({\n alignRects: alignRects.right,\n targetRect: snapRect,\n isVertical: false,\n });\n\n // 处理顶部对齐\n if (topFullAlign) {\n const top = topFullAlign.rect.top;\n const height = bottomFullAlign\n ? snapRect.bottom - snapRect.height / 2 - top\n : snapRect.bottom - top;\n const width = this.options.edgeLineWidth;\n const lineData = {\n top,\n width,\n height,\n };\n edgeLines.push({\n className: 'edge-full-top-left',\n sourceNode: topFullAlign.sourceNodeId,\n left: snapRect.left,\n ...lineData,\n });\n edgeLines.push({\n className: 'edge-full-top-right',\n sourceNode: topFullAlign.sourceNodeId,\n left: snapRect.right,\n ...lineData,\n });\n edgeLines.push({\n className: 'edge-full-top-mid',\n sourceNode: topFullAlign.sourceNodeId,\n left: snapRect.left + snapRect.width / 2,\n dashed: true,\n ...lineData,\n });\n }\n\n // 处理底部对齐\n if (bottomFullAlign) {\n const top = topFullAlign ? snapRect.top + snapRect.height / 2 : snapRect.top;\n const height = bottomFullAlign.rect.bottom - top;\n const width = this.options.edgeLineWidth;\n const lineData = {\n top,\n width,\n height,\n };\n edgeLines.push({\n className: 'edge-full-bottom-left',\n sourceNode: bottomFullAlign.sourceNodeId,\n left: snapRect.left,\n ...lineData,\n });\n edgeLines.push({\n className: 'edge-full-bottom-right',\n sourceNode: bottomFullAlign.sourceNodeId,\n left: snapRect.right,\n ...lineData,\n });\n edgeLines.push({\n className: 'edge-full-bottom-mid',\n sourceNode: bottomFullAlign.sourceNodeId,\n left: snapRect.left + snapRect.width / 2,\n dashed: true,\n ...lineData,\n });\n }\n\n // 处理左侧对齐\n if (leftFullAlign) {\n const left = leftFullAlign.rect.left;\n const width = rightFullAlign\n ? snapRect.right - snapRect.width / 2 - left\n : snapRect.right - left;\n const height = this.options.edgeLineWidth;\n const lineData = {\n left,\n width,\n height,\n };\n edgeLines.push({\n className: 'edge-full-left-top',\n sourceNode: leftFullAlign.sourceNodeId,\n top: snapRect.top,\n ...lineData,\n });\n edgeLines.push({\n className: 'edge-full-left-bottom',\n sourceNode: leftFullAlign.sourceNodeId,\n top: snapRect.bottom,\n ...lineData,\n });\n edgeLines.push({\n className: 'edge-full-left-mid',\n sourceNode: leftFullAlign.sourceNodeId,\n top: snapRect.top + snapRect.height / 2,\n dashed: true,\n ...lineData,\n });\n }\n\n // 处理右侧对齐\n if (rightFullAlign) {\n const left = leftFullAlign ? snapRect.left + snapRect.width / 2 : snapRect.left;\n const width = rightFullAlign.rect.right - left;\n const height = this.options.edgeLineWidth;\n const lineData = {\n left,\n width,\n height,\n };\n edgeLines.push({\n className: 'edge-full-right-top',\n sourceNode: rightFullAlign.sourceNodeId,\n top: snapRect.top,\n ...lineData,\n });\n edgeLines.push({\n className: 'edge-full-right-bottom',\n sourceNode: rightFullAlign.sourceNodeId,\n top: snapRect.bottom,\n ...lineData,\n });\n edgeLines.push({\n className: 'edge-full-right-mid',\n sourceNode: rightFullAlign.sourceNodeId,\n top: snapRect.top + snapRect.height / 2,\n dashed: true,\n ...lineData,\n });\n }\n\n const snappedEdgeLines = Object.entries(snapEdgeLines)\n .map(([direction, snapLine]) => {\n if (!snapLine) {\n return;\n }\n const sourceNode = this.document.getNode(snapLine.sourceNodeId);\n if (!sourceNode) {\n return;\n }\n const nodeRect = sourceNode.getData(FlowNodeTransformData).bounds;\n if (isNumber(snapLine.x)) {\n // 垂直\n const top = Math.min(nodeRect.top, snapRect.top);\n const bottom = Math.max(nodeRect.bottom, snapRect.bottom);\n const height = bottom - top;\n const left = snapLine.x;\n const width = this.options.edgeLineWidth;\n const isMidX = direction === 'midVertical';\n const lineData: SnapRenderLine = {\n className: `edge-snapped-${direction}`,\n sourceNode: snapLine.sourceNodeId,\n top,\n left,\n width,\n height,\n dashed: isMidX,\n };\n const onTop = top === nodeRect.top;\n if (onTop && topFullAlign) {\n return;\n }\n if (!onTop && bottomFullAlign) {\n return;\n }\n return lineData;\n } else if (isNumber(snapLine.y)) {\n // 水平\n const left = Math.min(nodeRect.left, snapRect.left);\n const right = Math.max(nodeRect.right, snapRect.right);\n const width = right - left;\n const top = snapLine.y;\n const height = this.options.edgeLineWidth;\n const isMidY = direction === 'midHorizontal';\n const lineData: SnapRenderLine = {\n className: `edge-snapped-${direction}`,\n sourceNode: snapLine.sourceNodeId,\n top,\n left,\n width,\n height,\n dashed: isMidY,\n };\n const onLeft = left === nodeRect.left;\n if (onLeft && leftFullAlign) {\n return;\n }\n if (!onLeft && rightFullAlign) {\n return;\n }\n return lineData;\n }\n })\n .filter(Boolean) as SnapRenderLine[];\n\n edgeLines.push(...snappedEdgeLines);\n\n return edgeLines;\n }\n\n private directionFullAlign(params: {\n alignRects: AlignRect[];\n targetRect: Rectangle;\n isVertical: boolean;\n }): AlignRect | undefined {\n const { alignRects, targetRect, isVertical } = params;\n let fullAlignIndex = -1;\n for (let i = 0; i < alignRects.length; i++) {\n const alignRect = alignRects[i];\n const prevRect = alignRects[i - 1]?.rect ?? targetRect;\n const isFullAlign = this.rectFullAlign(alignRect.rect, prevRect, isVertical);\n if (!isFullAlign) {\n // 未对齐则中断\n break; // 用 for 循环 + break 反而比 Array.findIndex 实现可读性更好\n }\n fullAlignIndex = i;\n }\n const fullAlignRect = alignRects[fullAlignIndex];\n return fullAlignRect;\n }\n\n private rectFullAlign(rectA: Rectangle, rectB: Rectangle, isVertical: boolean): boolean {\n if (isVertical) {\n return isEqual(rectA.left, rectB.left) && isEqual(rectA.right, rectB.right);\n } else {\n return isEqual(rectA.top, rectB.top) && isEqual(rectA.bottom, rectB.bottom);\n }\n }\n\n private calcAlignLines(event: SnapEvent): SnapRenderLine[] {\n const { alignRects, alignSpacing, snapRect } = event;\n\n const topAlignLines = this.calcDirectionAlignLines({\n alignRects: alignRects.top,\n targetRect: snapRect,\n isVertical: true,\n spacing: alignSpacing.midVertical ?? alignSpacing.top,\n });\n\n const bottomAlignLines = this.calcDirectionAlignLines({\n alignRects: alignRects.bottom,\n targetRect: snapRect,\n isVertical: true,\n spacing: alignSpacing.midVertical ?? alignSpacing.bottom,\n });\n\n const leftAlignLines = this.calcDirectionAlignLines({\n alignRects: alignRects.left,\n targetRect: snapRect,\n isVertical: false,\n spacing: alignSpacing.midHorizontal ?? alignSpacing.left,\n });\n\n const rightAlignLines = this.calcDirectionAlignLines({\n alignRects: alignRects.right,\n targetRect: snapRect,\n isVertical: false,\n spacing: alignSpacing.midHorizontal ?? alignSpacing.right,\n });\n\n return [...topAlignLines, ...bottomAlignLines, ...leftAlignLines, ...rightAlignLines];\n }\n\n private calcDirectionAlignLines(params: {\n alignRects: AlignRect[];\n targetRect: Rectangle;\n isVertical: boolean;\n spacing?: number;\n }) {\n const { alignRects, targetRect, isVertical, spacing } = params;\n const alignLines: SnapRenderLine[] = [];\n if (!spacing) {\n return alignLines;\n }\n for (let i = 0; i < alignRects.length; i++) {\n const alignRect = alignRects[i];\n const rect = alignRect.rect;\n const prevRect = alignRects[i - 1]?.rect ?? targetRect;\n\n const betweenSpacing = isVertical\n ? Math.min(Math.abs(prevRect.top - rect.bottom), Math.abs(prevRect.bottom - rect.top))\n : Math.min(Math.abs(prevRect.left - rect.right), Math.abs(prevRect.right - rect.left));\n if (!isEqual(betweenSpacing, spacing)) {\n // 不连续,需要中断\n break; // 因为要用到 break,所以不能用 Array.map()\n }\n if (isVertical) {\n const centerX = this.calcHorizontalIntersectionCenter(rect, targetRect);\n alignLines.push({\n className: 'align-vertical',\n sourceNode: alignRect.sourceNodeId,\n top: Math.min(rect.bottom, prevRect.bottom),\n left: centerX,\n width: 1,\n height: spacing,\n });\n } else {\n const centerY = this.calcVerticalIntersectionCenter(rect, targetRect);\n alignLines.push({\n className: 'align-horizontal',\n sourceNode: alignRect.sourceNodeId,\n top: centerY,\n left: Math.min(rect.right, prevRect.right),\n width: spacing,\n height: 1,\n });\n }\n }\n return alignLines;\n }\n\n private calcVerticalIntersectionCenter(rectA: Rectangle, rectB: Rectangle): number {\n const top = Math.max(rectA.top, rectB.top);\n const bottom = Math.min(rectA.bottom, rectB.bottom);\n return (top + bottom) / 2;\n }\n\n private calcHorizontalIntersectionCenter(rectA: Rectangle, rectB: Rectangle): number {\n const left = Math.max(rectA.left, rectB.left);\n const right = Math.min(rectA.right, rectB.right);\n return (left + right) / 2;\n }\n}\n"],"mappings":"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","names":["inject","injectable","FlowNodeTransformData","WorkflowDocument","FlowNodeTransformData","inject","WorkflowDocument","injectable"]}
1
+ {"version":3,"sources":["../../src/create-plugin.ts","../../src/service.ts","../../src/constant.ts","../../src/utils.ts","../../src/layer.tsx"],"sourcesContent":["import { definePluginCreator } from '@flowgram.ai/core';\n\nimport {\n FreeSnapPluginOptions,\n WorkflowSnapLayerOptions,\n WorkflowSnapServiceOptions,\n} from './type';\nimport { WorkflowSnapService } from './service';\nimport { WorkflowSnapLayer } from './layer';\nimport { SnapDefaultOptions } from './constant';\n\nexport const createFreeSnapPlugin = definePluginCreator<FreeSnapPluginOptions>({\n onBind({ bind }) {\n bind(WorkflowSnapService).toSelf().inSingletonScope();\n },\n onInit(ctx, opts) {\n const options: WorkflowSnapServiceOptions & WorkflowSnapLayerOptions = {\n ...SnapDefaultOptions,\n ...opts,\n };\n ctx.playground.registerLayer(WorkflowSnapLayer, options);\n const snapService = ctx.get<WorkflowSnapService>(WorkflowSnapService);\n snapService.init(options);\n },\n onDispose(ctx) {\n const snapService = ctx.get<WorkflowSnapService>(WorkflowSnapService);\n snapService.dispose();\n },\n});\n","import { inject, injectable } from 'inversify';\nimport { Disposable, Emitter, Rectangle } from '@flowgram.ai/utils';\nimport { IPoint } from '@flowgram.ai/utils';\nimport { WorkflowNodeEntity, WorkflowDocument } from '@flowgram.ai/free-layout-core';\nimport { WorkflowDragService } from '@flowgram.ai/free-layout-core';\nimport { FlowNodeTransformData } from '@flowgram.ai/document';\nimport { FlowNodeBaseType } from '@flowgram.ai/document';\nimport { EntityManager, PlaygroundConfigEntity, TransformData } from '@flowgram.ai/core';\n\nimport { isEqual, isGreaterThan, isLessThan, isLessThanOrEqual, isNumber } from './utils';\nimport type {\n SnapEvent,\n SnapHorizontalLine,\n SnapLines,\n SnapMidHorizontalLine,\n SnapMidVerticalLine,\n SnapVerticalLine,\n WorkflowSnapServiceOptions,\n AlignRects,\n AlignRect,\n AlignSpacing,\n SnapNodeRect,\n SnapEdgeLines,\n} from './type';\nimport { SnapDefaultOptions } from './constant';\n\n@injectable()\nexport class WorkflowSnapService {\n @inject(WorkflowDocument) private readonly document: WorkflowDocument;\n\n @inject(EntityManager) private readonly entityManager: EntityManager;\n\n @inject(WorkflowDragService)\n private readonly dragService: WorkflowDragService;\n\n @inject(PlaygroundConfigEntity)\n private readonly playgroundConfig: PlaygroundConfigEntity;\n\n private disposers: Disposable[] = [];\n\n private options: WorkflowSnapServiceOptions;\n\n private snapEmitter = new Emitter<SnapEvent>();\n\n public readonly onSnap = this.snapEmitter.event;\n\n private _disabled = false;\n\n public init(params: Partial<WorkflowSnapServiceOptions> = {}): void {\n this.options = {\n ...SnapDefaultOptions,\n ...params,\n };\n this.mountListener();\n }\n\n public dispose(): void {\n this.disposers.forEach((disposer) => disposer.dispose());\n }\n\n public get disabled(): boolean {\n return this._disabled;\n }\n\n public disable(): void {\n if (this._disabled) {\n return;\n }\n this._disabled = true;\n this.clear();\n }\n\n public enable(): void {\n if (!this._disabled) {\n return;\n }\n this._disabled = false;\n this.clear();\n }\n\n private mountListener(): void {\n const dragAdjusterDisposer = this.dragService.registerPosAdjuster((params) => {\n const { selectedNodes: targetNodes, position } = params;\n const isMultiSnapping = this.options.enableMultiSnapping ? false : targetNodes.length !== 1;\n if (this._disabled || !this.options.enableEdgeSnapping || isMultiSnapping) {\n return {\n x: 0,\n y: 0,\n };\n }\n return this.snapping({\n targetNodes,\n position,\n });\n });\n const dragEndDisposer = this.dragService.onNodesDrag((event) => {\n if (event.type !== 'onDragEnd' || this._disabled) {\n return;\n }\n if (this.options.enableGridSnapping) {\n this.gridSnapping({\n targetNodes: event.nodes,\n gridSize: this.options.gridSize,\n });\n }\n if (this.options.enableEdgeSnapping) {\n this.clear();\n }\n });\n this.disposers.push(dragAdjusterDisposer, dragEndDisposer);\n }\n\n private snapping(params: { targetNodes: WorkflowNodeEntity[]; position: IPoint }): IPoint {\n const { targetNodes, position } = params;\n\n const targetBounds = this.getBounds(targetNodes);\n\n const targetRect = new Rectangle(\n position.x,\n position.y,\n targetBounds.width,\n targetBounds.height\n );\n\n const snapNodeRects = this.getSnapNodeRects({\n targetNodes,\n targetRect,\n });\n\n const { alignOffset, alignRects, alignSpacing } = this.calcAlignOffset({\n targetRect,\n alignThreshold: this.options.edgeThreshold,\n snapNodeRects,\n });\n\n const { snapOffset, snapEdgeLines } = this.calcSnapOffset({\n targetRect,\n edgeThreshold: this.options.edgeThreshold,\n snapNodeRects,\n });\n\n const offset: IPoint = {\n x: snapOffset.x || alignOffset.x,\n y: snapOffset.y || alignOffset.y,\n };\n\n const snapRect = new Rectangle(\n position.x + offset.x,\n position.y + offset.y,\n targetRect.width,\n targetRect.height\n );\n\n this.snapEmitter.fire({\n snapRect,\n snapEdgeLines,\n alignRects,\n alignSpacing,\n });\n\n return offset;\n }\n\n private calcSnapOffset(params: {\n snapNodeRects: SnapNodeRect[];\n targetRect: Rectangle;\n edgeThreshold: number;\n }): {\n snapOffset: IPoint;\n snapEdgeLines: SnapEdgeLines;\n } {\n const { snapNodeRects, edgeThreshold, targetRect } = params;\n\n const snapLines = this.getSnapLines({\n snapNodeRects,\n });\n\n // 找到最近的线条\n const topYClosestLine = snapLines.horizontal.find((line) =>\n isLessThanOrEqual(Math.abs(line.y - targetRect.top), edgeThreshold)\n );\n const bottomYClosestLine = snapLines.horizontal.find((line) =>\n isLessThanOrEqual(Math.abs(line.y - targetRect.bottom), edgeThreshold)\n );\n const leftXClosestLine = snapLines.vertical.find((line) =>\n isLessThanOrEqual(Math.abs(line.x - targetRect.left), edgeThreshold)\n );\n const rightXClosestLine = snapLines.vertical.find((line) =>\n isLessThanOrEqual(Math.abs(line.x - targetRect.right), edgeThreshold)\n );\n const midYClosestLine = snapLines.midHorizontal.find((line) =>\n isLessThanOrEqual(Math.abs(line.y - targetRect.center.y), edgeThreshold)\n );\n const midXClosestLine = snapLines.midVertical.find((line) =>\n isLessThanOrEqual(Math.abs(line.x - targetRect.center.x), edgeThreshold)\n );\n\n // 计算最近坐标\n const topYClosest = topYClosestLine?.y;\n const bottomYClosest = isNumber(bottomYClosestLine?.y)\n ? bottomYClosestLine!.y - targetRect.height\n : undefined;\n const leftXClosest = leftXClosestLine?.x;\n const rightXClosest = isNumber(rightXClosestLine?.x)\n ? rightXClosestLine!.x - targetRect.width\n : undefined;\n const midYClosest = isNumber(midYClosestLine?.y)\n ? midYClosestLine!.y - targetRect.height / 2\n : undefined;\n const midXClosest = isNumber(midXClosestLine?.x)\n ? midXClosestLine!.x - targetRect.width / 2\n : undefined;\n\n // 吸附后坐标,按优先级取值\n const snappingPosition = {\n x: midXClosest ?? leftXClosest ?? rightXClosest ?? targetRect.x,\n y: midYClosest ?? topYClosest ?? bottomYClosest ?? targetRect.y,\n };\n\n // 吸附修正偏移量\n const snapOffset: IPoint = {\n x: snappingPosition.x - targetRect.x,\n y: snappingPosition.y - targetRect.y,\n };\n\n // 生效的吸附线条\n const snapEdgeLines: SnapEdgeLines = {\n top: isEqual(topYClosest, snappingPosition.y) ? topYClosestLine : undefined,\n bottom: isEqual(bottomYClosest, snappingPosition.y) ? bottomYClosestLine : undefined,\n left: isEqual(leftXClosest, snappingPosition.x) ? leftXClosestLine : undefined,\n right: isEqual(rightXClosest, snappingPosition.x) ? rightXClosestLine : undefined,\n midVertical: isEqual(midXClosest, snappingPosition.x) ? midXClosestLine : undefined,\n midHorizontal: isEqual(midYClosest, snappingPosition.y) ? midYClosestLine : undefined,\n };\n\n return { snapOffset, snapEdgeLines };\n }\n\n private gridSnapping(params: { gridSize: number; targetNodes: WorkflowNodeEntity[] }): void {\n const { gridSize, targetNodes } = params;\n const rect = this.getBounds(targetNodes);\n const snap = (value: number) => Math.round(value / gridSize) * gridSize;\n const snappedPosition: IPoint = {\n x: snap(rect.x),\n y: snap(rect.y),\n };\n const offset: IPoint = {\n x: snappedPosition.x - rect.x,\n y: snappedPosition.y - rect.y,\n };\n targetNodes.forEach((node) =>\n this.updateNodePositionWithOffset({\n node,\n offset,\n })\n );\n }\n\n private clear() {\n this.snapEmitter.fire({\n snapEdgeLines: {},\n snapRect: Rectangle.EMPTY,\n alignRects: {\n top: [],\n bottom: [],\n left: [],\n right: [],\n },\n alignSpacing: {},\n });\n }\n\n private getSnapLines(params: { snapNodeRects: SnapNodeRect[] }): SnapLines {\n const { snapNodeRects } = params;\n const horizontalLines: SnapHorizontalLine[] = [];\n const verticalLines: SnapVerticalLine[] = [];\n const midHorizontalLines: SnapMidHorizontalLine[] = [];\n const midVerticalLines: SnapMidVerticalLine[] = [];\n\n snapNodeRects.forEach((snapNodeRect) => {\n const nodeBounds = snapNodeRect.rect;\n const nodeCenter = nodeBounds.center;\n // 边缘横线\n const top: SnapHorizontalLine = {\n y: nodeBounds.top,\n sourceNodeId: snapNodeRect.id,\n };\n const bottom: SnapHorizontalLine = {\n y: nodeBounds.bottom,\n sourceNodeId: snapNodeRect.id,\n };\n // 边缘竖线\n const left: SnapVerticalLine = {\n x: nodeBounds.left,\n sourceNodeId: snapNodeRect.id,\n };\n const right: SnapVerticalLine = {\n x: nodeBounds.right,\n sourceNodeId: snapNodeRect.id,\n };\n // 中间横线\n const midHorizontal: SnapMidHorizontalLine = {\n y: nodeCenter.y,\n sourceNodeId: snapNodeRect.id,\n };\n // 中间竖线\n const midVertical: SnapMidVerticalLine = {\n x: nodeCenter.x,\n sourceNodeId: snapNodeRect.id,\n };\n horizontalLines.push(top, bottom);\n verticalLines.push(left, right);\n midHorizontalLines.push(midHorizontal);\n midVerticalLines.push(midVertical);\n });\n\n return {\n horizontal: horizontalLines,\n vertical: verticalLines,\n midHorizontal: midHorizontalLines,\n midVertical: midVerticalLines,\n };\n }\n\n private getAvailableNodes(params: {\n targetNodes: WorkflowNodeEntity[];\n targetRect: Rectangle;\n }): WorkflowNodeEntity[] {\n const { targetNodes, targetRect } = params;\n\n const targetCenter = targetRect.center;\n const targetContainerId = targetNodes[0].parent?.id ?? this.document.root.id;\n\n const disabledNodeIds = targetNodes.map((n) => n.id);\n disabledNodeIds.push(FlowNodeBaseType.ROOT);\n const availableNodes = this.nodes\n .filter((n) => n.parent?.id === targetContainerId)\n .filter((n) => !disabledNodeIds.includes(n.id))\n .sort((nodeA, nodeB) => {\n const nodeCenterA = nodeA.getData(FlowNodeTransformData)!.bounds.center;\n const nodeCenterB = nodeB.getData(FlowNodeTransformData)!.bounds.center;\n // 距离越近优先级越高\n const distanceA =\n Math.abs(nodeCenterA.x - targetCenter.x) + Math.abs(nodeCenterA.y - targetCenter.y);\n const distanceB =\n Math.abs(nodeCenterB.x - targetCenter.x) + Math.abs(nodeCenterB.y - targetCenter.y);\n return distanceA - distanceB;\n });\n return availableNodes;\n }\n\n private viewRect(): Rectangle {\n const { width, height, scrollX, scrollY, zoom } = this.playgroundConfig.config;\n return new Rectangle(scrollX / zoom, scrollY / zoom, width / zoom, height / zoom);\n }\n\n private getSnapNodeRects(params: {\n targetNodes: WorkflowNodeEntity[];\n targetRect: Rectangle;\n }): SnapNodeRect[] {\n const availableNodes = this.getAvailableNodes(params);\n const viewRect = this.viewRect();\n return availableNodes\n .map((node) => {\n const snapNodeRect: SnapNodeRect = {\n id: node.id,\n rect: node.getData(FlowNodeTransformData).bounds,\n entity: node,\n };\n if (\n this.options.enableOnlyViewportSnapping &&\n node.parent?.flowNodeType === FlowNodeBaseType.ROOT &&\n !Rectangle.intersects(viewRect, snapNodeRect.rect)\n ) {\n // 最外层节点仅包含当前可见节点\n return;\n }\n return snapNodeRect;\n })\n .filter(Boolean) as SnapNodeRect[];\n }\n\n private get nodes(): WorkflowNodeEntity[] {\n return this.entityManager.getEntities<WorkflowNodeEntity>(WorkflowNodeEntity);\n }\n\n private getBounds(nodes: WorkflowNodeEntity[]): Rectangle {\n if (nodes.length === 0) {\n return Rectangle.EMPTY;\n }\n return Rectangle.enlarge(nodes.map((n) => n.getData(FlowNodeTransformData)!.bounds));\n }\n\n private updateNodePositionWithOffset(params: { node: WorkflowNodeEntity; offset: IPoint }): void {\n const { node, offset } = params;\n const transform = node.getData(TransformData);\n const positionWithOffset: IPoint = {\n x: transform.position.x + offset.x,\n y: transform.position.y + offset.y,\n };\n if (node.collapsedChildren?.length > 0) {\n // 嵌套情况下需将子节点 transform 设为 dirty\n node.collapsedChildren.forEach((childNode) => {\n const childNodeTransformData =\n childNode.getData<FlowNodeTransformData>(FlowNodeTransformData);\n childNodeTransformData.fireChange();\n });\n }\n transform.update({\n position: positionWithOffset,\n });\n }\n\n private calcAlignOffset(params: {\n snapNodeRects: SnapNodeRect[];\n targetRect: Rectangle;\n alignThreshold: number;\n }): {\n alignOffset: IPoint;\n alignRects: AlignRects;\n alignSpacing: AlignSpacing;\n } {\n const { snapNodeRects, targetRect, alignThreshold } = params;\n\n const alignRects = this.getAlignRects({\n targetRect,\n snapNodeRects,\n });\n\n const alignSpacing = this.calcAlignSpacing({\n targetRect,\n alignRects,\n });\n\n let topY: number | undefined;\n let bottomY: number | undefined;\n let leftX: number | undefined;\n let rightX: number | undefined;\n let midY: number | undefined;\n let midX: number | undefined;\n\n if (alignSpacing.top) {\n const topAlignY = alignRects.top[0].rect.bottom + alignSpacing.top;\n const isAlignTop = isLessThanOrEqual(Math.abs(targetRect.top - topAlignY), alignThreshold);\n if (isAlignTop) {\n // 生效\n topY = topAlignY;\n } else {\n // 失效\n alignSpacing.top = undefined;\n }\n }\n if (alignSpacing.bottom) {\n const bottomAlignY = alignRects.bottom[0].rect.top - alignSpacing.bottom;\n const isAlignBottom = isLessThan(Math.abs(targetRect.bottom - bottomAlignY), alignThreshold);\n if (isAlignBottom) {\n bottomY = bottomAlignY - targetRect.height;\n } else {\n alignSpacing.bottom = undefined;\n }\n }\n if (alignSpacing.left) {\n const leftAlignX = alignRects.left[0].rect.right + alignSpacing.left;\n const isAlignLeft = isLessThanOrEqual(Math.abs(targetRect.left - leftAlignX), alignThreshold);\n if (isAlignLeft) {\n leftX = leftAlignX;\n } else {\n alignSpacing.left = undefined;\n }\n }\n if (alignSpacing.right) {\n const rightAlignX = alignRects.right[0].rect.left - alignSpacing.right;\n const isAlignRight = isLessThanOrEqual(\n Math.abs(targetRect.right - rightAlignX),\n alignThreshold\n );\n if (isAlignRight) {\n rightX = rightAlignX - targetRect.width;\n } else {\n alignSpacing.right = undefined;\n }\n }\n if (alignSpacing.midHorizontal) {\n const leftAlignX = alignRects.left[0].rect.right + alignSpacing.midHorizontal;\n const isAlignMidHorizontal = isLessThanOrEqual(\n Math.abs(targetRect.left - leftAlignX),\n alignThreshold\n );\n if (isAlignMidHorizontal) {\n midX = leftAlignX;\n } else {\n alignSpacing.midHorizontal = undefined;\n }\n }\n if (alignSpacing.midVertical) {\n const topAlignY = alignRects.top[0].rect.bottom + alignSpacing.midVertical;\n const isAlignMidVertical = isLessThanOrEqual(\n Math.abs(targetRect.top - topAlignY),\n alignThreshold\n );\n if (isAlignMidVertical) {\n midY = topAlignY;\n } else {\n alignSpacing.midVertical = undefined;\n }\n }\n\n const alignPosition: IPoint = {\n x: midX ?? leftX ?? rightX ?? targetRect.x,\n y: midY ?? topY ?? bottomY ?? targetRect.y,\n };\n\n const alignOffset: IPoint = {\n x: alignPosition.x - targetRect.x,\n y: alignPosition.y - targetRect.y,\n };\n\n return { alignOffset, alignRects, alignSpacing };\n }\n\n private calcAlignSpacing(params: {\n targetRect: Rectangle;\n alignRects: AlignRects;\n }): AlignSpacing {\n const { targetRect, alignRects } = params;\n\n const topSpacing = this.getDirectionAlignSpacing({\n rects: alignRects.top,\n isHorizontal: false,\n });\n const bottomSpacing = this.getDirectionAlignSpacing({\n rects: alignRects.bottom,\n isHorizontal: false,\n });\n const leftSpacing = this.getDirectionAlignSpacing({\n rects: alignRects.left,\n isHorizontal: true,\n });\n const rightSpacing = this.getDirectionAlignSpacing({\n rects: alignRects.right,\n isHorizontal: true,\n });\n const midHorizontalSpacing = this.getMidAlignSpacing({\n rectA: alignRects.left[0]?.rect,\n rectB: alignRects.right[0]?.rect,\n targetRect,\n isHorizontal: true,\n });\n const midVerticalSpacing = this.getMidAlignSpacing({\n rectA: alignRects.top[0]?.rect,\n rectB: alignRects.bottom[0]?.rect,\n targetRect,\n isHorizontal: false,\n });\n return {\n top: topSpacing,\n bottom: bottomSpacing,\n left: leftSpacing,\n right: rightSpacing,\n midHorizontal: midHorizontalSpacing,\n midVertical: midVerticalSpacing,\n };\n }\n\n private getAlignRects(params: {\n targetRect: Rectangle;\n snapNodeRects: SnapNodeRect[];\n }): AlignRects {\n const { targetRect, snapNodeRects } = params;\n\n const topVerticalRects: AlignRect[] = [];\n const bottomVerticalRects: AlignRect[] = [];\n const leftHorizontalRects: AlignRect[] = [];\n const rightHorizontalRects: AlignRect[] = [];\n\n snapNodeRects.forEach((snapNodeRect) => {\n const nodeRect = snapNodeRect.rect;\n const { isVerticalIntersection, isHorizontalIntersection, isIntersection } =\n this.intersection(nodeRect, targetRect);\n if (isIntersection) {\n // 忽略重叠的节点\n return;\n } else if (isVerticalIntersection) {\n // 垂直重合\n if (isGreaterThan(nodeRect.center.y, targetRect.center.y)) {\n // 下方\n bottomVerticalRects.push({\n rect: nodeRect,\n sourceNodeId: snapNodeRect.id,\n });\n } else {\n // 上方\n topVerticalRects.push({\n rect: nodeRect,\n sourceNodeId: snapNodeRect.id,\n });\n }\n } else if (isHorizontalIntersection) {\n // 水平重合\n if (isGreaterThan(nodeRect.center.x, targetRect.center.x)) {\n // 右方\n rightHorizontalRects.push({\n rect: nodeRect,\n sourceNodeId: snapNodeRect.id,\n });\n } else {\n // 左方\n leftHorizontalRects.push({\n rect: nodeRect,\n sourceNodeId: snapNodeRect.id,\n });\n }\n }\n });\n\n return {\n top: topVerticalRects,\n bottom: bottomVerticalRects,\n left: leftHorizontalRects,\n right: rightHorizontalRects,\n };\n }\n\n private getMidAlignSpacing(params: {\n rectA?: Rectangle;\n rectB?: Rectangle;\n targetRect: Rectangle;\n isHorizontal: boolean;\n }): number | undefined {\n const { rectA, rectB, targetRect, isHorizontal } = params;\n if (!rectA || !rectB) {\n return;\n }\n const { isVerticalIntersection, isHorizontalIntersection, isIntersection } = this.intersection(\n rectA,\n rectB\n );\n if (isIntersection) {\n return;\n }\n if (isHorizontal && isHorizontalIntersection && !isVerticalIntersection) {\n const betweenSpacing = Math.min(\n Math.abs(rectA.left - rectB.right),\n Math.abs(rectA.right - rectB.left)\n );\n return (betweenSpacing - targetRect.width) / 2;\n } else if (!isHorizontal && isVerticalIntersection && !isHorizontalIntersection) {\n const betweenSpacing = Math.min(\n Math.abs(rectA.top - rectB.bottom),\n Math.abs(rectA.bottom - rectB.top)\n );\n return (betweenSpacing - targetRect.height) / 2;\n }\n }\n\n private getDirectionAlignSpacing(params: {\n rects: AlignRect[];\n isHorizontal: boolean;\n }): number | undefined {\n const { rects, isHorizontal } = params;\n if (rects.length < 2) {\n // 非法情况\n return;\n }\n const rectA = rects[0].rect;\n const rectB = rects[1].rect;\n\n const { isVerticalIntersection, isHorizontalIntersection, isIntersection } = this.intersection(\n rectA,\n rectB\n );\n\n if (isIntersection) {\n // 非法情况:重叠\n return;\n }\n if (isHorizontal && isHorizontalIntersection && !isVerticalIntersection) {\n return Math.min(Math.abs(rectA.left - rectB.right), Math.abs(rectA.right - rectB.left));\n } else if (!isHorizontal && isVerticalIntersection && !isHorizontalIntersection) {\n return Math.min(Math.abs(rectA.top - rectB.bottom), Math.abs(rectA.bottom - rectB.top));\n }\n return;\n }\n\n private intersection(\n rectA: Rectangle,\n rectB: Rectangle\n ): {\n isHorizontalIntersection: boolean;\n isVerticalIntersection: boolean;\n isIntersection: boolean;\n } {\n const isVerticalIntersection =\n isLessThan(rectA.left, rectB.right) && isGreaterThan(rectA.right, rectB.left);\n const isHorizontalIntersection =\n isLessThan(rectA.top, rectB.bottom) && isGreaterThan(rectA.bottom, rectB.top);\n const isIntersection = isHorizontalIntersection && isVerticalIntersection;\n\n return {\n isHorizontalIntersection,\n isVerticalIntersection,\n isIntersection,\n };\n }\n}\n","import type { WorkflowSnapLayerOptions, WorkflowSnapServiceOptions } from './type';\n\nexport const SnapDefaultOptions: WorkflowSnapServiceOptions & WorkflowSnapLayerOptions = {\n enableEdgeSnapping: true,\n edgeThreshold: 7,\n enableGridSnapping: false,\n gridSize: 20,\n enableMultiSnapping: false,\n enableOnlyViewportSnapping: true,\n edgeColor: '#4E40E5',\n alignColor: '#4E40E5',\n edgeLineWidth: 2,\n alignLineWidth: 2,\n alignCrossWidth: 16,\n};\n\nexport const Epsilon = 0.00001;\n","import { Epsilon } from './constant';\n\n/** 检查浮点数 a 是否等于 b */\nexport const isEqual = (a: number | undefined, b: number | undefined): boolean => {\n if (a === undefined || b === undefined) {\n return false;\n }\n // 检查 a 和 b 的差的绝对值是否小于 Epsilon\n return Math.abs(a - b) < Epsilon;\n};\n\n/** 检查浮点数 a 是否小于 b */\nexport const isLessThan = (a: number | undefined, b: number | undefined): boolean => {\n if (a === undefined || b === undefined) {\n return false;\n }\n // 检查 a 是否显著小于 b\n return b - a > Epsilon;\n};\n\n/** 检查浮点数 a 是否大于 b */\nexport const isGreaterThan = (a: number | undefined, b: number | undefined): boolean => {\n if (a === undefined || b === undefined) {\n return false;\n }\n return a - b > Epsilon;\n};\n\n/** 检查浮点数 a 是否小于等于 b */\nexport const isLessThanOrEqual = (a: number | undefined, b: number | undefined): boolean =>\n isEqual(a, b) || isLessThan(a, b);\n\n/** 检查浮点数 a 是否大于等于 b */\nexport const isGreaterThanOrEqual = (a: number | undefined, b: number | undefined): boolean =>\n isEqual(a, b) || isGreaterThan(a, b);\n\n/** 检查值是否是数字类型 */\nexport const isNumber = (value: unknown): value is number =>\n typeof value === 'number' && !isNaN(value);\n","import React from 'react';\n\nimport { inject, injectable } from 'inversify';\nimport { domUtils } from '@flowgram.ai/utils';\nimport { Rectangle } from '@flowgram.ai/utils';\nimport { WorkflowDocument } from '@flowgram.ai/free-layout-core';\nimport { FlowNodeTransformData } from '@flowgram.ai/document';\nimport { Layer } from '@flowgram.ai/core';\n\nimport { isEqual, isGreaterThan, isNumber } from './utils';\nimport { AlignRect, SnapEvent, WorkflowSnapLayerOptions } from './type';\nimport { WorkflowSnapService } from './service';\n\ninterface SnapRenderLine {\n className: string;\n sourceNode: string;\n top: number;\n left: number;\n width: number;\n height: number;\n dashed?: boolean;\n}\n\n@injectable()\nexport class WorkflowSnapLayer extends Layer<WorkflowSnapLayerOptions> {\n public static type = 'WorkflowSnapLayer';\n\n @inject(WorkflowDocument) private readonly document: WorkflowDocument;\n\n @inject(WorkflowSnapService) private readonly service: WorkflowSnapService;\n\n public readonly node = domUtils.createDivWithClass(\n 'gedit-playground-layer gedit-flow-snap-layer'\n );\n\n private edgeLines: SnapRenderLine[] = [];\n\n private alignLines: SnapRenderLine[] = [];\n\n public onReady(): void {\n this.node.style.zIndex = '9999';\n this.toDispose.pushAll([\n this.service.onSnap((event: SnapEvent) => {\n this.edgeLines = this.calcEdgeLines(event);\n this.alignLines = this.calcAlignLines(event);\n this.render();\n }),\n ]);\n }\n\n public render(): JSX.Element {\n return (\n <>\n {this.alignLines.length > 0 && (\n <div className=\"workflow-snap-align-lines\">{this.renderAlignLines()}</div>\n )}\n {this.edgeLines.length > 0 && (\n <div className=\"workflow-snap-edge-lines\">{this.renderEdgeLines()}</div>\n )}\n </>\n );\n }\n\n public onZoom(scale: number): void {\n this.node.style.transform = `scale(${scale})`;\n }\n\n private renderEdgeLines(): JSX.Element[] {\n return this.edgeLines.map((renderLine: SnapRenderLine) => {\n const { className, sourceNode, top, left, width, height, dashed } = renderLine;\n const id = `${className}-${sourceNode}-${top}-${left}-${width}-${height}`;\n const isHorizontal = width < height;\n const border = `${this.options.edgeLineWidth}px ${dashed ? 'dashed' : 'solid'} ${\n this.options.edgeColor\n }`;\n return (\n <div\n className={`workflow-snap-edge-line ${className}`}\n data-testid=\"sdk.workflow.canvas.snap.edgeLine\"\n data-snap-line-id={id}\n data-snap-line-source-node={sourceNode}\n key={id}\n style={{\n top,\n left,\n width,\n height,\n position: 'absolute',\n borderLeft: isHorizontal ? border : 'none',\n borderTop: !isHorizontal ? border : 'none',\n }}\n />\n );\n });\n }\n\n private renderAlignLines(): JSX.Element[] {\n return this.alignLines.map((renderLine: SnapRenderLine) => {\n const id = `${renderLine.className}-${renderLine.sourceNode}-${renderLine.top}-${renderLine.left}-${renderLine.width}-${renderLine.height}`;\n const isHorizontal = isGreaterThan(renderLine.width, renderLine.height);\n const alignLineWidth = this.options.alignLineWidth; // 整体线条粗细\n const alignCrossWidth = this.options.alignCrossWidth; // 工字形横线的长度\n\n // 调整渲染位置以保持居中\n const adjustedTop = isHorizontal ? renderLine.top - alignLineWidth / 2 : renderLine.top;\n const adjustedLeft = isHorizontal ? renderLine.left : renderLine.left - alignLineWidth / 2;\n\n return (\n <div\n className={`workflow-snap-align-line ${renderLine.className}`}\n data-testid=\"sdk.workflow.canvas.snap.alignLine\"\n data-snap-line-id={id}\n data-snap-line-source-node={renderLine.sourceNode}\n key={id}\n style={{\n position: 'absolute',\n }}\n >\n {/* 主线 */}\n <div\n style={{\n position: 'absolute',\n top: adjustedTop,\n left: adjustedLeft,\n width: isHorizontal ? renderLine.width : alignLineWidth,\n height: isHorizontal ? alignLineWidth : renderLine.height,\n backgroundColor: this.options.alignColor,\n }}\n />\n {/* 左端或上端横线 */}\n <div\n style={{\n position: 'absolute',\n top: isHorizontal\n ? adjustedTop - (alignCrossWidth - alignLineWidth) / 2\n : adjustedTop,\n left: isHorizontal\n ? adjustedLeft\n : adjustedLeft - (alignCrossWidth - alignLineWidth) / 2,\n width: isHorizontal ? alignLineWidth : alignCrossWidth,\n height: isHorizontal ? alignCrossWidth : alignLineWidth,\n backgroundColor: this.options.alignColor,\n }}\n />\n {/* 右端或下端横线 */}\n <div\n style={{\n position: 'absolute',\n top: isHorizontal\n ? adjustedTop - (alignCrossWidth - alignLineWidth) / 2\n : adjustedTop + renderLine.height - alignLineWidth,\n left: isHorizontal\n ? adjustedLeft + renderLine.width - alignLineWidth\n : adjustedLeft - (alignCrossWidth - alignLineWidth) / 2,\n width: isHorizontal ? alignLineWidth : alignCrossWidth,\n height: isHorizontal ? alignCrossWidth : alignLineWidth,\n backgroundColor: this.options.alignColor,\n }}\n />\n </div>\n );\n });\n }\n\n private calcEdgeLines(event: SnapEvent): SnapRenderLine[] {\n const { alignRects, snapRect, snapEdgeLines } = event;\n const edgeLines: SnapRenderLine[] = [];\n\n const topFullAlign = this.directionFullAlign({\n alignRects: alignRects.top,\n targetRect: snapRect,\n isVertical: true,\n });\n const bottomFullAlign = this.directionFullAlign({\n alignRects: alignRects.bottom,\n targetRect: snapRect,\n isVertical: true,\n });\n const leftFullAlign = this.directionFullAlign({\n alignRects: alignRects.left,\n targetRect: snapRect,\n isVertical: false,\n });\n const rightFullAlign = this.directionFullAlign({\n alignRects: alignRects.right,\n targetRect: snapRect,\n isVertical: false,\n });\n\n // 处理顶部对齐\n if (topFullAlign) {\n const top = topFullAlign.rect.top;\n const height = bottomFullAlign\n ? snapRect.bottom - snapRect.height / 2 - top\n : snapRect.bottom - top;\n const width = this.options.edgeLineWidth;\n const lineData = {\n top,\n width,\n height,\n };\n edgeLines.push({\n className: 'edge-full-top-left',\n sourceNode: topFullAlign.sourceNodeId,\n left: snapRect.left,\n ...lineData,\n });\n edgeLines.push({\n className: 'edge-full-top-right',\n sourceNode: topFullAlign.sourceNodeId,\n left: snapRect.right,\n ...lineData,\n });\n edgeLines.push({\n className: 'edge-full-top-mid',\n sourceNode: topFullAlign.sourceNodeId,\n left: snapRect.left + snapRect.width / 2,\n dashed: true,\n ...lineData,\n });\n }\n\n // 处理底部对齐\n if (bottomFullAlign) {\n const top = topFullAlign ? snapRect.top + snapRect.height / 2 : snapRect.top;\n const height = bottomFullAlign.rect.bottom - top;\n const width = this.options.edgeLineWidth;\n const lineData = {\n top,\n width,\n height,\n };\n edgeLines.push({\n className: 'edge-full-bottom-left',\n sourceNode: bottomFullAlign.sourceNodeId,\n left: snapRect.left,\n ...lineData,\n });\n edgeLines.push({\n className: 'edge-full-bottom-right',\n sourceNode: bottomFullAlign.sourceNodeId,\n left: snapRect.right,\n ...lineData,\n });\n edgeLines.push({\n className: 'edge-full-bottom-mid',\n sourceNode: bottomFullAlign.sourceNodeId,\n left: snapRect.left + snapRect.width / 2,\n dashed: true,\n ...lineData,\n });\n }\n\n // 处理左侧对齐\n if (leftFullAlign) {\n const left = leftFullAlign.rect.left;\n const width = rightFullAlign\n ? snapRect.right - snapRect.width / 2 - left\n : snapRect.right - left;\n const height = this.options.edgeLineWidth;\n const lineData = {\n left,\n width,\n height,\n };\n edgeLines.push({\n className: 'edge-full-left-top',\n sourceNode: leftFullAlign.sourceNodeId,\n top: snapRect.top,\n ...lineData,\n });\n edgeLines.push({\n className: 'edge-full-left-bottom',\n sourceNode: leftFullAlign.sourceNodeId,\n top: snapRect.bottom,\n ...lineData,\n });\n edgeLines.push({\n className: 'edge-full-left-mid',\n sourceNode: leftFullAlign.sourceNodeId,\n top: snapRect.top + snapRect.height / 2,\n dashed: true,\n ...lineData,\n });\n }\n\n // 处理右侧对齐\n if (rightFullAlign) {\n const left = leftFullAlign ? snapRect.left + snapRect.width / 2 : snapRect.left;\n const width = rightFullAlign.rect.right - left;\n const height = this.options.edgeLineWidth;\n const lineData = {\n left,\n width,\n height,\n };\n edgeLines.push({\n className: 'edge-full-right-top',\n sourceNode: rightFullAlign.sourceNodeId,\n top: snapRect.top,\n ...lineData,\n });\n edgeLines.push({\n className: 'edge-full-right-bottom',\n sourceNode: rightFullAlign.sourceNodeId,\n top: snapRect.bottom,\n ...lineData,\n });\n edgeLines.push({\n className: 'edge-full-right-mid',\n sourceNode: rightFullAlign.sourceNodeId,\n top: snapRect.top + snapRect.height / 2,\n dashed: true,\n ...lineData,\n });\n }\n\n const snappedEdgeLines = Object.entries(snapEdgeLines)\n .map(([direction, snapLine]) => {\n if (!snapLine) {\n return;\n }\n const sourceNode = this.document.getNode(snapLine.sourceNodeId);\n if (!sourceNode) {\n return;\n }\n const nodeRect = sourceNode.getData(FlowNodeTransformData).bounds;\n if (isNumber(snapLine.x)) {\n // 垂直\n const top = Math.min(nodeRect.top, snapRect.top);\n const bottom = Math.max(nodeRect.bottom, snapRect.bottom);\n const height = bottom - top;\n const left = snapLine.x;\n const width = this.options.edgeLineWidth;\n const isMidX = direction === 'midVertical';\n const lineData: SnapRenderLine = {\n className: `edge-snapped-${direction}`,\n sourceNode: snapLine.sourceNodeId,\n top,\n left,\n width,\n height,\n dashed: isMidX,\n };\n const onTop = top === nodeRect.top;\n if (onTop && topFullAlign) {\n return;\n }\n if (!onTop && bottomFullAlign) {\n return;\n }\n return lineData;\n } else if (isNumber(snapLine.y)) {\n // 水平\n const left = Math.min(nodeRect.left, snapRect.left);\n const right = Math.max(nodeRect.right, snapRect.right);\n const width = right - left;\n const top = snapLine.y;\n const height = this.options.edgeLineWidth;\n const isMidY = direction === 'midHorizontal';\n const lineData: SnapRenderLine = {\n className: `edge-snapped-${direction}`,\n sourceNode: snapLine.sourceNodeId,\n top,\n left,\n width,\n height,\n dashed: isMidY,\n };\n const onLeft = left === nodeRect.left;\n if (onLeft && leftFullAlign) {\n return;\n }\n if (!onLeft && rightFullAlign) {\n return;\n }\n return lineData;\n }\n })\n .filter(Boolean) as SnapRenderLine[];\n\n edgeLines.push(...snappedEdgeLines);\n\n return edgeLines;\n }\n\n private directionFullAlign(params: {\n alignRects: AlignRect[];\n targetRect: Rectangle;\n isVertical: boolean;\n }): AlignRect | undefined {\n const { alignRects, targetRect, isVertical } = params;\n let fullAlignIndex = -1;\n for (let i = 0; i < alignRects.length; i++) {\n const alignRect = alignRects[i];\n const prevRect = alignRects[i - 1]?.rect ?? targetRect;\n const isFullAlign = this.rectFullAlign(alignRect.rect, prevRect, isVertical);\n if (!isFullAlign) {\n // 未对齐则中断\n break; // 用 for 循环 + break 反而比 Array.findIndex 实现可读性更好\n }\n fullAlignIndex = i;\n }\n const fullAlignRect = alignRects[fullAlignIndex];\n return fullAlignRect;\n }\n\n private rectFullAlign(rectA: Rectangle, rectB: Rectangle, isVertical: boolean): boolean {\n if (isVertical) {\n return isEqual(rectA.left, rectB.left) && isEqual(rectA.right, rectB.right);\n } else {\n return isEqual(rectA.top, rectB.top) && isEqual(rectA.bottom, rectB.bottom);\n }\n }\n\n private calcAlignLines(event: SnapEvent): SnapRenderLine[] {\n const { alignRects, alignSpacing, snapRect } = event;\n\n const topAlignLines = this.calcDirectionAlignLines({\n alignRects: alignRects.top,\n targetRect: snapRect,\n isVertical: true,\n spacing: alignSpacing.midVertical ?? alignSpacing.top,\n });\n\n const bottomAlignLines = this.calcDirectionAlignLines({\n alignRects: alignRects.bottom,\n targetRect: snapRect,\n isVertical: true,\n spacing: alignSpacing.midVertical ?? alignSpacing.bottom,\n });\n\n const leftAlignLines = this.calcDirectionAlignLines({\n alignRects: alignRects.left,\n targetRect: snapRect,\n isVertical: false,\n spacing: alignSpacing.midHorizontal ?? alignSpacing.left,\n });\n\n const rightAlignLines = this.calcDirectionAlignLines({\n alignRects: alignRects.right,\n targetRect: snapRect,\n isVertical: false,\n spacing: alignSpacing.midHorizontal ?? alignSpacing.right,\n });\n\n return [...topAlignLines, ...bottomAlignLines, ...leftAlignLines, ...rightAlignLines];\n }\n\n private calcDirectionAlignLines(params: {\n alignRects: AlignRect[];\n targetRect: Rectangle;\n isVertical: boolean;\n spacing?: number;\n }) {\n const { alignRects, targetRect, isVertical, spacing } = params;\n const alignLines: SnapRenderLine[] = [];\n if (!spacing) {\n return alignLines;\n }\n for (let i = 0; i < alignRects.length; i++) {\n const alignRect = alignRects[i];\n const rect = alignRect.rect;\n const prevRect = alignRects[i - 1]?.rect ?? targetRect;\n\n const betweenSpacing = isVertical\n ? Math.min(Math.abs(prevRect.top - rect.bottom), Math.abs(prevRect.bottom - rect.top))\n : Math.min(Math.abs(prevRect.left - rect.right), Math.abs(prevRect.right - rect.left));\n if (!isEqual(betweenSpacing, spacing)) {\n // 不连续,需要中断\n break; // 因为要用到 break,所以不能用 Array.map()\n }\n if (isVertical) {\n const centerX = this.calcHorizontalIntersectionCenter(rect, targetRect);\n alignLines.push({\n className: 'align-vertical',\n sourceNode: alignRect.sourceNodeId,\n top: Math.min(rect.bottom, prevRect.bottom),\n left: centerX,\n width: 1,\n height: spacing,\n });\n } else {\n const centerY = this.calcVerticalIntersectionCenter(rect, targetRect);\n alignLines.push({\n className: 'align-horizontal',\n sourceNode: alignRect.sourceNodeId,\n top: centerY,\n left: Math.min(rect.right, prevRect.right),\n width: spacing,\n height: 1,\n });\n }\n }\n return alignLines;\n }\n\n private calcVerticalIntersectionCenter(rectA: Rectangle, rectB: Rectangle): number {\n const top = Math.max(rectA.top, rectB.top);\n const bottom = Math.min(rectA.bottom, rectB.bottom);\n return (top + bottom) / 2;\n }\n\n private calcHorizontalIntersectionCenter(rectA: Rectangle, rectB: Rectangle): number {\n const left = Math.max(rectA.left, rectB.left);\n const right = Math.min(rectA.right, rectB.right);\n return (left + right) / 2;\n }\n}\n"],"mappings":"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","names":["inject","injectable","WorkflowDocument","FlowNodeTransformData","FlowNodeTransformData","inject","WorkflowDocument","injectable"]}
package/dist/index.d.mts CHANGED
@@ -78,8 +78,12 @@ declare class WorkflowSnapService {
78
78
  private options;
79
79
  private snapEmitter;
80
80
  readonly onSnap: _flowgram_ai_utils.Event<SnapEvent>;
81
+ private _disabled;
81
82
  init(params?: Partial<WorkflowSnapServiceOptions>): void;
82
83
  dispose(): void;
84
+ get disabled(): boolean;
85
+ disable(): void;
86
+ enable(): void;
83
87
  private mountListener;
84
88
  private snapping;
85
89
  private calcSnapOffset;
package/dist/index.d.ts CHANGED
@@ -78,8 +78,12 @@ declare class WorkflowSnapService {
78
78
  private options;
79
79
  private snapEmitter;
80
80
  readonly onSnap: _flowgram_ai_utils.Event<SnapEvent>;
81
+ private _disabled;
81
82
  init(params?: Partial<WorkflowSnapServiceOptions>): void;
82
83
  dispose(): void;
84
+ get disabled(): boolean;
85
+ disable(): void;
86
+ enable(): void;
83
87
  private mountListener;
84
88
  private snapping;
85
89
  private calcSnapOffset;
package/dist/index.js CHANGED
@@ -48,12 +48,12 @@ var import_core3 = require("@flowgram.ai/core");
48
48
 
49
49
  // src/service.ts
50
50
  var import_inversify = require("inversify");
51
+ var import_utils = require("@flowgram.ai/utils");
52
+ var import_free_layout_core = require("@flowgram.ai/free-layout-core");
53
+ var import_free_layout_core2 = require("@flowgram.ai/free-layout-core");
51
54
  var import_document = require("@flowgram.ai/document");
52
55
  var import_document2 = require("@flowgram.ai/document");
53
56
  var import_core = require("@flowgram.ai/core");
54
- var import_free_layout_core = require("@flowgram.ai/free-layout-core");
55
- var import_free_layout_core2 = require("@flowgram.ai/free-layout-core");
56
- var import_utils = require("@flowgram.ai/utils");
57
57
 
58
58
  // src/constant.ts
59
59
  var SnapDefaultOptions = {
@@ -99,6 +99,7 @@ var WorkflowSnapService = class {
99
99
  this.disposers = [];
100
100
  this.snapEmitter = new import_utils.Emitter();
101
101
  this.onSnap = this.snapEmitter.event;
102
+ this._disabled = false;
102
103
  }
103
104
  init(params = {}) {
104
105
  this.options = {
@@ -110,15 +111,40 @@ var WorkflowSnapService = class {
110
111
  dispose() {
111
112
  this.disposers.forEach((disposer) => disposer.dispose());
112
113
  }
114
+ get disabled() {
115
+ return this._disabled;
116
+ }
117
+ disable() {
118
+ if (this._disabled) {
119
+ return;
120
+ }
121
+ this._disabled = true;
122
+ this.clear();
123
+ }
124
+ enable() {
125
+ if (!this._disabled) {
126
+ return;
127
+ }
128
+ this._disabled = false;
129
+ this.clear();
130
+ }
113
131
  mountListener() {
114
- const dragAdjusterDisposer = this.dragService.registerPosAdjuster(
115
- (params) => this.snapping({
116
- targetNodes: params.selectedNodes,
117
- position: params.position
118
- })
119
- );
132
+ const dragAdjusterDisposer = this.dragService.registerPosAdjuster((params) => {
133
+ const { selectedNodes: targetNodes, position } = params;
134
+ const isMultiSnapping = this.options.enableMultiSnapping ? false : targetNodes.length !== 1;
135
+ if (this._disabled || !this.options.enableEdgeSnapping || isMultiSnapping) {
136
+ return {
137
+ x: 0,
138
+ y: 0
139
+ };
140
+ }
141
+ return this.snapping({
142
+ targetNodes,
143
+ position
144
+ });
145
+ });
120
146
  const dragEndDisposer = this.dragService.onNodesDrag((event) => {
121
- if (event.type !== "onDragEnd") {
147
+ if (event.type !== "onDragEnd" || this._disabled) {
122
148
  return;
123
149
  }
124
150
  if (this.options.enableGridSnapping) {
@@ -135,19 +161,12 @@ var WorkflowSnapService = class {
135
161
  }
136
162
  snapping(params) {
137
163
  const { targetNodes, position } = params;
138
- const isMultiSnapping = this.options.enableMultiSnapping ? false : targetNodes.length !== 1;
139
- if (!this.options.enableEdgeSnapping || isMultiSnapping) {
140
- return {
141
- x: 0,
142
- y: 0
143
- };
144
- }
145
- const selectedBounds = this.getBounds(targetNodes);
164
+ const targetBounds = this.getBounds(targetNodes);
146
165
  const targetRect = new import_utils.Rectangle(
147
166
  position.x,
148
167
  position.y,
149
- selectedBounds.width,
150
- selectedBounds.height
168
+ targetBounds.width,
169
+ targetBounds.height
151
170
  );
152
171
  const snapNodeRects = this.getSnapNodeRects({
153
172
  targetNodes,
@@ -614,10 +633,10 @@ WorkflowSnapService = __decorateClass([
614
633
  // src/layer.tsx
615
634
  var import_react = __toESM(require("react"));
616
635
  var import_inversify2 = require("inversify");
636
+ var import_utils3 = require("@flowgram.ai/utils");
637
+ var import_free_layout_core3 = require("@flowgram.ai/free-layout-core");
617
638
  var import_document3 = require("@flowgram.ai/document");
618
639
  var import_core2 = require("@flowgram.ai/core");
619
- var import_free_layout_core3 = require("@flowgram.ai/free-layout-core");
620
- var import_utils3 = require("@flowgram.ai/utils");
621
640
  var WorkflowSnapLayer = class extends import_core2.Layer {
622
641
  constructor() {
623
642
  super(...arguments);
@@ -655,7 +674,7 @@ var WorkflowSnapLayer = class extends import_core2.Layer {
655
674
  className: `workflow-snap-edge-line ${className}`,
656
675
  "data-testid": "sdk.workflow.canvas.snap.edgeLine",
657
676
  "data-snap-line-id": id,
658
- "data-snap-line-sourceNode": sourceNode,
677
+ "data-snap-line-source-node": sourceNode,
659
678
  key: id,
660
679
  style: {
661
680
  top,
@@ -684,7 +703,7 @@ var WorkflowSnapLayer = class extends import_core2.Layer {
684
703
  className: `workflow-snap-align-line ${renderLine.className}`,
685
704
  "data-testid": "sdk.workflow.canvas.snap.alignLine",
686
705
  "data-snap-line-id": id,
687
- "data-snap-line-sourceNode": renderLine.sourceNode,
706
+ "data-snap-line-source-node": renderLine.sourceNode,
688
707
  key: id,
689
708
  style: {
690
709
  position: "absolute"
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/create-plugin.ts","../src/service.ts","../src/constant.ts","../src/utils.ts","../src/layer.tsx"],"sourcesContent":["export { createFreeSnapPlugin } from './create-plugin';\nexport { WorkflowSnapService } from './service';\n","import { definePluginCreator } from '@flowgram.ai/core';\n\nimport {\n FreeSnapPluginOptions,\n WorkflowSnapLayerOptions,\n WorkflowSnapServiceOptions,\n} from './type';\nimport { WorkflowSnapService } from './service';\nimport { WorkflowSnapLayer } from './layer';\nimport { SnapDefaultOptions } from './constant';\n\nexport const createFreeSnapPlugin = definePluginCreator<FreeSnapPluginOptions>({\n onBind({ bind }) {\n bind(WorkflowSnapService).toSelf().inSingletonScope();\n },\n onInit(ctx, opts) {\n const options: WorkflowSnapServiceOptions & WorkflowSnapLayerOptions = {\n ...SnapDefaultOptions,\n ...opts,\n };\n ctx.playground.registerLayer(WorkflowSnapLayer, options);\n const snapService = ctx.get<WorkflowSnapService>(WorkflowSnapService);\n snapService.init(options);\n },\n onDispose(ctx) {\n const snapService = ctx.get<WorkflowSnapService>(WorkflowSnapService);\n snapService.dispose();\n },\n});\n","import { inject, injectable } from 'inversify';\nimport { FlowNodeTransformData } from '@flowgram.ai/document';\nimport { FlowNodeBaseType } from '@flowgram.ai/document';\nimport { EntityManager, PlaygroundConfigEntity, TransformData } from '@flowgram.ai/core';\nimport { WorkflowNodeEntity, WorkflowDocument } from '@flowgram.ai/free-layout-core';\nimport { WorkflowDragService } from '@flowgram.ai/free-layout-core';\nimport { Disposable, Emitter, Rectangle } from '@flowgram.ai/utils';\nimport { IPoint } from '@flowgram.ai/utils';\n\nimport { isEqual, isGreaterThan, isLessThan, isLessThanOrEqual, isNumber } from './utils';\nimport type {\n SnapEvent,\n SnapHorizontalLine,\n SnapLines,\n SnapMidHorizontalLine,\n SnapMidVerticalLine,\n SnapVerticalLine,\n WorkflowSnapServiceOptions,\n AlignRects,\n AlignRect,\n AlignSpacing,\n SnapNodeRect,\n SnapEdgeLines,\n} from './type';\nimport { SnapDefaultOptions } from './constant';\n\n@injectable()\nexport class WorkflowSnapService {\n @inject(WorkflowDocument) private readonly document: WorkflowDocument;\n\n @inject(EntityManager) private readonly entityManager: EntityManager;\n\n @inject(WorkflowDragService)\n private readonly dragService: WorkflowDragService;\n\n @inject(PlaygroundConfigEntity)\n private readonly playgroundConfig: PlaygroundConfigEntity;\n\n private disposers: Disposable[] = [];\n\n private options: WorkflowSnapServiceOptions;\n\n private snapEmitter = new Emitter<SnapEvent>();\n\n public readonly onSnap = this.snapEmitter.event;\n\n public init(params: Partial<WorkflowSnapServiceOptions> = {}): void {\n this.options = {\n ...SnapDefaultOptions,\n ...params,\n };\n this.mountListener();\n }\n\n public dispose(): void {\n this.disposers.forEach(disposer => disposer.dispose());\n }\n\n private mountListener(): void {\n const dragAdjusterDisposer = this.dragService.registerPosAdjuster(params =>\n this.snapping({\n targetNodes: params.selectedNodes,\n position: params.position,\n }),\n );\n const dragEndDisposer = this.dragService.onNodesDrag(event => {\n if (event.type !== 'onDragEnd') {\n return;\n }\n if (this.options.enableGridSnapping) {\n this.gridSnapping({\n targetNodes: event.nodes,\n gridSize: this.options.gridSize,\n });\n }\n if (this.options.enableEdgeSnapping) {\n this.clear();\n }\n });\n this.disposers.push(dragAdjusterDisposer, dragEndDisposer);\n }\n\n private snapping(params: { targetNodes: WorkflowNodeEntity[]; position: IPoint }): IPoint {\n const { targetNodes: targetNodes, position } = params;\n\n const isMultiSnapping = this.options.enableMultiSnapping ? false : targetNodes.length !== 1;\n\n if (!this.options.enableEdgeSnapping || isMultiSnapping) {\n return {\n x: 0,\n y: 0,\n };\n }\n\n const selectedBounds = this.getBounds(targetNodes);\n\n const targetRect = new Rectangle(\n position.x,\n position.y,\n selectedBounds.width,\n selectedBounds.height,\n );\n\n const snapNodeRects = this.getSnapNodeRects({\n targetNodes,\n targetRect,\n });\n\n const { alignOffset, alignRects, alignSpacing } = this.calcAlignOffset({\n targetRect,\n alignThreshold: this.options.edgeThreshold,\n snapNodeRects,\n });\n\n const { snapOffset, snapEdgeLines } = this.calcSnapOffset({\n targetRect,\n edgeThreshold: this.options.edgeThreshold,\n snapNodeRects,\n });\n\n const offset: IPoint = {\n x: snapOffset.x || alignOffset.x,\n y: snapOffset.y || alignOffset.y,\n };\n\n const snapRect = new Rectangle(\n position.x + offset.x,\n position.y + offset.y,\n targetRect.width,\n targetRect.height,\n );\n\n this.snapEmitter.fire({\n snapRect,\n snapEdgeLines,\n alignRects,\n alignSpacing,\n });\n\n return offset;\n }\n\n private calcSnapOffset(params: {\n snapNodeRects: SnapNodeRect[];\n targetRect: Rectangle;\n edgeThreshold: number;\n }): {\n snapOffset: IPoint;\n snapEdgeLines: SnapEdgeLines;\n } {\n const { snapNodeRects, edgeThreshold, targetRect } = params;\n\n const snapLines = this.getSnapLines({\n snapNodeRects,\n });\n\n // 找到最近的线条\n const topYClosestLine = snapLines.horizontal.find(line =>\n isLessThanOrEqual(Math.abs(line.y - targetRect.top), edgeThreshold),\n );\n const bottomYClosestLine = snapLines.horizontal.find(line =>\n isLessThanOrEqual(Math.abs(line.y - targetRect.bottom), edgeThreshold),\n );\n const leftXClosestLine = snapLines.vertical.find(line =>\n isLessThanOrEqual(Math.abs(line.x - targetRect.left), edgeThreshold),\n );\n const rightXClosestLine = snapLines.vertical.find(line =>\n isLessThanOrEqual(Math.abs(line.x - targetRect.right), edgeThreshold),\n );\n const midYClosestLine = snapLines.midHorizontal.find(line =>\n isLessThanOrEqual(Math.abs(line.y - targetRect.center.y), edgeThreshold),\n );\n const midXClosestLine = snapLines.midVertical.find(line =>\n isLessThanOrEqual(Math.abs(line.x - targetRect.center.x), edgeThreshold),\n );\n\n // 计算最近坐标\n const topYClosest = topYClosestLine?.y;\n const bottomYClosest = isNumber(bottomYClosestLine?.y)\n ? bottomYClosestLine!.y - targetRect.height\n : undefined;\n const leftXClosest = leftXClosestLine?.x;\n const rightXClosest = isNumber(rightXClosestLine?.x)\n ? rightXClosestLine!.x - targetRect.width\n : undefined;\n const midYClosest = isNumber(midYClosestLine?.y)\n ? midYClosestLine!.y - targetRect.height / 2\n : undefined;\n const midXClosest = isNumber(midXClosestLine?.x)\n ? midXClosestLine!.x - targetRect.width / 2\n : undefined;\n\n // 吸附后坐标,按优先级取值\n const snappingPosition = {\n x: midXClosest ?? leftXClosest ?? rightXClosest ?? targetRect.x,\n y: midYClosest ?? topYClosest ?? bottomYClosest ?? targetRect.y,\n };\n\n // 吸附修正偏移量\n const snapOffset: IPoint = {\n x: snappingPosition.x - targetRect.x,\n y: snappingPosition.y - targetRect.y,\n };\n\n // 生效的吸附线条\n const snapEdgeLines: SnapEdgeLines = {\n top: isEqual(topYClosest, snappingPosition.y) ? topYClosestLine : undefined,\n bottom: isEqual(bottomYClosest, snappingPosition.y) ? bottomYClosestLine : undefined,\n left: isEqual(leftXClosest, snappingPosition.x) ? leftXClosestLine : undefined,\n right: isEqual(rightXClosest, snappingPosition.x) ? rightXClosestLine : undefined,\n midVertical: isEqual(midXClosest, snappingPosition.x) ? midXClosestLine : undefined,\n midHorizontal: isEqual(midYClosest, snappingPosition.y) ? midYClosestLine : undefined,\n };\n\n return { snapOffset, snapEdgeLines };\n }\n\n private gridSnapping(params: { gridSize: number; targetNodes: WorkflowNodeEntity[] }): void {\n const { gridSize, targetNodes } = params;\n const rect = this.getBounds(targetNodes);\n const snap = (value: number) => Math.round(value / gridSize) * gridSize;\n const snappedPosition: IPoint = {\n x: snap(rect.x),\n y: snap(rect.y),\n };\n const offset: IPoint = {\n x: snappedPosition.x - rect.x,\n y: snappedPosition.y - rect.y,\n };\n targetNodes.forEach(node =>\n this.updateNodePositionWithOffset({\n node,\n offset,\n }),\n );\n }\n\n private clear() {\n this.snapEmitter.fire({\n snapEdgeLines: {},\n snapRect: Rectangle.EMPTY,\n alignRects: {\n top: [],\n bottom: [],\n left: [],\n right: [],\n },\n alignSpacing: {},\n });\n }\n\n private getSnapLines(params: { snapNodeRects: SnapNodeRect[] }): SnapLines {\n const { snapNodeRects } = params;\n const horizontalLines: SnapHorizontalLine[] = [];\n const verticalLines: SnapVerticalLine[] = [];\n const midHorizontalLines: SnapMidHorizontalLine[] = [];\n const midVerticalLines: SnapMidVerticalLine[] = [];\n\n snapNodeRects.forEach(snapNodeRect => {\n const nodeBounds = snapNodeRect.rect;\n const nodeCenter = nodeBounds.center;\n // 边缘横线\n const top: SnapHorizontalLine = {\n y: nodeBounds.top,\n sourceNodeId: snapNodeRect.id,\n };\n const bottom: SnapHorizontalLine = {\n y: nodeBounds.bottom,\n sourceNodeId: snapNodeRect.id,\n };\n // 边缘竖线\n const left: SnapVerticalLine = {\n x: nodeBounds.left,\n sourceNodeId: snapNodeRect.id,\n };\n const right: SnapVerticalLine = {\n x: nodeBounds.right,\n sourceNodeId: snapNodeRect.id,\n };\n // 中间横线\n const midHorizontal: SnapMidHorizontalLine = {\n y: nodeCenter.y,\n sourceNodeId: snapNodeRect.id,\n };\n // 中间竖线\n const midVertical: SnapMidVerticalLine = {\n x: nodeCenter.x,\n sourceNodeId: snapNodeRect.id,\n };\n horizontalLines.push(top, bottom);\n verticalLines.push(left, right);\n midHorizontalLines.push(midHorizontal);\n midVerticalLines.push(midVertical);\n });\n\n return {\n horizontal: horizontalLines,\n vertical: verticalLines,\n midHorizontal: midHorizontalLines,\n midVertical: midVerticalLines,\n };\n }\n\n private getAvailableNodes(params: {\n targetNodes: WorkflowNodeEntity[];\n targetRect: Rectangle;\n }): WorkflowNodeEntity[] {\n const { targetNodes, targetRect } = params;\n\n const targetCenter = targetRect.center;\n const targetContainerId = targetNodes[0].parent?.id ?? this.document.root.id;\n\n const disabledNodeIds = targetNodes.map(n => n.id);\n disabledNodeIds.push(FlowNodeBaseType.ROOT);\n const availableNodes = this.nodes\n .filter(n => n.parent?.id === targetContainerId)\n .filter(n => !disabledNodeIds.includes(n.id))\n .sort((nodeA, nodeB) => {\n const nodeCenterA = nodeA.getData(FlowNodeTransformData)!.bounds.center;\n const nodeCenterB = nodeB.getData(FlowNodeTransformData)!.bounds.center;\n // 距离越近优先级越高\n const distanceA =\n Math.abs(nodeCenterA.x - targetCenter.x) + Math.abs(nodeCenterA.y - targetCenter.y);\n const distanceB =\n Math.abs(nodeCenterB.x - targetCenter.x) + Math.abs(nodeCenterB.y - targetCenter.y);\n return distanceA - distanceB;\n });\n return availableNodes;\n }\n\n private viewRect(): Rectangle {\n const { width, height, scrollX, scrollY, zoom } = this.playgroundConfig.config;\n return new Rectangle(scrollX / zoom, scrollY / zoom, width / zoom, height / zoom);\n }\n\n private getSnapNodeRects(params: {\n targetNodes: WorkflowNodeEntity[];\n targetRect: Rectangle;\n }): SnapNodeRect[] {\n const availableNodes = this.getAvailableNodes(params);\n const viewRect = this.viewRect();\n return availableNodes\n .map(node => {\n const snapNodeRect: SnapNodeRect = {\n id: node.id,\n rect: node.getData(FlowNodeTransformData).bounds,\n entity: node,\n };\n if (\n this.options.enableOnlyViewportSnapping &&\n node.parent?.flowNodeType === FlowNodeBaseType.ROOT &&\n !Rectangle.intersects(viewRect, snapNodeRect.rect)\n ) {\n // 最外层节点仅包含当前可见节点\n return;\n }\n return snapNodeRect;\n })\n .filter(Boolean) as SnapNodeRect[];\n }\n\n private get nodes(): WorkflowNodeEntity[] {\n return this.entityManager.getEntities<WorkflowNodeEntity>(WorkflowNodeEntity);\n }\n\n private getBounds(nodes: WorkflowNodeEntity[]): Rectangle {\n if (nodes.length === 0) {\n return Rectangle.EMPTY;\n }\n return Rectangle.enlarge(nodes.map(n => n.getData(FlowNodeTransformData)!.bounds));\n }\n\n private updateNodePositionWithOffset(params: { node: WorkflowNodeEntity; offset: IPoint }): void {\n const { node, offset } = params;\n const transform = node.getData(TransformData);\n const positionWithOffset: IPoint = {\n x: transform.position.x + offset.x,\n y: transform.position.y + offset.y,\n };\n if (node.collapsedChildren?.length > 0) {\n // 嵌套情况下需将子节点 transform 设为 dirty\n node.collapsedChildren.forEach(childNode => {\n const childNodeTransformData =\n childNode.getData<FlowNodeTransformData>(FlowNodeTransformData);\n childNodeTransformData.fireChange();\n });\n }\n transform.update({\n position: positionWithOffset,\n });\n }\n\n private calcAlignOffset(params: {\n snapNodeRects: SnapNodeRect[];\n targetRect: Rectangle;\n alignThreshold: number;\n }): {\n alignOffset: IPoint;\n alignRects: AlignRects;\n alignSpacing: AlignSpacing;\n } {\n const { snapNodeRects, targetRect, alignThreshold } = params;\n\n const alignRects = this.getAlignRects({\n targetRect,\n snapNodeRects,\n });\n\n const alignSpacing = this.calcAlignSpacing({\n targetRect,\n alignRects,\n });\n\n let topY: number | undefined;\n let bottomY: number | undefined;\n let leftX: number | undefined;\n let rightX: number | undefined;\n let midY: number | undefined;\n let midX: number | undefined;\n\n if (alignSpacing.top) {\n const topAlignY = alignRects.top[0].rect.bottom + alignSpacing.top;\n const isAlignTop = isLessThanOrEqual(Math.abs(targetRect.top - topAlignY), alignThreshold);\n if (isAlignTop) {\n // 生效\n topY = topAlignY;\n } else {\n // 失效\n alignSpacing.top = undefined;\n }\n }\n if (alignSpacing.bottom) {\n const bottomAlignY = alignRects.bottom[0].rect.top - alignSpacing.bottom;\n const isAlignBottom = isLessThan(Math.abs(targetRect.bottom - bottomAlignY), alignThreshold);\n if (isAlignBottom) {\n bottomY = bottomAlignY - targetRect.height;\n } else {\n alignSpacing.bottom = undefined;\n }\n }\n if (alignSpacing.left) {\n const leftAlignX = alignRects.left[0].rect.right + alignSpacing.left;\n const isAlignLeft = isLessThanOrEqual(Math.abs(targetRect.left - leftAlignX), alignThreshold);\n if (isAlignLeft) {\n leftX = leftAlignX;\n } else {\n alignSpacing.left = undefined;\n }\n }\n if (alignSpacing.right) {\n const rightAlignX = alignRects.right[0].rect.left - alignSpacing.right;\n const isAlignRight = isLessThanOrEqual(\n Math.abs(targetRect.right - rightAlignX),\n alignThreshold,\n );\n if (isAlignRight) {\n rightX = rightAlignX - targetRect.width;\n } else {\n alignSpacing.right = undefined;\n }\n }\n if (alignSpacing.midHorizontal) {\n const leftAlignX = alignRects.left[0].rect.right + alignSpacing.midHorizontal;\n const isAlignMidHorizontal = isLessThanOrEqual(\n Math.abs(targetRect.left - leftAlignX),\n alignThreshold,\n );\n if (isAlignMidHorizontal) {\n midX = leftAlignX;\n } else {\n alignSpacing.midHorizontal = undefined;\n }\n }\n if (alignSpacing.midVertical) {\n const topAlignY = alignRects.top[0].rect.bottom + alignSpacing.midVertical;\n const isAlignMidVertical = isLessThanOrEqual(\n Math.abs(targetRect.top - topAlignY),\n alignThreshold,\n );\n if (isAlignMidVertical) {\n midY = topAlignY;\n } else {\n alignSpacing.midVertical = undefined;\n }\n }\n\n const alignPosition: IPoint = {\n x: midX ?? leftX ?? rightX ?? targetRect.x,\n y: midY ?? topY ?? bottomY ?? targetRect.y,\n };\n\n const alignOffset: IPoint = {\n x: alignPosition.x - targetRect.x,\n y: alignPosition.y - targetRect.y,\n };\n\n return { alignOffset, alignRects, alignSpacing };\n }\n\n private calcAlignSpacing(params: {\n targetRect: Rectangle;\n alignRects: AlignRects;\n }): AlignSpacing {\n const { targetRect, alignRects } = params;\n\n const topSpacing = this.getDirectionAlignSpacing({\n rects: alignRects.top,\n isHorizontal: false,\n });\n const bottomSpacing = this.getDirectionAlignSpacing({\n rects: alignRects.bottom,\n isHorizontal: false,\n });\n const leftSpacing = this.getDirectionAlignSpacing({\n rects: alignRects.left,\n isHorizontal: true,\n });\n const rightSpacing = this.getDirectionAlignSpacing({\n rects: alignRects.right,\n isHorizontal: true,\n });\n const midHorizontalSpacing = this.getMidAlignSpacing({\n rectA: alignRects.left[0]?.rect,\n rectB: alignRects.right[0]?.rect,\n targetRect,\n isHorizontal: true,\n });\n const midVerticalSpacing = this.getMidAlignSpacing({\n rectA: alignRects.top[0]?.rect,\n rectB: alignRects.bottom[0]?.rect,\n targetRect,\n isHorizontal: false,\n });\n return {\n top: topSpacing,\n bottom: bottomSpacing,\n left: leftSpacing,\n right: rightSpacing,\n midHorizontal: midHorizontalSpacing,\n midVertical: midVerticalSpacing,\n };\n }\n\n private getAlignRects(params: {\n targetRect: Rectangle;\n snapNodeRects: SnapNodeRect[];\n }): AlignRects {\n const { targetRect, snapNodeRects } = params;\n\n const topVerticalRects: AlignRect[] = [];\n const bottomVerticalRects: AlignRect[] = [];\n const leftHorizontalRects: AlignRect[] = [];\n const rightHorizontalRects: AlignRect[] = [];\n\n snapNodeRects.forEach(snapNodeRect => {\n const nodeRect = snapNodeRect.rect;\n const { isVerticalIntersection, isHorizontalIntersection, isIntersection } =\n this.intersection(nodeRect, targetRect);\n if (isIntersection) {\n // 忽略重叠的节点\n return;\n } else if (isVerticalIntersection) {\n // 垂直重合\n if (isGreaterThan(nodeRect.center.y, targetRect.center.y)) {\n // 下方\n bottomVerticalRects.push({\n rect: nodeRect,\n sourceNodeId: snapNodeRect.id,\n });\n } else {\n // 上方\n topVerticalRects.push({\n rect: nodeRect,\n sourceNodeId: snapNodeRect.id,\n });\n }\n } else if (isHorizontalIntersection) {\n // 水平重合\n if (isGreaterThan(nodeRect.center.x, targetRect.center.x)) {\n // 右方\n rightHorizontalRects.push({\n rect: nodeRect,\n sourceNodeId: snapNodeRect.id,\n });\n } else {\n // 左方\n leftHorizontalRects.push({\n rect: nodeRect,\n sourceNodeId: snapNodeRect.id,\n });\n }\n }\n });\n\n return {\n top: topVerticalRects,\n bottom: bottomVerticalRects,\n left: leftHorizontalRects,\n right: rightHorizontalRects,\n };\n }\n\n private getMidAlignSpacing(params: {\n rectA?: Rectangle;\n rectB?: Rectangle;\n targetRect: Rectangle;\n isHorizontal: boolean;\n }): number | undefined {\n const { rectA, rectB, targetRect, isHorizontal } = params;\n if (!rectA || !rectB) {\n return;\n }\n const { isVerticalIntersection, isHorizontalIntersection, isIntersection } = this.intersection(\n rectA,\n rectB,\n );\n if (isIntersection) {\n return;\n }\n if (isHorizontal && isHorizontalIntersection && !isVerticalIntersection) {\n const betweenSpacing = Math.min(\n Math.abs(rectA.left - rectB.right),\n Math.abs(rectA.right - rectB.left),\n );\n return (betweenSpacing - targetRect.width) / 2;\n } else if (!isHorizontal && isVerticalIntersection && !isHorizontalIntersection) {\n const betweenSpacing = Math.min(\n Math.abs(rectA.top - rectB.bottom),\n Math.abs(rectA.bottom - rectB.top),\n );\n return (betweenSpacing - targetRect.height) / 2;\n }\n }\n\n private getDirectionAlignSpacing(params: {\n rects: AlignRect[];\n isHorizontal: boolean;\n }): number | undefined {\n const { rects, isHorizontal } = params;\n if (rects.length < 2) {\n // 非法情况\n return;\n }\n const rectA = rects[0].rect;\n const rectB = rects[1].rect;\n\n const { isVerticalIntersection, isHorizontalIntersection, isIntersection } = this.intersection(\n rectA,\n rectB,\n );\n\n if (isIntersection) {\n // 非法情况:重叠\n return;\n }\n if (isHorizontal && isHorizontalIntersection && !isVerticalIntersection) {\n return Math.min(Math.abs(rectA.left - rectB.right), Math.abs(rectA.right - rectB.left));\n } else if (!isHorizontal && isVerticalIntersection && !isHorizontalIntersection) {\n return Math.min(Math.abs(rectA.top - rectB.bottom), Math.abs(rectA.bottom - rectB.top));\n }\n return;\n }\n\n private intersection(\n rectA: Rectangle,\n rectB: Rectangle,\n ): {\n isHorizontalIntersection: boolean;\n isVerticalIntersection: boolean;\n isIntersection: boolean;\n } {\n const isVerticalIntersection =\n isLessThan(rectA.left, rectB.right) && isGreaterThan(rectA.right, rectB.left);\n const isHorizontalIntersection =\n isLessThan(rectA.top, rectB.bottom) && isGreaterThan(rectA.bottom, rectB.top);\n const isIntersection = isHorizontalIntersection && isVerticalIntersection;\n\n return {\n isHorizontalIntersection,\n isVerticalIntersection,\n isIntersection,\n };\n }\n}\n","import type { WorkflowSnapLayerOptions, WorkflowSnapServiceOptions } from './type';\n\nexport const SnapDefaultOptions: WorkflowSnapServiceOptions & WorkflowSnapLayerOptions = {\n enableEdgeSnapping: true,\n edgeThreshold: 7,\n enableGridSnapping: false,\n gridSize: 20,\n enableMultiSnapping: false,\n enableOnlyViewportSnapping: true,\n edgeColor: '#4E40E5',\n alignColor: '#4E40E5',\n edgeLineWidth: 2,\n alignLineWidth: 2,\n alignCrossWidth: 16,\n};\n\nexport const Epsilon = 0.00001;\n","import { Epsilon } from './constant';\n\n/** 检查浮点数 a 是否等于 b */\nexport const isEqual = (a: number | undefined, b: number | undefined): boolean => {\n if (a === undefined || b === undefined) {\n return false;\n }\n // 检查 a 和 b 的差的绝对值是否小于 Epsilon\n return Math.abs(a - b) < Epsilon;\n};\n\n/** 检查浮点数 a 是否小于 b */\nexport const isLessThan = (a: number | undefined, b: number | undefined): boolean => {\n if (a === undefined || b === undefined) {\n return false;\n }\n // 检查 a 是否显著小于 b\n return b - a > Epsilon;\n};\n\n/** 检查浮点数 a 是否大于 b */\nexport const isGreaterThan = (a: number | undefined, b: number | undefined): boolean => {\n if (a === undefined || b === undefined) {\n return false;\n }\n return a - b > Epsilon;\n};\n\n/** 检查浮点数 a 是否小于等于 b */\nexport const isLessThanOrEqual = (a: number | undefined, b: number | undefined): boolean =>\n isEqual(a, b) || isLessThan(a, b);\n\n/** 检查浮点数 a 是否大于等于 b */\nexport const isGreaterThanOrEqual = (a: number | undefined, b: number | undefined): boolean =>\n isEqual(a, b) || isGreaterThan(a, b);\n\n/** 检查值是否是数字类型 */\nexport const isNumber = (value: unknown): value is number =>\n typeof value === 'number' && !isNaN(value);\n","import React from 'react';\n\nimport { inject, injectable } from 'inversify';\nimport { FlowNodeTransformData } from '@flowgram.ai/document';\nimport { Layer } from '@flowgram.ai/core';\nimport { WorkflowDocument } from '@flowgram.ai/free-layout-core';\nimport { domUtils } from '@flowgram.ai/utils';\nimport { Rectangle } from '@flowgram.ai/utils';\n\nimport { isEqual, isGreaterThan, isNumber } from './utils';\nimport { AlignRect, SnapEvent, WorkflowSnapLayerOptions } from './type';\nimport { WorkflowSnapService } from './service';\n\ninterface SnapRenderLine {\n className: string;\n sourceNode: string;\n top: number;\n left: number;\n width: number;\n height: number;\n dashed?: boolean;\n}\n\n@injectable()\nexport class WorkflowSnapLayer extends Layer<WorkflowSnapLayerOptions> {\n public static type = 'WorkflowSnapLayer';\n\n @inject(WorkflowDocument) private readonly document: WorkflowDocument;\n\n @inject(WorkflowSnapService) private readonly service: WorkflowSnapService;\n\n public readonly node = domUtils.createDivWithClass(\n 'gedit-playground-layer gedit-flow-snap-layer',\n );\n\n private edgeLines: SnapRenderLine[] = [];\n\n private alignLines: SnapRenderLine[] = [];\n\n public onReady(): void {\n this.node.style.zIndex = '9999';\n this.toDispose.pushAll([\n this.service.onSnap((event: SnapEvent) => {\n this.edgeLines = this.calcEdgeLines(event);\n this.alignLines = this.calcAlignLines(event);\n this.render();\n }),\n ]);\n }\n\n public render(): JSX.Element {\n return (\n <>\n {this.alignLines.length > 0 && (\n <div className=\"workflow-snap-align-lines\">{this.renderAlignLines()}</div>\n )}\n {this.edgeLines.length > 0 && (\n <div className=\"workflow-snap-edge-lines\">{this.renderEdgeLines()}</div>\n )}\n </>\n );\n }\n\n public onZoom(scale: number): void {\n this.node.style.transform = `scale(${scale})`;\n }\n\n private renderEdgeLines(): JSX.Element[] {\n return this.edgeLines.map((renderLine: SnapRenderLine) => {\n const { className, sourceNode, top, left, width, height, dashed } = renderLine;\n const id = `${className}-${sourceNode}-${top}-${left}-${width}-${height}`;\n const isHorizontal = width < height;\n const border = `${this.options.edgeLineWidth}px ${dashed ? 'dashed' : 'solid'} ${\n this.options.edgeColor\n }`;\n return (\n <div\n className={`workflow-snap-edge-line ${className}`}\n data-testid=\"sdk.workflow.canvas.snap.edgeLine\"\n data-snap-line-id={id}\n data-snap-line-sourceNode={sourceNode}\n key={id}\n style={{\n top,\n left,\n width,\n height,\n position: 'absolute',\n borderLeft: isHorizontal ? border : 'none',\n borderTop: !isHorizontal ? border : 'none',\n }}\n />\n );\n });\n }\n\n private renderAlignLines(): JSX.Element[] {\n return this.alignLines.map((renderLine: SnapRenderLine) => {\n const id = `${renderLine.className}-${renderLine.sourceNode}-${renderLine.top}-${renderLine.left}-${renderLine.width}-${renderLine.height}`;\n const isHorizontal = isGreaterThan(renderLine.width, renderLine.height);\n const alignLineWidth = this.options.alignLineWidth; // 整体线条粗细\n const alignCrossWidth = this.options.alignCrossWidth; // 工字形横线的长度\n\n // 调整渲染位置以保持居中\n const adjustedTop = isHorizontal ? renderLine.top - alignLineWidth / 2 : renderLine.top;\n const adjustedLeft = isHorizontal ? renderLine.left : renderLine.left - alignLineWidth / 2;\n\n return (\n <div\n className={`workflow-snap-align-line ${renderLine.className}`}\n data-testid=\"sdk.workflow.canvas.snap.alignLine\"\n data-snap-line-id={id}\n data-snap-line-sourceNode={renderLine.sourceNode}\n key={id}\n style={{\n position: 'absolute',\n }}\n >\n {/* 主线 */}\n <div\n style={{\n position: 'absolute',\n top: adjustedTop,\n left: adjustedLeft,\n width: isHorizontal ? renderLine.width : alignLineWidth,\n height: isHorizontal ? alignLineWidth : renderLine.height,\n backgroundColor: this.options.alignColor,\n }}\n />\n {/* 左端或上端横线 */}\n <div\n style={{\n position: 'absolute',\n top: isHorizontal\n ? adjustedTop - (alignCrossWidth - alignLineWidth) / 2\n : adjustedTop,\n left: isHorizontal\n ? adjustedLeft\n : adjustedLeft - (alignCrossWidth - alignLineWidth) / 2,\n width: isHorizontal ? alignLineWidth : alignCrossWidth,\n height: isHorizontal ? alignCrossWidth : alignLineWidth,\n backgroundColor: this.options.alignColor,\n }}\n />\n {/* 右端或下端横线 */}\n <div\n style={{\n position: 'absolute',\n top: isHorizontal\n ? adjustedTop - (alignCrossWidth - alignLineWidth) / 2\n : adjustedTop + renderLine.height - alignLineWidth,\n left: isHorizontal\n ? adjustedLeft + renderLine.width - alignLineWidth\n : adjustedLeft - (alignCrossWidth - alignLineWidth) / 2,\n width: isHorizontal ? alignLineWidth : alignCrossWidth,\n height: isHorizontal ? alignCrossWidth : alignLineWidth,\n backgroundColor: this.options.alignColor,\n }}\n />\n </div>\n );\n });\n }\n\n private calcEdgeLines(event: SnapEvent): SnapRenderLine[] {\n const { alignRects, snapRect, snapEdgeLines } = event;\n const edgeLines: SnapRenderLine[] = [];\n\n const topFullAlign = this.directionFullAlign({\n alignRects: alignRects.top,\n targetRect: snapRect,\n isVertical: true,\n });\n const bottomFullAlign = this.directionFullAlign({\n alignRects: alignRects.bottom,\n targetRect: snapRect,\n isVertical: true,\n });\n const leftFullAlign = this.directionFullAlign({\n alignRects: alignRects.left,\n targetRect: snapRect,\n isVertical: false,\n });\n const rightFullAlign = this.directionFullAlign({\n alignRects: alignRects.right,\n targetRect: snapRect,\n isVertical: false,\n });\n\n // 处理顶部对齐\n if (topFullAlign) {\n const top = topFullAlign.rect.top;\n const height = bottomFullAlign\n ? snapRect.bottom - snapRect.height / 2 - top\n : snapRect.bottom - top;\n const width = this.options.edgeLineWidth;\n const lineData = {\n top,\n width,\n height,\n };\n edgeLines.push({\n className: 'edge-full-top-left',\n sourceNode: topFullAlign.sourceNodeId,\n left: snapRect.left,\n ...lineData,\n });\n edgeLines.push({\n className: 'edge-full-top-right',\n sourceNode: topFullAlign.sourceNodeId,\n left: snapRect.right,\n ...lineData,\n });\n edgeLines.push({\n className: 'edge-full-top-mid',\n sourceNode: topFullAlign.sourceNodeId,\n left: snapRect.left + snapRect.width / 2,\n dashed: true,\n ...lineData,\n });\n }\n\n // 处理底部对齐\n if (bottomFullAlign) {\n const top = topFullAlign ? snapRect.top + snapRect.height / 2 : snapRect.top;\n const height = bottomFullAlign.rect.bottom - top;\n const width = this.options.edgeLineWidth;\n const lineData = {\n top,\n width,\n height,\n };\n edgeLines.push({\n className: 'edge-full-bottom-left',\n sourceNode: bottomFullAlign.sourceNodeId,\n left: snapRect.left,\n ...lineData,\n });\n edgeLines.push({\n className: 'edge-full-bottom-right',\n sourceNode: bottomFullAlign.sourceNodeId,\n left: snapRect.right,\n ...lineData,\n });\n edgeLines.push({\n className: 'edge-full-bottom-mid',\n sourceNode: bottomFullAlign.sourceNodeId,\n left: snapRect.left + snapRect.width / 2,\n dashed: true,\n ...lineData,\n });\n }\n\n // 处理左侧对齐\n if (leftFullAlign) {\n const left = leftFullAlign.rect.left;\n const width = rightFullAlign\n ? snapRect.right - snapRect.width / 2 - left\n : snapRect.right - left;\n const height = this.options.edgeLineWidth;\n const lineData = {\n left,\n width,\n height,\n };\n edgeLines.push({\n className: 'edge-full-left-top',\n sourceNode: leftFullAlign.sourceNodeId,\n top: snapRect.top,\n ...lineData,\n });\n edgeLines.push({\n className: 'edge-full-left-bottom',\n sourceNode: leftFullAlign.sourceNodeId,\n top: snapRect.bottom,\n ...lineData,\n });\n edgeLines.push({\n className: 'edge-full-left-mid',\n sourceNode: leftFullAlign.sourceNodeId,\n top: snapRect.top + snapRect.height / 2,\n dashed: true,\n ...lineData,\n });\n }\n\n // 处理右侧对齐\n if (rightFullAlign) {\n const left = leftFullAlign ? snapRect.left + snapRect.width / 2 : snapRect.left;\n const width = rightFullAlign.rect.right - left;\n const height = this.options.edgeLineWidth;\n const lineData = {\n left,\n width,\n height,\n };\n edgeLines.push({\n className: 'edge-full-right-top',\n sourceNode: rightFullAlign.sourceNodeId,\n top: snapRect.top,\n ...lineData,\n });\n edgeLines.push({\n className: 'edge-full-right-bottom',\n sourceNode: rightFullAlign.sourceNodeId,\n top: snapRect.bottom,\n ...lineData,\n });\n edgeLines.push({\n className: 'edge-full-right-mid',\n sourceNode: rightFullAlign.sourceNodeId,\n top: snapRect.top + snapRect.height / 2,\n dashed: true,\n ...lineData,\n });\n }\n\n const snappedEdgeLines = Object.entries(snapEdgeLines)\n .map(([direction, snapLine]) => {\n if (!snapLine) {\n return;\n }\n const sourceNode = this.document.getNode(snapLine.sourceNodeId);\n if (!sourceNode) {\n return;\n }\n const nodeRect = sourceNode.getData(FlowNodeTransformData).bounds;\n if (isNumber(snapLine.x)) {\n // 垂直\n const top = Math.min(nodeRect.top, snapRect.top);\n const bottom = Math.max(nodeRect.bottom, snapRect.bottom);\n const height = bottom - top;\n const left = snapLine.x;\n const width = this.options.edgeLineWidth;\n const isMidX = direction === 'midVertical';\n const lineData: SnapRenderLine = {\n className: `edge-snapped-${direction}`,\n sourceNode: snapLine.sourceNodeId,\n top,\n left,\n width,\n height,\n dashed: isMidX,\n };\n const onTop = top === nodeRect.top;\n if (onTop && topFullAlign) {\n return;\n }\n if (!onTop && bottomFullAlign) {\n return;\n }\n return lineData;\n } else if (isNumber(snapLine.y)) {\n // 水平\n const left = Math.min(nodeRect.left, snapRect.left);\n const right = Math.max(nodeRect.right, snapRect.right);\n const width = right - left;\n const top = snapLine.y;\n const height = this.options.edgeLineWidth;\n const isMidY = direction === 'midHorizontal';\n const lineData: SnapRenderLine = {\n className: `edge-snapped-${direction}`,\n sourceNode: snapLine.sourceNodeId,\n top,\n left,\n width,\n height,\n dashed: isMidY,\n };\n const onLeft = left === nodeRect.left;\n if (onLeft && leftFullAlign) {\n return;\n }\n if (!onLeft && rightFullAlign) {\n return;\n }\n return lineData;\n }\n })\n .filter(Boolean) as SnapRenderLine[];\n\n edgeLines.push(...snappedEdgeLines);\n\n return edgeLines;\n }\n\n private directionFullAlign(params: {\n alignRects: AlignRect[];\n targetRect: Rectangle;\n isVertical: boolean;\n }): AlignRect | undefined {\n const { alignRects, targetRect, isVertical } = params;\n let fullAlignIndex = -1;\n for (let i = 0; i < alignRects.length; i++) {\n const alignRect = alignRects[i];\n const prevRect = alignRects[i - 1]?.rect ?? targetRect;\n const isFullAlign = this.rectFullAlign(alignRect.rect, prevRect, isVertical);\n if (!isFullAlign) {\n // 未对齐则中断\n break; // 用 for 循环 + break 反而比 Array.findIndex 实现可读性更好\n }\n fullAlignIndex = i;\n }\n const fullAlignRect = alignRects[fullAlignIndex];\n return fullAlignRect;\n }\n\n private rectFullAlign(rectA: Rectangle, rectB: Rectangle, isVertical: boolean): boolean {\n if (isVertical) {\n return isEqual(rectA.left, rectB.left) && isEqual(rectA.right, rectB.right);\n } else {\n return isEqual(rectA.top, rectB.top) && isEqual(rectA.bottom, rectB.bottom);\n }\n }\n\n private calcAlignLines(event: SnapEvent): SnapRenderLine[] {\n const { alignRects, alignSpacing, snapRect } = event;\n\n const topAlignLines = this.calcDirectionAlignLines({\n alignRects: alignRects.top,\n targetRect: snapRect,\n isVertical: true,\n spacing: alignSpacing.midVertical ?? alignSpacing.top,\n });\n\n const bottomAlignLines = this.calcDirectionAlignLines({\n alignRects: alignRects.bottom,\n targetRect: snapRect,\n isVertical: true,\n spacing: alignSpacing.midVertical ?? alignSpacing.bottom,\n });\n\n const leftAlignLines = this.calcDirectionAlignLines({\n alignRects: alignRects.left,\n targetRect: snapRect,\n isVertical: false,\n spacing: alignSpacing.midHorizontal ?? alignSpacing.left,\n });\n\n const rightAlignLines = this.calcDirectionAlignLines({\n alignRects: alignRects.right,\n targetRect: snapRect,\n isVertical: false,\n spacing: alignSpacing.midHorizontal ?? alignSpacing.right,\n });\n\n return [...topAlignLines, ...bottomAlignLines, ...leftAlignLines, ...rightAlignLines];\n }\n\n private calcDirectionAlignLines(params: {\n alignRects: AlignRect[];\n targetRect: Rectangle;\n isVertical: boolean;\n spacing?: number;\n }) {\n const { alignRects, targetRect, isVertical, spacing } = params;\n const alignLines: SnapRenderLine[] = [];\n if (!spacing) {\n return alignLines;\n }\n for (let i = 0; i < alignRects.length; i++) {\n const alignRect = alignRects[i];\n const rect = alignRect.rect;\n const prevRect = alignRects[i - 1]?.rect ?? targetRect;\n\n const betweenSpacing = isVertical\n ? Math.min(Math.abs(prevRect.top - rect.bottom), Math.abs(prevRect.bottom - rect.top))\n : Math.min(Math.abs(prevRect.left - rect.right), Math.abs(prevRect.right - rect.left));\n if (!isEqual(betweenSpacing, spacing)) {\n // 不连续,需要中断\n break; // 因为要用到 break,所以不能用 Array.map()\n }\n if (isVertical) {\n const centerX = this.calcHorizontalIntersectionCenter(rect, targetRect);\n alignLines.push({\n className: 'align-vertical',\n sourceNode: alignRect.sourceNodeId,\n top: Math.min(rect.bottom, prevRect.bottom),\n left: centerX,\n width: 1,\n height: spacing,\n });\n } else {\n const centerY = this.calcVerticalIntersectionCenter(rect, targetRect);\n alignLines.push({\n className: 'align-horizontal',\n sourceNode: alignRect.sourceNodeId,\n top: centerY,\n left: Math.min(rect.right, prevRect.right),\n width: spacing,\n height: 1,\n });\n }\n }\n return alignLines;\n }\n\n private calcVerticalIntersectionCenter(rectA: Rectangle, rectB: Rectangle): number {\n const top = Math.max(rectA.top, rectB.top);\n const bottom = Math.min(rectA.bottom, rectB.bottom);\n return (top + bottom) / 2;\n }\n\n private calcHorizontalIntersectionCenter(rectA: Rectangle, rectB: Rectangle): number {\n const left = Math.max(rectA.left, rectB.left);\n const right = Math.min(rectA.right, rectB.right);\n return (left + right) / 2;\n }\n}\n"],"mappings":"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","names":["import_core","import_document","import_free_layout_core","import_inversify","import_document","import_core","import_free_layout_core","import_utils","React"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/create-plugin.ts","../src/service.ts","../src/constant.ts","../src/utils.ts","../src/layer.tsx"],"sourcesContent":["export { createFreeSnapPlugin } from './create-plugin';\nexport { WorkflowSnapService } from './service';\n","import { definePluginCreator } from '@flowgram.ai/core';\n\nimport {\n FreeSnapPluginOptions,\n WorkflowSnapLayerOptions,\n WorkflowSnapServiceOptions,\n} from './type';\nimport { WorkflowSnapService } from './service';\nimport { WorkflowSnapLayer } from './layer';\nimport { SnapDefaultOptions } from './constant';\n\nexport const createFreeSnapPlugin = definePluginCreator<FreeSnapPluginOptions>({\n onBind({ bind }) {\n bind(WorkflowSnapService).toSelf().inSingletonScope();\n },\n onInit(ctx, opts) {\n const options: WorkflowSnapServiceOptions & WorkflowSnapLayerOptions = {\n ...SnapDefaultOptions,\n ...opts,\n };\n ctx.playground.registerLayer(WorkflowSnapLayer, options);\n const snapService = ctx.get<WorkflowSnapService>(WorkflowSnapService);\n snapService.init(options);\n },\n onDispose(ctx) {\n const snapService = ctx.get<WorkflowSnapService>(WorkflowSnapService);\n snapService.dispose();\n },\n});\n","import { inject, injectable } from 'inversify';\nimport { Disposable, Emitter, Rectangle } from '@flowgram.ai/utils';\nimport { IPoint } from '@flowgram.ai/utils';\nimport { WorkflowNodeEntity, WorkflowDocument } from '@flowgram.ai/free-layout-core';\nimport { WorkflowDragService } from '@flowgram.ai/free-layout-core';\nimport { FlowNodeTransformData } from '@flowgram.ai/document';\nimport { FlowNodeBaseType } from '@flowgram.ai/document';\nimport { EntityManager, PlaygroundConfigEntity, TransformData } from '@flowgram.ai/core';\n\nimport { isEqual, isGreaterThan, isLessThan, isLessThanOrEqual, isNumber } from './utils';\nimport type {\n SnapEvent,\n SnapHorizontalLine,\n SnapLines,\n SnapMidHorizontalLine,\n SnapMidVerticalLine,\n SnapVerticalLine,\n WorkflowSnapServiceOptions,\n AlignRects,\n AlignRect,\n AlignSpacing,\n SnapNodeRect,\n SnapEdgeLines,\n} from './type';\nimport { SnapDefaultOptions } from './constant';\n\n@injectable()\nexport class WorkflowSnapService {\n @inject(WorkflowDocument) private readonly document: WorkflowDocument;\n\n @inject(EntityManager) private readonly entityManager: EntityManager;\n\n @inject(WorkflowDragService)\n private readonly dragService: WorkflowDragService;\n\n @inject(PlaygroundConfigEntity)\n private readonly playgroundConfig: PlaygroundConfigEntity;\n\n private disposers: Disposable[] = [];\n\n private options: WorkflowSnapServiceOptions;\n\n private snapEmitter = new Emitter<SnapEvent>();\n\n public readonly onSnap = this.snapEmitter.event;\n\n private _disabled = false;\n\n public init(params: Partial<WorkflowSnapServiceOptions> = {}): void {\n this.options = {\n ...SnapDefaultOptions,\n ...params,\n };\n this.mountListener();\n }\n\n public dispose(): void {\n this.disposers.forEach((disposer) => disposer.dispose());\n }\n\n public get disabled(): boolean {\n return this._disabled;\n }\n\n public disable(): void {\n if (this._disabled) {\n return;\n }\n this._disabled = true;\n this.clear();\n }\n\n public enable(): void {\n if (!this._disabled) {\n return;\n }\n this._disabled = false;\n this.clear();\n }\n\n private mountListener(): void {\n const dragAdjusterDisposer = this.dragService.registerPosAdjuster((params) => {\n const { selectedNodes: targetNodes, position } = params;\n const isMultiSnapping = this.options.enableMultiSnapping ? false : targetNodes.length !== 1;\n if (this._disabled || !this.options.enableEdgeSnapping || isMultiSnapping) {\n return {\n x: 0,\n y: 0,\n };\n }\n return this.snapping({\n targetNodes,\n position,\n });\n });\n const dragEndDisposer = this.dragService.onNodesDrag((event) => {\n if (event.type !== 'onDragEnd' || this._disabled) {\n return;\n }\n if (this.options.enableGridSnapping) {\n this.gridSnapping({\n targetNodes: event.nodes,\n gridSize: this.options.gridSize,\n });\n }\n if (this.options.enableEdgeSnapping) {\n this.clear();\n }\n });\n this.disposers.push(dragAdjusterDisposer, dragEndDisposer);\n }\n\n private snapping(params: { targetNodes: WorkflowNodeEntity[]; position: IPoint }): IPoint {\n const { targetNodes, position } = params;\n\n const targetBounds = this.getBounds(targetNodes);\n\n const targetRect = new Rectangle(\n position.x,\n position.y,\n targetBounds.width,\n targetBounds.height\n );\n\n const snapNodeRects = this.getSnapNodeRects({\n targetNodes,\n targetRect,\n });\n\n const { alignOffset, alignRects, alignSpacing } = this.calcAlignOffset({\n targetRect,\n alignThreshold: this.options.edgeThreshold,\n snapNodeRects,\n });\n\n const { snapOffset, snapEdgeLines } = this.calcSnapOffset({\n targetRect,\n edgeThreshold: this.options.edgeThreshold,\n snapNodeRects,\n });\n\n const offset: IPoint = {\n x: snapOffset.x || alignOffset.x,\n y: snapOffset.y || alignOffset.y,\n };\n\n const snapRect = new Rectangle(\n position.x + offset.x,\n position.y + offset.y,\n targetRect.width,\n targetRect.height\n );\n\n this.snapEmitter.fire({\n snapRect,\n snapEdgeLines,\n alignRects,\n alignSpacing,\n });\n\n return offset;\n }\n\n private calcSnapOffset(params: {\n snapNodeRects: SnapNodeRect[];\n targetRect: Rectangle;\n edgeThreshold: number;\n }): {\n snapOffset: IPoint;\n snapEdgeLines: SnapEdgeLines;\n } {\n const { snapNodeRects, edgeThreshold, targetRect } = params;\n\n const snapLines = this.getSnapLines({\n snapNodeRects,\n });\n\n // 找到最近的线条\n const topYClosestLine = snapLines.horizontal.find((line) =>\n isLessThanOrEqual(Math.abs(line.y - targetRect.top), edgeThreshold)\n );\n const bottomYClosestLine = snapLines.horizontal.find((line) =>\n isLessThanOrEqual(Math.abs(line.y - targetRect.bottom), edgeThreshold)\n );\n const leftXClosestLine = snapLines.vertical.find((line) =>\n isLessThanOrEqual(Math.abs(line.x - targetRect.left), edgeThreshold)\n );\n const rightXClosestLine = snapLines.vertical.find((line) =>\n isLessThanOrEqual(Math.abs(line.x - targetRect.right), edgeThreshold)\n );\n const midYClosestLine = snapLines.midHorizontal.find((line) =>\n isLessThanOrEqual(Math.abs(line.y - targetRect.center.y), edgeThreshold)\n );\n const midXClosestLine = snapLines.midVertical.find((line) =>\n isLessThanOrEqual(Math.abs(line.x - targetRect.center.x), edgeThreshold)\n );\n\n // 计算最近坐标\n const topYClosest = topYClosestLine?.y;\n const bottomYClosest = isNumber(bottomYClosestLine?.y)\n ? bottomYClosestLine!.y - targetRect.height\n : undefined;\n const leftXClosest = leftXClosestLine?.x;\n const rightXClosest = isNumber(rightXClosestLine?.x)\n ? rightXClosestLine!.x - targetRect.width\n : undefined;\n const midYClosest = isNumber(midYClosestLine?.y)\n ? midYClosestLine!.y - targetRect.height / 2\n : undefined;\n const midXClosest = isNumber(midXClosestLine?.x)\n ? midXClosestLine!.x - targetRect.width / 2\n : undefined;\n\n // 吸附后坐标,按优先级取值\n const snappingPosition = {\n x: midXClosest ?? leftXClosest ?? rightXClosest ?? targetRect.x,\n y: midYClosest ?? topYClosest ?? bottomYClosest ?? targetRect.y,\n };\n\n // 吸附修正偏移量\n const snapOffset: IPoint = {\n x: snappingPosition.x - targetRect.x,\n y: snappingPosition.y - targetRect.y,\n };\n\n // 生效的吸附线条\n const snapEdgeLines: SnapEdgeLines = {\n top: isEqual(topYClosest, snappingPosition.y) ? topYClosestLine : undefined,\n bottom: isEqual(bottomYClosest, snappingPosition.y) ? bottomYClosestLine : undefined,\n left: isEqual(leftXClosest, snappingPosition.x) ? leftXClosestLine : undefined,\n right: isEqual(rightXClosest, snappingPosition.x) ? rightXClosestLine : undefined,\n midVertical: isEqual(midXClosest, snappingPosition.x) ? midXClosestLine : undefined,\n midHorizontal: isEqual(midYClosest, snappingPosition.y) ? midYClosestLine : undefined,\n };\n\n return { snapOffset, snapEdgeLines };\n }\n\n private gridSnapping(params: { gridSize: number; targetNodes: WorkflowNodeEntity[] }): void {\n const { gridSize, targetNodes } = params;\n const rect = this.getBounds(targetNodes);\n const snap = (value: number) => Math.round(value / gridSize) * gridSize;\n const snappedPosition: IPoint = {\n x: snap(rect.x),\n y: snap(rect.y),\n };\n const offset: IPoint = {\n x: snappedPosition.x - rect.x,\n y: snappedPosition.y - rect.y,\n };\n targetNodes.forEach((node) =>\n this.updateNodePositionWithOffset({\n node,\n offset,\n })\n );\n }\n\n private clear() {\n this.snapEmitter.fire({\n snapEdgeLines: {},\n snapRect: Rectangle.EMPTY,\n alignRects: {\n top: [],\n bottom: [],\n left: [],\n right: [],\n },\n alignSpacing: {},\n });\n }\n\n private getSnapLines(params: { snapNodeRects: SnapNodeRect[] }): SnapLines {\n const { snapNodeRects } = params;\n const horizontalLines: SnapHorizontalLine[] = [];\n const verticalLines: SnapVerticalLine[] = [];\n const midHorizontalLines: SnapMidHorizontalLine[] = [];\n const midVerticalLines: SnapMidVerticalLine[] = [];\n\n snapNodeRects.forEach((snapNodeRect) => {\n const nodeBounds = snapNodeRect.rect;\n const nodeCenter = nodeBounds.center;\n // 边缘横线\n const top: SnapHorizontalLine = {\n y: nodeBounds.top,\n sourceNodeId: snapNodeRect.id,\n };\n const bottom: SnapHorizontalLine = {\n y: nodeBounds.bottom,\n sourceNodeId: snapNodeRect.id,\n };\n // 边缘竖线\n const left: SnapVerticalLine = {\n x: nodeBounds.left,\n sourceNodeId: snapNodeRect.id,\n };\n const right: SnapVerticalLine = {\n x: nodeBounds.right,\n sourceNodeId: snapNodeRect.id,\n };\n // 中间横线\n const midHorizontal: SnapMidHorizontalLine = {\n y: nodeCenter.y,\n sourceNodeId: snapNodeRect.id,\n };\n // 中间竖线\n const midVertical: SnapMidVerticalLine = {\n x: nodeCenter.x,\n sourceNodeId: snapNodeRect.id,\n };\n horizontalLines.push(top, bottom);\n verticalLines.push(left, right);\n midHorizontalLines.push(midHorizontal);\n midVerticalLines.push(midVertical);\n });\n\n return {\n horizontal: horizontalLines,\n vertical: verticalLines,\n midHorizontal: midHorizontalLines,\n midVertical: midVerticalLines,\n };\n }\n\n private getAvailableNodes(params: {\n targetNodes: WorkflowNodeEntity[];\n targetRect: Rectangle;\n }): WorkflowNodeEntity[] {\n const { targetNodes, targetRect } = params;\n\n const targetCenter = targetRect.center;\n const targetContainerId = targetNodes[0].parent?.id ?? this.document.root.id;\n\n const disabledNodeIds = targetNodes.map((n) => n.id);\n disabledNodeIds.push(FlowNodeBaseType.ROOT);\n const availableNodes = this.nodes\n .filter((n) => n.parent?.id === targetContainerId)\n .filter((n) => !disabledNodeIds.includes(n.id))\n .sort((nodeA, nodeB) => {\n const nodeCenterA = nodeA.getData(FlowNodeTransformData)!.bounds.center;\n const nodeCenterB = nodeB.getData(FlowNodeTransformData)!.bounds.center;\n // 距离越近优先级越高\n const distanceA =\n Math.abs(nodeCenterA.x - targetCenter.x) + Math.abs(nodeCenterA.y - targetCenter.y);\n const distanceB =\n Math.abs(nodeCenterB.x - targetCenter.x) + Math.abs(nodeCenterB.y - targetCenter.y);\n return distanceA - distanceB;\n });\n return availableNodes;\n }\n\n private viewRect(): Rectangle {\n const { width, height, scrollX, scrollY, zoom } = this.playgroundConfig.config;\n return new Rectangle(scrollX / zoom, scrollY / zoom, width / zoom, height / zoom);\n }\n\n private getSnapNodeRects(params: {\n targetNodes: WorkflowNodeEntity[];\n targetRect: Rectangle;\n }): SnapNodeRect[] {\n const availableNodes = this.getAvailableNodes(params);\n const viewRect = this.viewRect();\n return availableNodes\n .map((node) => {\n const snapNodeRect: SnapNodeRect = {\n id: node.id,\n rect: node.getData(FlowNodeTransformData).bounds,\n entity: node,\n };\n if (\n this.options.enableOnlyViewportSnapping &&\n node.parent?.flowNodeType === FlowNodeBaseType.ROOT &&\n !Rectangle.intersects(viewRect, snapNodeRect.rect)\n ) {\n // 最外层节点仅包含当前可见节点\n return;\n }\n return snapNodeRect;\n })\n .filter(Boolean) as SnapNodeRect[];\n }\n\n private get nodes(): WorkflowNodeEntity[] {\n return this.entityManager.getEntities<WorkflowNodeEntity>(WorkflowNodeEntity);\n }\n\n private getBounds(nodes: WorkflowNodeEntity[]): Rectangle {\n if (nodes.length === 0) {\n return Rectangle.EMPTY;\n }\n return Rectangle.enlarge(nodes.map((n) => n.getData(FlowNodeTransformData)!.bounds));\n }\n\n private updateNodePositionWithOffset(params: { node: WorkflowNodeEntity; offset: IPoint }): void {\n const { node, offset } = params;\n const transform = node.getData(TransformData);\n const positionWithOffset: IPoint = {\n x: transform.position.x + offset.x,\n y: transform.position.y + offset.y,\n };\n if (node.collapsedChildren?.length > 0) {\n // 嵌套情况下需将子节点 transform 设为 dirty\n node.collapsedChildren.forEach((childNode) => {\n const childNodeTransformData =\n childNode.getData<FlowNodeTransformData>(FlowNodeTransformData);\n childNodeTransformData.fireChange();\n });\n }\n transform.update({\n position: positionWithOffset,\n });\n }\n\n private calcAlignOffset(params: {\n snapNodeRects: SnapNodeRect[];\n targetRect: Rectangle;\n alignThreshold: number;\n }): {\n alignOffset: IPoint;\n alignRects: AlignRects;\n alignSpacing: AlignSpacing;\n } {\n const { snapNodeRects, targetRect, alignThreshold } = params;\n\n const alignRects = this.getAlignRects({\n targetRect,\n snapNodeRects,\n });\n\n const alignSpacing = this.calcAlignSpacing({\n targetRect,\n alignRects,\n });\n\n let topY: number | undefined;\n let bottomY: number | undefined;\n let leftX: number | undefined;\n let rightX: number | undefined;\n let midY: number | undefined;\n let midX: number | undefined;\n\n if (alignSpacing.top) {\n const topAlignY = alignRects.top[0].rect.bottom + alignSpacing.top;\n const isAlignTop = isLessThanOrEqual(Math.abs(targetRect.top - topAlignY), alignThreshold);\n if (isAlignTop) {\n // 生效\n topY = topAlignY;\n } else {\n // 失效\n alignSpacing.top = undefined;\n }\n }\n if (alignSpacing.bottom) {\n const bottomAlignY = alignRects.bottom[0].rect.top - alignSpacing.bottom;\n const isAlignBottom = isLessThan(Math.abs(targetRect.bottom - bottomAlignY), alignThreshold);\n if (isAlignBottom) {\n bottomY = bottomAlignY - targetRect.height;\n } else {\n alignSpacing.bottom = undefined;\n }\n }\n if (alignSpacing.left) {\n const leftAlignX = alignRects.left[0].rect.right + alignSpacing.left;\n const isAlignLeft = isLessThanOrEqual(Math.abs(targetRect.left - leftAlignX), alignThreshold);\n if (isAlignLeft) {\n leftX = leftAlignX;\n } else {\n alignSpacing.left = undefined;\n }\n }\n if (alignSpacing.right) {\n const rightAlignX = alignRects.right[0].rect.left - alignSpacing.right;\n const isAlignRight = isLessThanOrEqual(\n Math.abs(targetRect.right - rightAlignX),\n alignThreshold\n );\n if (isAlignRight) {\n rightX = rightAlignX - targetRect.width;\n } else {\n alignSpacing.right = undefined;\n }\n }\n if (alignSpacing.midHorizontal) {\n const leftAlignX = alignRects.left[0].rect.right + alignSpacing.midHorizontal;\n const isAlignMidHorizontal = isLessThanOrEqual(\n Math.abs(targetRect.left - leftAlignX),\n alignThreshold\n );\n if (isAlignMidHorizontal) {\n midX = leftAlignX;\n } else {\n alignSpacing.midHorizontal = undefined;\n }\n }\n if (alignSpacing.midVertical) {\n const topAlignY = alignRects.top[0].rect.bottom + alignSpacing.midVertical;\n const isAlignMidVertical = isLessThanOrEqual(\n Math.abs(targetRect.top - topAlignY),\n alignThreshold\n );\n if (isAlignMidVertical) {\n midY = topAlignY;\n } else {\n alignSpacing.midVertical = undefined;\n }\n }\n\n const alignPosition: IPoint = {\n x: midX ?? leftX ?? rightX ?? targetRect.x,\n y: midY ?? topY ?? bottomY ?? targetRect.y,\n };\n\n const alignOffset: IPoint = {\n x: alignPosition.x - targetRect.x,\n y: alignPosition.y - targetRect.y,\n };\n\n return { alignOffset, alignRects, alignSpacing };\n }\n\n private calcAlignSpacing(params: {\n targetRect: Rectangle;\n alignRects: AlignRects;\n }): AlignSpacing {\n const { targetRect, alignRects } = params;\n\n const topSpacing = this.getDirectionAlignSpacing({\n rects: alignRects.top,\n isHorizontal: false,\n });\n const bottomSpacing = this.getDirectionAlignSpacing({\n rects: alignRects.bottom,\n isHorizontal: false,\n });\n const leftSpacing = this.getDirectionAlignSpacing({\n rects: alignRects.left,\n isHorizontal: true,\n });\n const rightSpacing = this.getDirectionAlignSpacing({\n rects: alignRects.right,\n isHorizontal: true,\n });\n const midHorizontalSpacing = this.getMidAlignSpacing({\n rectA: alignRects.left[0]?.rect,\n rectB: alignRects.right[0]?.rect,\n targetRect,\n isHorizontal: true,\n });\n const midVerticalSpacing = this.getMidAlignSpacing({\n rectA: alignRects.top[0]?.rect,\n rectB: alignRects.bottom[0]?.rect,\n targetRect,\n isHorizontal: false,\n });\n return {\n top: topSpacing,\n bottom: bottomSpacing,\n left: leftSpacing,\n right: rightSpacing,\n midHorizontal: midHorizontalSpacing,\n midVertical: midVerticalSpacing,\n };\n }\n\n private getAlignRects(params: {\n targetRect: Rectangle;\n snapNodeRects: SnapNodeRect[];\n }): AlignRects {\n const { targetRect, snapNodeRects } = params;\n\n const topVerticalRects: AlignRect[] = [];\n const bottomVerticalRects: AlignRect[] = [];\n const leftHorizontalRects: AlignRect[] = [];\n const rightHorizontalRects: AlignRect[] = [];\n\n snapNodeRects.forEach((snapNodeRect) => {\n const nodeRect = snapNodeRect.rect;\n const { isVerticalIntersection, isHorizontalIntersection, isIntersection } =\n this.intersection(nodeRect, targetRect);\n if (isIntersection) {\n // 忽略重叠的节点\n return;\n } else if (isVerticalIntersection) {\n // 垂直重合\n if (isGreaterThan(nodeRect.center.y, targetRect.center.y)) {\n // 下方\n bottomVerticalRects.push({\n rect: nodeRect,\n sourceNodeId: snapNodeRect.id,\n });\n } else {\n // 上方\n topVerticalRects.push({\n rect: nodeRect,\n sourceNodeId: snapNodeRect.id,\n });\n }\n } else if (isHorizontalIntersection) {\n // 水平重合\n if (isGreaterThan(nodeRect.center.x, targetRect.center.x)) {\n // 右方\n rightHorizontalRects.push({\n rect: nodeRect,\n sourceNodeId: snapNodeRect.id,\n });\n } else {\n // 左方\n leftHorizontalRects.push({\n rect: nodeRect,\n sourceNodeId: snapNodeRect.id,\n });\n }\n }\n });\n\n return {\n top: topVerticalRects,\n bottom: bottomVerticalRects,\n left: leftHorizontalRects,\n right: rightHorizontalRects,\n };\n }\n\n private getMidAlignSpacing(params: {\n rectA?: Rectangle;\n rectB?: Rectangle;\n targetRect: Rectangle;\n isHorizontal: boolean;\n }): number | undefined {\n const { rectA, rectB, targetRect, isHorizontal } = params;\n if (!rectA || !rectB) {\n return;\n }\n const { isVerticalIntersection, isHorizontalIntersection, isIntersection } = this.intersection(\n rectA,\n rectB\n );\n if (isIntersection) {\n return;\n }\n if (isHorizontal && isHorizontalIntersection && !isVerticalIntersection) {\n const betweenSpacing = Math.min(\n Math.abs(rectA.left - rectB.right),\n Math.abs(rectA.right - rectB.left)\n );\n return (betweenSpacing - targetRect.width) / 2;\n } else if (!isHorizontal && isVerticalIntersection && !isHorizontalIntersection) {\n const betweenSpacing = Math.min(\n Math.abs(rectA.top - rectB.bottom),\n Math.abs(rectA.bottom - rectB.top)\n );\n return (betweenSpacing - targetRect.height) / 2;\n }\n }\n\n private getDirectionAlignSpacing(params: {\n rects: AlignRect[];\n isHorizontal: boolean;\n }): number | undefined {\n const { rects, isHorizontal } = params;\n if (rects.length < 2) {\n // 非法情况\n return;\n }\n const rectA = rects[0].rect;\n const rectB = rects[1].rect;\n\n const { isVerticalIntersection, isHorizontalIntersection, isIntersection } = this.intersection(\n rectA,\n rectB\n );\n\n if (isIntersection) {\n // 非法情况:重叠\n return;\n }\n if (isHorizontal && isHorizontalIntersection && !isVerticalIntersection) {\n return Math.min(Math.abs(rectA.left - rectB.right), Math.abs(rectA.right - rectB.left));\n } else if (!isHorizontal && isVerticalIntersection && !isHorizontalIntersection) {\n return Math.min(Math.abs(rectA.top - rectB.bottom), Math.abs(rectA.bottom - rectB.top));\n }\n return;\n }\n\n private intersection(\n rectA: Rectangle,\n rectB: Rectangle\n ): {\n isHorizontalIntersection: boolean;\n isVerticalIntersection: boolean;\n isIntersection: boolean;\n } {\n const isVerticalIntersection =\n isLessThan(rectA.left, rectB.right) && isGreaterThan(rectA.right, rectB.left);\n const isHorizontalIntersection =\n isLessThan(rectA.top, rectB.bottom) && isGreaterThan(rectA.bottom, rectB.top);\n const isIntersection = isHorizontalIntersection && isVerticalIntersection;\n\n return {\n isHorizontalIntersection,\n isVerticalIntersection,\n isIntersection,\n };\n }\n}\n","import type { WorkflowSnapLayerOptions, WorkflowSnapServiceOptions } from './type';\n\nexport const SnapDefaultOptions: WorkflowSnapServiceOptions & WorkflowSnapLayerOptions = {\n enableEdgeSnapping: true,\n edgeThreshold: 7,\n enableGridSnapping: false,\n gridSize: 20,\n enableMultiSnapping: false,\n enableOnlyViewportSnapping: true,\n edgeColor: '#4E40E5',\n alignColor: '#4E40E5',\n edgeLineWidth: 2,\n alignLineWidth: 2,\n alignCrossWidth: 16,\n};\n\nexport const Epsilon = 0.00001;\n","import { Epsilon } from './constant';\n\n/** 检查浮点数 a 是否等于 b */\nexport const isEqual = (a: number | undefined, b: number | undefined): boolean => {\n if (a === undefined || b === undefined) {\n return false;\n }\n // 检查 a 和 b 的差的绝对值是否小于 Epsilon\n return Math.abs(a - b) < Epsilon;\n};\n\n/** 检查浮点数 a 是否小于 b */\nexport const isLessThan = (a: number | undefined, b: number | undefined): boolean => {\n if (a === undefined || b === undefined) {\n return false;\n }\n // 检查 a 是否显著小于 b\n return b - a > Epsilon;\n};\n\n/** 检查浮点数 a 是否大于 b */\nexport const isGreaterThan = (a: number | undefined, b: number | undefined): boolean => {\n if (a === undefined || b === undefined) {\n return false;\n }\n return a - b > Epsilon;\n};\n\n/** 检查浮点数 a 是否小于等于 b */\nexport const isLessThanOrEqual = (a: number | undefined, b: number | undefined): boolean =>\n isEqual(a, b) || isLessThan(a, b);\n\n/** 检查浮点数 a 是否大于等于 b */\nexport const isGreaterThanOrEqual = (a: number | undefined, b: number | undefined): boolean =>\n isEqual(a, b) || isGreaterThan(a, b);\n\n/** 检查值是否是数字类型 */\nexport const isNumber = (value: unknown): value is number =>\n typeof value === 'number' && !isNaN(value);\n","import React from 'react';\n\nimport { inject, injectable } from 'inversify';\nimport { domUtils } from '@flowgram.ai/utils';\nimport { Rectangle } from '@flowgram.ai/utils';\nimport { WorkflowDocument } from '@flowgram.ai/free-layout-core';\nimport { FlowNodeTransformData } from '@flowgram.ai/document';\nimport { Layer } from '@flowgram.ai/core';\n\nimport { isEqual, isGreaterThan, isNumber } from './utils';\nimport { AlignRect, SnapEvent, WorkflowSnapLayerOptions } from './type';\nimport { WorkflowSnapService } from './service';\n\ninterface SnapRenderLine {\n className: string;\n sourceNode: string;\n top: number;\n left: number;\n width: number;\n height: number;\n dashed?: boolean;\n}\n\n@injectable()\nexport class WorkflowSnapLayer extends Layer<WorkflowSnapLayerOptions> {\n public static type = 'WorkflowSnapLayer';\n\n @inject(WorkflowDocument) private readonly document: WorkflowDocument;\n\n @inject(WorkflowSnapService) private readonly service: WorkflowSnapService;\n\n public readonly node = domUtils.createDivWithClass(\n 'gedit-playground-layer gedit-flow-snap-layer'\n );\n\n private edgeLines: SnapRenderLine[] = [];\n\n private alignLines: SnapRenderLine[] = [];\n\n public onReady(): void {\n this.node.style.zIndex = '9999';\n this.toDispose.pushAll([\n this.service.onSnap((event: SnapEvent) => {\n this.edgeLines = this.calcEdgeLines(event);\n this.alignLines = this.calcAlignLines(event);\n this.render();\n }),\n ]);\n }\n\n public render(): JSX.Element {\n return (\n <>\n {this.alignLines.length > 0 && (\n <div className=\"workflow-snap-align-lines\">{this.renderAlignLines()}</div>\n )}\n {this.edgeLines.length > 0 && (\n <div className=\"workflow-snap-edge-lines\">{this.renderEdgeLines()}</div>\n )}\n </>\n );\n }\n\n public onZoom(scale: number): void {\n this.node.style.transform = `scale(${scale})`;\n }\n\n private renderEdgeLines(): JSX.Element[] {\n return this.edgeLines.map((renderLine: SnapRenderLine) => {\n const { className, sourceNode, top, left, width, height, dashed } = renderLine;\n const id = `${className}-${sourceNode}-${top}-${left}-${width}-${height}`;\n const isHorizontal = width < height;\n const border = `${this.options.edgeLineWidth}px ${dashed ? 'dashed' : 'solid'} ${\n this.options.edgeColor\n }`;\n return (\n <div\n className={`workflow-snap-edge-line ${className}`}\n data-testid=\"sdk.workflow.canvas.snap.edgeLine\"\n data-snap-line-id={id}\n data-snap-line-source-node={sourceNode}\n key={id}\n style={{\n top,\n left,\n width,\n height,\n position: 'absolute',\n borderLeft: isHorizontal ? border : 'none',\n borderTop: !isHorizontal ? border : 'none',\n }}\n />\n );\n });\n }\n\n private renderAlignLines(): JSX.Element[] {\n return this.alignLines.map((renderLine: SnapRenderLine) => {\n const id = `${renderLine.className}-${renderLine.sourceNode}-${renderLine.top}-${renderLine.left}-${renderLine.width}-${renderLine.height}`;\n const isHorizontal = isGreaterThan(renderLine.width, renderLine.height);\n const alignLineWidth = this.options.alignLineWidth; // 整体线条粗细\n const alignCrossWidth = this.options.alignCrossWidth; // 工字形横线的长度\n\n // 调整渲染位置以保持居中\n const adjustedTop = isHorizontal ? renderLine.top - alignLineWidth / 2 : renderLine.top;\n const adjustedLeft = isHorizontal ? renderLine.left : renderLine.left - alignLineWidth / 2;\n\n return (\n <div\n className={`workflow-snap-align-line ${renderLine.className}`}\n data-testid=\"sdk.workflow.canvas.snap.alignLine\"\n data-snap-line-id={id}\n data-snap-line-source-node={renderLine.sourceNode}\n key={id}\n style={{\n position: 'absolute',\n }}\n >\n {/* 主线 */}\n <div\n style={{\n position: 'absolute',\n top: adjustedTop,\n left: adjustedLeft,\n width: isHorizontal ? renderLine.width : alignLineWidth,\n height: isHorizontal ? alignLineWidth : renderLine.height,\n backgroundColor: this.options.alignColor,\n }}\n />\n {/* 左端或上端横线 */}\n <div\n style={{\n position: 'absolute',\n top: isHorizontal\n ? adjustedTop - (alignCrossWidth - alignLineWidth) / 2\n : adjustedTop,\n left: isHorizontal\n ? adjustedLeft\n : adjustedLeft - (alignCrossWidth - alignLineWidth) / 2,\n width: isHorizontal ? alignLineWidth : alignCrossWidth,\n height: isHorizontal ? alignCrossWidth : alignLineWidth,\n backgroundColor: this.options.alignColor,\n }}\n />\n {/* 右端或下端横线 */}\n <div\n style={{\n position: 'absolute',\n top: isHorizontal\n ? adjustedTop - (alignCrossWidth - alignLineWidth) / 2\n : adjustedTop + renderLine.height - alignLineWidth,\n left: isHorizontal\n ? adjustedLeft + renderLine.width - alignLineWidth\n : adjustedLeft - (alignCrossWidth - alignLineWidth) / 2,\n width: isHorizontal ? alignLineWidth : alignCrossWidth,\n height: isHorizontal ? alignCrossWidth : alignLineWidth,\n backgroundColor: this.options.alignColor,\n }}\n />\n </div>\n );\n });\n }\n\n private calcEdgeLines(event: SnapEvent): SnapRenderLine[] {\n const { alignRects, snapRect, snapEdgeLines } = event;\n const edgeLines: SnapRenderLine[] = [];\n\n const topFullAlign = this.directionFullAlign({\n alignRects: alignRects.top,\n targetRect: snapRect,\n isVertical: true,\n });\n const bottomFullAlign = this.directionFullAlign({\n alignRects: alignRects.bottom,\n targetRect: snapRect,\n isVertical: true,\n });\n const leftFullAlign = this.directionFullAlign({\n alignRects: alignRects.left,\n targetRect: snapRect,\n isVertical: false,\n });\n const rightFullAlign = this.directionFullAlign({\n alignRects: alignRects.right,\n targetRect: snapRect,\n isVertical: false,\n });\n\n // 处理顶部对齐\n if (topFullAlign) {\n const top = topFullAlign.rect.top;\n const height = bottomFullAlign\n ? snapRect.bottom - snapRect.height / 2 - top\n : snapRect.bottom - top;\n const width = this.options.edgeLineWidth;\n const lineData = {\n top,\n width,\n height,\n };\n edgeLines.push({\n className: 'edge-full-top-left',\n sourceNode: topFullAlign.sourceNodeId,\n left: snapRect.left,\n ...lineData,\n });\n edgeLines.push({\n className: 'edge-full-top-right',\n sourceNode: topFullAlign.sourceNodeId,\n left: snapRect.right,\n ...lineData,\n });\n edgeLines.push({\n className: 'edge-full-top-mid',\n sourceNode: topFullAlign.sourceNodeId,\n left: snapRect.left + snapRect.width / 2,\n dashed: true,\n ...lineData,\n });\n }\n\n // 处理底部对齐\n if (bottomFullAlign) {\n const top = topFullAlign ? snapRect.top + snapRect.height / 2 : snapRect.top;\n const height = bottomFullAlign.rect.bottom - top;\n const width = this.options.edgeLineWidth;\n const lineData = {\n top,\n width,\n height,\n };\n edgeLines.push({\n className: 'edge-full-bottom-left',\n sourceNode: bottomFullAlign.sourceNodeId,\n left: snapRect.left,\n ...lineData,\n });\n edgeLines.push({\n className: 'edge-full-bottom-right',\n sourceNode: bottomFullAlign.sourceNodeId,\n left: snapRect.right,\n ...lineData,\n });\n edgeLines.push({\n className: 'edge-full-bottom-mid',\n sourceNode: bottomFullAlign.sourceNodeId,\n left: snapRect.left + snapRect.width / 2,\n dashed: true,\n ...lineData,\n });\n }\n\n // 处理左侧对齐\n if (leftFullAlign) {\n const left = leftFullAlign.rect.left;\n const width = rightFullAlign\n ? snapRect.right - snapRect.width / 2 - left\n : snapRect.right - left;\n const height = this.options.edgeLineWidth;\n const lineData = {\n left,\n width,\n height,\n };\n edgeLines.push({\n className: 'edge-full-left-top',\n sourceNode: leftFullAlign.sourceNodeId,\n top: snapRect.top,\n ...lineData,\n });\n edgeLines.push({\n className: 'edge-full-left-bottom',\n sourceNode: leftFullAlign.sourceNodeId,\n top: snapRect.bottom,\n ...lineData,\n });\n edgeLines.push({\n className: 'edge-full-left-mid',\n sourceNode: leftFullAlign.sourceNodeId,\n top: snapRect.top + snapRect.height / 2,\n dashed: true,\n ...lineData,\n });\n }\n\n // 处理右侧对齐\n if (rightFullAlign) {\n const left = leftFullAlign ? snapRect.left + snapRect.width / 2 : snapRect.left;\n const width = rightFullAlign.rect.right - left;\n const height = this.options.edgeLineWidth;\n const lineData = {\n left,\n width,\n height,\n };\n edgeLines.push({\n className: 'edge-full-right-top',\n sourceNode: rightFullAlign.sourceNodeId,\n top: snapRect.top,\n ...lineData,\n });\n edgeLines.push({\n className: 'edge-full-right-bottom',\n sourceNode: rightFullAlign.sourceNodeId,\n top: snapRect.bottom,\n ...lineData,\n });\n edgeLines.push({\n className: 'edge-full-right-mid',\n sourceNode: rightFullAlign.sourceNodeId,\n top: snapRect.top + snapRect.height / 2,\n dashed: true,\n ...lineData,\n });\n }\n\n const snappedEdgeLines = Object.entries(snapEdgeLines)\n .map(([direction, snapLine]) => {\n if (!snapLine) {\n return;\n }\n const sourceNode = this.document.getNode(snapLine.sourceNodeId);\n if (!sourceNode) {\n return;\n }\n const nodeRect = sourceNode.getData(FlowNodeTransformData).bounds;\n if (isNumber(snapLine.x)) {\n // 垂直\n const top = Math.min(nodeRect.top, snapRect.top);\n const bottom = Math.max(nodeRect.bottom, snapRect.bottom);\n const height = bottom - top;\n const left = snapLine.x;\n const width = this.options.edgeLineWidth;\n const isMidX = direction === 'midVertical';\n const lineData: SnapRenderLine = {\n className: `edge-snapped-${direction}`,\n sourceNode: snapLine.sourceNodeId,\n top,\n left,\n width,\n height,\n dashed: isMidX,\n };\n const onTop = top === nodeRect.top;\n if (onTop && topFullAlign) {\n return;\n }\n if (!onTop && bottomFullAlign) {\n return;\n }\n return lineData;\n } else if (isNumber(snapLine.y)) {\n // 水平\n const left = Math.min(nodeRect.left, snapRect.left);\n const right = Math.max(nodeRect.right, snapRect.right);\n const width = right - left;\n const top = snapLine.y;\n const height = this.options.edgeLineWidth;\n const isMidY = direction === 'midHorizontal';\n const lineData: SnapRenderLine = {\n className: `edge-snapped-${direction}`,\n sourceNode: snapLine.sourceNodeId,\n top,\n left,\n width,\n height,\n dashed: isMidY,\n };\n const onLeft = left === nodeRect.left;\n if (onLeft && leftFullAlign) {\n return;\n }\n if (!onLeft && rightFullAlign) {\n return;\n }\n return lineData;\n }\n })\n .filter(Boolean) as SnapRenderLine[];\n\n edgeLines.push(...snappedEdgeLines);\n\n return edgeLines;\n }\n\n private directionFullAlign(params: {\n alignRects: AlignRect[];\n targetRect: Rectangle;\n isVertical: boolean;\n }): AlignRect | undefined {\n const { alignRects, targetRect, isVertical } = params;\n let fullAlignIndex = -1;\n for (let i = 0; i < alignRects.length; i++) {\n const alignRect = alignRects[i];\n const prevRect = alignRects[i - 1]?.rect ?? targetRect;\n const isFullAlign = this.rectFullAlign(alignRect.rect, prevRect, isVertical);\n if (!isFullAlign) {\n // 未对齐则中断\n break; // 用 for 循环 + break 反而比 Array.findIndex 实现可读性更好\n }\n fullAlignIndex = i;\n }\n const fullAlignRect = alignRects[fullAlignIndex];\n return fullAlignRect;\n }\n\n private rectFullAlign(rectA: Rectangle, rectB: Rectangle, isVertical: boolean): boolean {\n if (isVertical) {\n return isEqual(rectA.left, rectB.left) && isEqual(rectA.right, rectB.right);\n } else {\n return isEqual(rectA.top, rectB.top) && isEqual(rectA.bottom, rectB.bottom);\n }\n }\n\n private calcAlignLines(event: SnapEvent): SnapRenderLine[] {\n const { alignRects, alignSpacing, snapRect } = event;\n\n const topAlignLines = this.calcDirectionAlignLines({\n alignRects: alignRects.top,\n targetRect: snapRect,\n isVertical: true,\n spacing: alignSpacing.midVertical ?? alignSpacing.top,\n });\n\n const bottomAlignLines = this.calcDirectionAlignLines({\n alignRects: alignRects.bottom,\n targetRect: snapRect,\n isVertical: true,\n spacing: alignSpacing.midVertical ?? alignSpacing.bottom,\n });\n\n const leftAlignLines = this.calcDirectionAlignLines({\n alignRects: alignRects.left,\n targetRect: snapRect,\n isVertical: false,\n spacing: alignSpacing.midHorizontal ?? alignSpacing.left,\n });\n\n const rightAlignLines = this.calcDirectionAlignLines({\n alignRects: alignRects.right,\n targetRect: snapRect,\n isVertical: false,\n spacing: alignSpacing.midHorizontal ?? alignSpacing.right,\n });\n\n return [...topAlignLines, ...bottomAlignLines, ...leftAlignLines, ...rightAlignLines];\n }\n\n private calcDirectionAlignLines(params: {\n alignRects: AlignRect[];\n targetRect: Rectangle;\n isVertical: boolean;\n spacing?: number;\n }) {\n const { alignRects, targetRect, isVertical, spacing } = params;\n const alignLines: SnapRenderLine[] = [];\n if (!spacing) {\n return alignLines;\n }\n for (let i = 0; i < alignRects.length; i++) {\n const alignRect = alignRects[i];\n const rect = alignRect.rect;\n const prevRect = alignRects[i - 1]?.rect ?? targetRect;\n\n const betweenSpacing = isVertical\n ? Math.min(Math.abs(prevRect.top - rect.bottom), Math.abs(prevRect.bottom - rect.top))\n : Math.min(Math.abs(prevRect.left - rect.right), Math.abs(prevRect.right - rect.left));\n if (!isEqual(betweenSpacing, spacing)) {\n // 不连续,需要中断\n break; // 因为要用到 break,所以不能用 Array.map()\n }\n if (isVertical) {\n const centerX = this.calcHorizontalIntersectionCenter(rect, targetRect);\n alignLines.push({\n className: 'align-vertical',\n sourceNode: alignRect.sourceNodeId,\n top: Math.min(rect.bottom, prevRect.bottom),\n left: centerX,\n width: 1,\n height: spacing,\n });\n } else {\n const centerY = this.calcVerticalIntersectionCenter(rect, targetRect);\n alignLines.push({\n className: 'align-horizontal',\n sourceNode: alignRect.sourceNodeId,\n top: centerY,\n left: Math.min(rect.right, prevRect.right),\n width: spacing,\n height: 1,\n });\n }\n }\n return alignLines;\n }\n\n private calcVerticalIntersectionCenter(rectA: Rectangle, rectB: Rectangle): number {\n const top = Math.max(rectA.top, rectB.top);\n const bottom = Math.min(rectA.bottom, rectB.bottom);\n return (top + bottom) / 2;\n }\n\n private calcHorizontalIntersectionCenter(rectA: Rectangle, rectB: Rectangle): number {\n const left = Math.max(rectA.left, rectB.left);\n const right = Math.min(rectA.right, rectB.right);\n return (left + right) / 2;\n }\n}\n"],"mappings":"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","names":["import_core","import_free_layout_core","import_document","import_inversify","import_utils","import_free_layout_core","import_document","import_core","React"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flowgram.ai/free-snap-plugin",
3
- "version": "0.1.13",
3
+ "version": "0.1.15",
4
4
  "homepage": "https://flowgram.ai/",
5
5
  "repository": "https://github.com/bytedance/flowgram.ai",
6
6
  "license": "MIT",
@@ -18,11 +18,11 @@
18
18
  "inversify": "^6.0.1",
19
19
  "reflect-metadata": "~0.2.2",
20
20
  "lodash": "^4.17.21",
21
- "@flowgram.ai/document": "0.1.13",
22
- "@flowgram.ai/free-layout-core": "0.1.13",
23
- "@flowgram.ai/core": "0.1.13",
24
- "@flowgram.ai/utils": "0.1.13",
25
- "@flowgram.ai/renderer": "0.1.13"
21
+ "@flowgram.ai/core": "0.1.15",
22
+ "@flowgram.ai/free-layout-core": "0.1.15",
23
+ "@flowgram.ai/document": "0.1.15",
24
+ "@flowgram.ai/utils": "0.1.15",
25
+ "@flowgram.ai/renderer": "0.1.15"
26
26
  },
27
27
  "devDependencies": {
28
28
  "@types/bezier-js": "4.1.3",
@@ -38,8 +38,8 @@
38
38
  "tsup": "^8.0.1",
39
39
  "typescript": "^5.0.4",
40
40
  "vitest": "^0.34.6",
41
- "@flowgram.ai/eslint-config": "0.1.13",
42
- "@flowgram.ai/ts-config": "0.1.13"
41
+ "@flowgram.ai/ts-config": "0.1.15",
42
+ "@flowgram.ai/eslint-config": "0.1.15"
43
43
  },
44
44
  "peerDependencies": {
45
45
  "react": ">=17",