@flowgram.ai/free-hover-plugin 0.1.0-alpha.2 → 0.1.0-alpha.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/index.js +75 -55
- package/dist/esm/index.js.map +1 -1
- package/dist/index.d.mts +4 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +75 -55
- package/dist/index.js.map +1 -1
- package/package.json +14 -15
package/dist/esm/index.js
CHANGED
|
@@ -15,43 +15,37 @@ import { definePluginCreator } from "@flowgram.ai/core";
|
|
|
15
15
|
// src/hover-layer.tsx
|
|
16
16
|
import { inject, injectable } from "inversify";
|
|
17
17
|
import { SelectorBoxConfigEntity } from "@flowgram.ai/renderer";
|
|
18
|
-
import { FlowNodeTransformData as FlowNodeTransformData2 } from "@flowgram.ai/document";
|
|
19
|
-
import {
|
|
20
|
-
EditorState,
|
|
21
|
-
EditorStateConfigEntity,
|
|
22
|
-
Layer,
|
|
23
|
-
PlaygroundConfigEntity,
|
|
24
|
-
observeEntities,
|
|
25
|
-
observeEntity,
|
|
26
|
-
observeEntityDatas
|
|
27
|
-
} from "@flowgram.ai/core";
|
|
28
18
|
import {
|
|
29
19
|
WorkflowDocument,
|
|
30
20
|
WorkflowDragService,
|
|
31
21
|
WorkflowHoverService,
|
|
32
22
|
WorkflowLineEntity,
|
|
33
23
|
WorkflowLinesManager,
|
|
34
|
-
WorkflowNodeEntity,
|
|
24
|
+
WorkflowNodeEntity as WorkflowNodeEntity2,
|
|
35
25
|
WorkflowSelectService
|
|
36
26
|
} from "@flowgram.ai/free-layout-core";
|
|
37
27
|
import { WorkflowPortEntity } from "@flowgram.ai/free-layout-core";
|
|
28
|
+
import { FlowNodeBaseType, FlowNodeTransformData as FlowNodeTransformData2 } from "@flowgram.ai/document";
|
|
29
|
+
import {
|
|
30
|
+
EditorState,
|
|
31
|
+
EditorStateConfigEntity,
|
|
32
|
+
Layer,
|
|
33
|
+
PlaygroundConfigEntity,
|
|
34
|
+
observeEntities,
|
|
35
|
+
observeEntity,
|
|
36
|
+
observeEntityDatas
|
|
37
|
+
} from "@flowgram.ai/core";
|
|
38
38
|
|
|
39
39
|
// src/selection-utils.ts
|
|
40
|
-
import { FlowNodeTransformData, FlowNodeEntity } from "@flowgram.ai/document";
|
|
41
40
|
import { Rectangle } from "@flowgram.ai/utils";
|
|
41
|
+
import { WorkflowNodeEntity } from "@flowgram.ai/free-layout-core";
|
|
42
|
+
import { FlowNodeTransformData } from "@flowgram.ai/document";
|
|
42
43
|
var BOUNDS_PADDING = 2;
|
|
43
|
-
function getSelectionBounds(selection, ignoreOneSelect) {
|
|
44
|
-
const selectedNodes = selection.filter((node) => node instanceof
|
|
45
|
-
|
|
46
|
-
return Rectangle.EMPTY;
|
|
47
|
-
}
|
|
48
|
-
if (ignoreOneSelect && selectedNodes.length === 1 && // 选中的节点不包含多个子节点
|
|
49
|
-
selectedNodes[0].childrenLength <= 1) {
|
|
50
|
-
return Rectangle.EMPTY;
|
|
51
|
-
}
|
|
52
|
-
return Rectangle.enlarge(selectedNodes.map((n) => n.getData(FlowNodeTransformData).bounds)).pad(
|
|
44
|
+
function getSelectionBounds(selection, ignoreOneSelect = true) {
|
|
45
|
+
const selectedNodes = selection.filter((node) => node instanceof WorkflowNodeEntity);
|
|
46
|
+
return selectedNodes.length > (ignoreOneSelect ? 1 : 0) ? Rectangle.enlarge(selectedNodes.map((n) => n.getData(FlowNodeTransformData).bounds)).pad(
|
|
53
47
|
BOUNDS_PADDING
|
|
54
|
-
);
|
|
48
|
+
) : Rectangle.EMPTY;
|
|
55
49
|
}
|
|
56
50
|
|
|
57
51
|
// src/hover-layer.tsx
|
|
@@ -75,7 +69,7 @@ var HoverLayer = class extends Layer {
|
|
|
75
69
|
}
|
|
76
70
|
autorun() {
|
|
77
71
|
const { activatedNode } = this.selectionService;
|
|
78
|
-
this.nodeTransformsWithSort = this.nodeTransforms.filter((n) => n.entity.id !== "root").reverse().sort((n1) => n1.entity === activatedNode ? -1 : 0);
|
|
72
|
+
this.nodeTransformsWithSort = this.nodeTransforms.filter((n) => n.entity.id !== "root" && n.entity.flowNodeType !== FlowNodeBaseType.GROUP).reverse().sort((n1) => n1.entity === activatedNode ? -1 : 0);
|
|
79
73
|
}
|
|
80
74
|
/**
|
|
81
75
|
* 是否正在调整线条
|
|
@@ -90,6 +84,15 @@ var HoverLayer = class extends Layer {
|
|
|
90
84
|
...this.options
|
|
91
85
|
};
|
|
92
86
|
this.toDispose.pushAll([
|
|
87
|
+
// 监听主动触发的 hover 事件
|
|
88
|
+
this.hoverService.onUpdateHoverPosition((hoverPosition) => {
|
|
89
|
+
const { position, target } = hoverPosition;
|
|
90
|
+
const canvasPosition = this.config.getPosFromMouseEvent({
|
|
91
|
+
clientX: position.x,
|
|
92
|
+
clientY: position.y
|
|
93
|
+
});
|
|
94
|
+
this.updateHoveredState(canvasPosition, target);
|
|
95
|
+
}),
|
|
93
96
|
// 监听画布鼠标移动事件
|
|
94
97
|
this.listenPlaygroundEvent("mousemove", (e) => {
|
|
95
98
|
this.hoverService.hoveredPos = this.config.getPosFromMouseEvent(e);
|
|
@@ -103,20 +106,21 @@ var HoverLayer = class extends Layer {
|
|
|
103
106
|
this.updateHoveredState(mousePos, e?.target);
|
|
104
107
|
}),
|
|
105
108
|
this.selectionService.onSelectionChanged(() => this.autorun()),
|
|
109
|
+
// 控制触控
|
|
110
|
+
this.listenPlaygroundEvent("touchstart", (e) => {
|
|
111
|
+
if (!this.isEnabled() || this.isDrawing) {
|
|
112
|
+
return void 0;
|
|
113
|
+
}
|
|
114
|
+
return this.handleDragLine(e);
|
|
115
|
+
}),
|
|
106
116
|
// 控制选中逻辑
|
|
107
117
|
this.listenPlaygroundEvent("mousedown", (e) => {
|
|
108
118
|
if (!this.isEnabled() || this.isDrawing) {
|
|
109
119
|
return void 0;
|
|
110
120
|
}
|
|
111
121
|
const { hoveredNode } = this.hoverService;
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
return true;
|
|
115
|
-
}
|
|
116
|
-
if (hoveredNode && hoveredNode instanceof WorkflowPortEntity && hoveredNode.portType !== "input" && !hoveredNode.disabled && e.button !== 1) {
|
|
117
|
-
e.stopPropagation();
|
|
118
|
-
e.preventDefault();
|
|
119
|
-
this.dragService.startDrawingLine(hoveredNode, e);
|
|
122
|
+
const lineDrag = this.handleDragLine(e);
|
|
123
|
+
if (lineDrag) {
|
|
120
124
|
return true;
|
|
121
125
|
}
|
|
122
126
|
const mousePos = this.config.getPosFromMouseEvent(e);
|
|
@@ -126,10 +130,10 @@ var HoverLayer = class extends Layer {
|
|
|
126
130
|
true
|
|
127
131
|
);
|
|
128
132
|
if (selectionBounds.width > 0 && selectionBounds.contains(mousePos.x, mousePos.y)) {
|
|
129
|
-
this.dragService.startDragSelectedNodes(e)
|
|
133
|
+
this.dragService.startDragSelectedNodes(e)?.then((dragSuccess) => {
|
|
130
134
|
if (!dragSuccess) {
|
|
131
|
-
if (hoveredNode && hoveredNode instanceof
|
|
132
|
-
if (e.
|
|
135
|
+
if (hoveredNode && hoveredNode instanceof WorkflowNodeEntity2) {
|
|
136
|
+
if (e.shiftKey) {
|
|
133
137
|
this.selectionService.toggleSelect(hoveredNode);
|
|
134
138
|
} else {
|
|
135
139
|
this.selectionService.selectNode(hoveredNode);
|
|
@@ -156,18 +160,24 @@ var HoverLayer = class extends Layer {
|
|
|
156
160
|
updateHoveredState(mousePos, target) {
|
|
157
161
|
const { hoverService } = this;
|
|
158
162
|
const nodeTransforms = this.nodeTransformsWithSort;
|
|
159
|
-
const
|
|
163
|
+
const outputPortHovered = this.linesManager.getPortFromMousePos(mousePos, "output");
|
|
164
|
+
const inputPortHovered = this.linesManager.getPortFromMousePos(mousePos, "input");
|
|
165
|
+
const portHovered = outputPortHovered || inputPortHovered;
|
|
160
166
|
const lineDomNodes = this.playgroundNode.querySelectorAll(LINE_CLASS_NAME);
|
|
161
167
|
const checkTargetFromLine = [...lineDomNodes].some(
|
|
162
168
|
(lineDom) => lineDom.contains(target)
|
|
163
169
|
);
|
|
164
170
|
if (portHovered) {
|
|
165
|
-
if (
|
|
171
|
+
if (this.document.options.twoWayConnection) {
|
|
166
172
|
hoverService.updateHoveredKey(portHovered.id);
|
|
167
|
-
} else
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
173
|
+
} else {
|
|
174
|
+
if (portHovered.portType === "output") {
|
|
175
|
+
hoverService.updateHoveredKey(portHovered.id);
|
|
176
|
+
} else if (checkTargetFromLine || target?.className?.includes?.(PORT_BG_CLASS_NAME)) {
|
|
177
|
+
const lineHovered2 = this.linesManager.getCloseInLineFromMousePos(mousePos);
|
|
178
|
+
if (lineHovered2) {
|
|
179
|
+
this.updateHoveredKey(lineHovered2.id);
|
|
180
|
+
}
|
|
171
181
|
}
|
|
172
182
|
}
|
|
173
183
|
return;
|
|
@@ -187,24 +197,21 @@ var HoverLayer = class extends Layer {
|
|
|
187
197
|
this.updateHoveredKey(nodeHovered.id);
|
|
188
198
|
}
|
|
189
199
|
}
|
|
190
|
-
const nodeInContainer = !!(nodeHovered?.parent && nodeHovered.parent.flowNodeType !== "root");
|
|
191
200
|
const lineHovered = checkTargetFromLine ? this.linesManager.getCloseInLineFromMousePos(mousePos) : void 0;
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
201
|
+
if (nodeHovered && lineHovered) {
|
|
202
|
+
const nodeStackIndex = nodeHovered.renderData.stackIndex;
|
|
203
|
+
const lineStackIndex = lineHovered.stackIndex;
|
|
204
|
+
if (nodeStackIndex > lineStackIndex) {
|
|
205
|
+
return this.updateHoveredKey(nodeHovered.id);
|
|
206
|
+
} else {
|
|
207
|
+
return this.updateHoveredKey(lineHovered.id);
|
|
208
|
+
}
|
|
200
209
|
}
|
|
201
210
|
if (nodeHovered) {
|
|
202
|
-
this.updateHoveredKey(nodeHovered.id);
|
|
203
|
-
return;
|
|
211
|
+
return this.updateHoveredKey(nodeHovered.id);
|
|
204
212
|
}
|
|
205
213
|
if (lineHovered) {
|
|
206
|
-
this.
|
|
207
|
-
return;
|
|
214
|
+
return this.updateHoveredKey(lineHovered.id);
|
|
208
215
|
}
|
|
209
216
|
hoverService.clearHovered();
|
|
210
217
|
const currentState = this.editorStateConfig.getCurrentState();
|
|
@@ -229,6 +236,19 @@ var HoverLayer = class extends Layer {
|
|
|
229
236
|
(currentState === EditorState.STATE_SELECT || currentState === EditorState.STATE_MOUSE_FRIENDLY_SELECT) && !this.selectorBoxConfigEntity.isStart && !this.dragService.isDragging
|
|
230
237
|
);
|
|
231
238
|
}
|
|
239
|
+
handleDragLine(e) {
|
|
240
|
+
const { someHovered } = this.hoverService;
|
|
241
|
+
if (someHovered && someHovered instanceof WorkflowLineEntity) {
|
|
242
|
+
this.dragService.resetLine(someHovered, e);
|
|
243
|
+
return true;
|
|
244
|
+
}
|
|
245
|
+
if (someHovered && someHovered instanceof WorkflowPortEntity && !someHovered.disabled && e.button !== 1) {
|
|
246
|
+
e.stopPropagation();
|
|
247
|
+
e.preventDefault();
|
|
248
|
+
this.dragService.startDrawingLine(someHovered, e);
|
|
249
|
+
return true;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
232
252
|
};
|
|
233
253
|
HoverLayer.type = "HoverLayer";
|
|
234
254
|
__decorateClass([
|
|
@@ -256,7 +276,7 @@ __decorateClass([
|
|
|
256
276
|
inject(PlaygroundConfigEntity)
|
|
257
277
|
], HoverLayer.prototype, "configEntity", 2);
|
|
258
278
|
__decorateClass([
|
|
259
|
-
observeEntityDatas(
|
|
279
|
+
observeEntityDatas(WorkflowNodeEntity2, FlowNodeTransformData2)
|
|
260
280
|
], HoverLayer.prototype, "nodeTransforms", 2);
|
|
261
281
|
__decorateClass([
|
|
262
282
|
observeEntities(WorkflowLineEntity)
|
package/dist/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/create-free-hover-plugin.ts","../../src/hover-layer.tsx","../../src/selection-utils.ts"],"sourcesContent":["import { definePluginCreator } from '@flowgram.ai/core';\n\nimport { HoverLayer } from './hover-layer';\n\nexport const createFreeHoverPlugin = definePluginCreator({\n onInit(ctx): void {\n ctx.playground.registerLayer(HoverLayer);\n },\n});\n","/* eslint-disable complexity */\nimport { inject, injectable } from 'inversify';\nimport { SelectorBoxConfigEntity } from '@flowgram.ai/renderer';\nimport { FlowNodeTransformData } from '@flowgram.ai/document';\nimport {\n EditorState,\n EditorStateConfigEntity,\n Layer,\n PlaygroundConfigEntity,\n observeEntities,\n observeEntity,\n observeEntityDatas,\n type LayerOptions,\n} from '@flowgram.ai/core';\nimport {\n WorkflowDocument,\n WorkflowDragService,\n WorkflowHoverService,\n WorkflowLineEntity,\n WorkflowLinesManager,\n WorkflowNodeEntity,\n WorkflowSelectService,\n} from '@flowgram.ai/free-layout-core';\nimport { WorkflowPortEntity } from '@flowgram.ai/free-layout-core';\nimport { type IPoint } from '@flowgram.ai/utils';\n\nimport { getSelectionBounds } from './selection-utils';\nconst PORT_BG_CLASS_NAME = 'workflow-port-bg';\n\nexport interface HoverLayerOptions extends LayerOptions {\n canHovered?: (e: MouseEvent, service: WorkflowHoverService) => boolean;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-namespace\nexport namespace HoverLayerOptions {\n export const DEFAULT: HoverLayerOptions = {\n canHovered: () => true,\n };\n}\n\nconst LINE_CLASS_NAME = '.gedit-flow-activity-line';\nconst NODE_CLASS_NAME = '.gedit-flow-activity-node';\n\n@injectable()\nexport class HoverLayer extends Layer<HoverLayerOptions> {\n static type = 'HoverLayer';\n\n @inject(WorkflowDocument) document: WorkflowDocument;\n\n @inject(WorkflowSelectService) selectionService: WorkflowSelectService;\n\n @inject(WorkflowDragService) dragService: WorkflowDragService;\n\n @inject(WorkflowHoverService) hoverService: WorkflowHoverService;\n\n @inject(WorkflowLinesManager)\n linesManager: WorkflowLinesManager;\n\n @observeEntity(EditorStateConfigEntity)\n protected editorStateConfig: EditorStateConfigEntity;\n\n @observeEntity(SelectorBoxConfigEntity)\n protected selectorBoxConfigEntity: SelectorBoxConfigEntity;\n\n @inject(PlaygroundConfigEntity) configEntity: PlaygroundConfigEntity;\n\n /**\n * 监听节点 transform\n */\n @observeEntityDatas(WorkflowNodeEntity, FlowNodeTransformData)\n protected readonly nodeTransforms: FlowNodeTransformData[];\n\n /**\n * 按选中排序\n * @private\n */\n protected nodeTransformsWithSort: FlowNodeTransformData[] = [];\n\n autorun(): void {\n const { activatedNode } = this.selectionService;\n this.nodeTransformsWithSort = this.nodeTransforms\n .filter(n => n.entity.id !== 'root')\n .reverse() // 后创建的排在前面\n .sort(n1 => (n1.entity === activatedNode ? -1 : 0));\n }\n\n /**\n * 监听线条\n */\n @observeEntities(WorkflowLineEntity)\n protected readonly lines: WorkflowLineEntity[];\n\n /**\n * 是否正在调整线条\n * @protected\n */\n get isDrawing(): boolean {\n return this.linesManager.isDrawing;\n }\n\n onReady(): void {\n this.options = {\n ...HoverLayerOptions.DEFAULT,\n ...this.options,\n };\n this.toDispose.pushAll([\n // 监听画布鼠标移动事件\n this.listenPlaygroundEvent('mousemove', (e: MouseEvent) => {\n this.hoverService.hoveredPos = this.config.getPosFromMouseEvent(e);\n if (!this.isEnabled()) {\n return;\n }\n if (!this.options.canHovered!(e, this.hoverService)) {\n return;\n }\n const mousePos = this.config.getPosFromMouseEvent(e);\n // 更新 hover 状态\n this.updateHoveredState(mousePos, e?.target as HTMLElement);\n }),\n this.selectionService.onSelectionChanged(() => this.autorun()),\n // 控制选中逻辑\n this.listenPlaygroundEvent('mousedown', (e: MouseEvent): boolean | undefined => {\n if (!this.isEnabled() || this.isDrawing) {\n return undefined;\n }\n const { hoveredNode } = this.hoverService;\n // 重置线条\n if (hoveredNode && hoveredNode instanceof WorkflowLineEntity) {\n this.dragService.resetLine(hoveredNode, e);\n return true;\n }\n if (\n hoveredNode &&\n hoveredNode instanceof WorkflowPortEntity &&\n hoveredNode.portType !== 'input' &&\n !hoveredNode.disabled &&\n e.button !== 1\n ) {\n e.stopPropagation();\n e.preventDefault();\n this.dragService.startDrawingLine(hoveredNode, e);\n return true;\n }\n const mousePos = this.config.getPosFromMouseEvent(e);\n const selectionBounds = getSelectionBounds(\n this.selectionService.selection,\n // 这里只考虑多选模式,单选模式已经下沉到 use-node-render 中\n true,\n );\n if (selectionBounds.width > 0 && selectionBounds.contains(mousePos.x, mousePos.y)) {\n /**\n * 拖拽选择框\n */\n this.dragService.startDragSelectedNodes(e).then(dragSuccess => {\n if (!dragSuccess) {\n // 拖拽没有成功触发了点击\n if (hoveredNode && hoveredNode instanceof WorkflowNodeEntity) {\n if (e.metaKey || e.shiftKey || e.ctrlKey) {\n this.selectionService.toggleSelect(hoveredNode);\n } else {\n this.selectionService.selectNode(hoveredNode);\n }\n } else {\n this.selectionService.clear();\n }\n }\n });\n // 这里会组织触发 selector box\n return true;\n } else {\n if (!hoveredNode) {\n this.selectionService.clear();\n }\n }\n return undefined;\n }),\n ]);\n }\n\n /**\n * 更新 hoverd\n * @param mousePos\n */\n updateHoveredState(mousePos: IPoint, target?: HTMLElement): void {\n const { hoverService } = this;\n const nodeTransforms = this.nodeTransformsWithSort;\n // // 判断连接点是否 hover\n const portHovered = this.linesManager.getPortFromMousePos(mousePos);\n\n const lineDomNodes = this.playgroundNode.querySelectorAll(LINE_CLASS_NAME);\n const checkTargetFromLine = [...lineDomNodes].some(lineDom =>\n lineDom.contains(target as HTMLElement),\n );\n // 默认 只有 output 点位可以 hover\n if (portHovered) {\n // 输出点可以直接选中\n if (portHovered.portType === 'output') {\n hoverService.updateHoveredKey(portHovered.id);\n } else if (checkTargetFromLine || target?.className?.includes?.(PORT_BG_CLASS_NAME)) {\n // 输入点采用获取最接近的线条\n const lineHovered = this.linesManager.getCloseInLineFromMousePos(mousePos);\n if (lineHovered) {\n this.updateHoveredKey(lineHovered.id);\n }\n }\n return;\n }\n\n // Drawing 情况,不能选中节点和线条\n if (this.isDrawing) {\n return;\n }\n\n const nodeHovered = nodeTransforms.find((trans: FlowNodeTransformData) =>\n trans.bounds.contains(mousePos.x, mousePos.y),\n )?.entity as WorkflowNodeEntity;\n\n // 判断当前鼠标位置所在元素是否在节点内部\n const nodeDomNodes = this.playgroundNode.querySelectorAll(NODE_CLASS_NAME);\n const checkTargetFromNode = [...nodeDomNodes].some(nodeDom =>\n nodeDom.contains(target as HTMLElement),\n );\n\n if (nodeHovered || checkTargetFromNode) {\n if (nodeHovered?.id) {\n this.updateHoveredKey(nodeHovered.id);\n }\n }\n\n const nodeInContainer = !!(nodeHovered?.parent && nodeHovered.parent.flowNodeType !== 'root');\n\n // 获取最接近的线条\n // 线条会相交需要获取最接近点位的线条,不能删除的线条不能被选中\n const lineHovered = checkTargetFromLine\n ? this.linesManager.getCloseInLineFromMousePos(mousePos)\n : undefined;\n const lineInContainer = !!lineHovered?.inContainer;\n\n // 判断容器内节点是否 hover\n if (nodeHovered && nodeInContainer) {\n this.updateHoveredKey(nodeHovered.id);\n return;\n }\n // 判断容器内线条是否 hover\n if (lineHovered && lineInContainer) {\n this.updateHoveredKey(lineHovered.id);\n return;\n }\n\n // 判断节点是否 hover\n if (nodeHovered) {\n this.updateHoveredKey(nodeHovered.id);\n return;\n }\n // 判断线条是否 hover\n if (lineHovered) {\n this.hoverService.updateHoveredKey(lineHovered.id);\n return;\n }\n\n // 上述逻辑都未命中 则清空 hoverd\n hoverService.clearHovered();\n\n const currentState = this.editorStateConfig.getCurrentState();\n const isMouseFriendly = currentState === EditorState.STATE_MOUSE_FRIENDLY_SELECT;\n\n // 鼠标优先,并且不是按住 shift 键,更新为小手\n if (isMouseFriendly && !this.editorStateConfig.isPressingShift) {\n this.configEntity.updateCursor('grab');\n }\n }\n\n updateHoveredKey(key: string): void {\n // 鼠标优先交互模式,如果是 hover,需要将鼠标的小手去掉,还原鼠标原有样式\n this.configEntity.updateCursor('default');\n this.hoverService.updateHoveredKey(key);\n }\n\n /**\n * 判断是否能够 hover\n * @returns 是否能 hover\n */\n isEnabled(): boolean {\n const currentState = this.editorStateConfig.getCurrentState();\n // 选择框情况禁止 hover\n return (\n // 鼠标友好模式下,也需要支持 hover 效果,不然线条选择不到\n // Coze 中没有使用该插件,需要在 workflow/render 包相应位置改动\n (currentState === EditorState.STATE_SELECT ||\n currentState === EditorState.STATE_MOUSE_FRIENDLY_SELECT) &&\n !this.selectorBoxConfigEntity.isStart &&\n !this.dragService.isDragging\n );\n }\n}\n","import { FlowNodeTransformData, FlowNodeEntity } from '@flowgram.ai/document';\nimport { type Entity } from '@flowgram.ai/core';\nimport { Rectangle } from '@flowgram.ai/utils';\n\nconst BOUNDS_PADDING = 2;\n\nexport function getSelectionBounds(\n selection: Entity[],\n ignoreOneSelect?: boolean, // 忽略单选\n): Rectangle {\n const selectedNodes = selection.filter(node => node instanceof FlowNodeEntity);\n\n if (!selectedNodes?.length) {\n return Rectangle.EMPTY;\n }\n\n // 选中单个的时候不显示\n if (\n ignoreOneSelect &&\n selectedNodes.length === 1 &&\n // 选中的节点不包含多个子节点\n (selectedNodes[0] as FlowNodeEntity).childrenLength <= 1\n ) {\n return Rectangle.EMPTY;\n }\n\n return Rectangle.enlarge(selectedNodes.map(n => n.getData(FlowNodeTransformData)!.bounds)).pad(\n BOUNDS_PADDING,\n );\n}\n"],"mappings":"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","names":["FlowNodeTransformData","HoverLayerOptions","lineHovered","FlowNodeTransformData"]}
|
|
1
|
+
{"version":3,"sources":["../../src/create-free-hover-plugin.ts","../../src/hover-layer.tsx","../../src/selection-utils.ts"],"sourcesContent":["/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { definePluginCreator } from '@flowgram.ai/core';\n\nimport { HoverLayer } from './hover-layer';\n\nexport const createFreeHoverPlugin = definePluginCreator({\n onInit(ctx): void {\n ctx.playground.registerLayer(HoverLayer);\n },\n});\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\n/* eslint-disable complexity */\nimport { inject, injectable } from 'inversify';\nimport { type IPoint } from '@flowgram.ai/utils';\nimport { SelectorBoxConfigEntity } from '@flowgram.ai/renderer';\nimport {\n WorkflowDocument,\n WorkflowDragService,\n WorkflowHoverService,\n WorkflowLineEntity,\n WorkflowLinesManager,\n WorkflowNodeEntity,\n WorkflowSelectService,\n} from '@flowgram.ai/free-layout-core';\nimport { WorkflowPortEntity } from '@flowgram.ai/free-layout-core';\nimport { FlowNodeBaseType, FlowNodeTransformData } from '@flowgram.ai/document';\nimport {\n EditorState,\n EditorStateConfigEntity,\n Layer,\n PlaygroundConfigEntity,\n observeEntities,\n observeEntity,\n observeEntityDatas,\n type LayerOptions,\n} from '@flowgram.ai/core';\n\nimport { getSelectionBounds } from './selection-utils';\nconst PORT_BG_CLASS_NAME = 'workflow-port-bg';\n\nexport interface HoverLayerOptions extends LayerOptions {\n canHovered?: (e: MouseEvent, service: WorkflowHoverService) => boolean;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-namespace\nexport namespace HoverLayerOptions {\n export const DEFAULT: HoverLayerOptions = {\n canHovered: () => true,\n };\n}\n\nconst LINE_CLASS_NAME = '.gedit-flow-activity-line';\nconst NODE_CLASS_NAME = '.gedit-flow-activity-node';\n\n@injectable()\nexport class HoverLayer extends Layer<HoverLayerOptions> {\n static type = 'HoverLayer';\n\n @inject(WorkflowDocument) document: WorkflowDocument;\n\n @inject(WorkflowSelectService) selectionService: WorkflowSelectService;\n\n @inject(WorkflowDragService) dragService: WorkflowDragService;\n\n @inject(WorkflowHoverService) hoverService: WorkflowHoverService;\n\n @inject(WorkflowLinesManager)\n linesManager: WorkflowLinesManager;\n\n @observeEntity(EditorStateConfigEntity)\n protected editorStateConfig: EditorStateConfigEntity;\n\n @observeEntity(SelectorBoxConfigEntity)\n protected selectorBoxConfigEntity: SelectorBoxConfigEntity;\n\n @inject(PlaygroundConfigEntity) configEntity: PlaygroundConfigEntity;\n\n /**\n * 监听节点 transform\n */\n @observeEntityDatas(WorkflowNodeEntity, FlowNodeTransformData)\n protected readonly nodeTransforms: FlowNodeTransformData[];\n\n /**\n * 按选中排序\n * @private\n */\n protected nodeTransformsWithSort: FlowNodeTransformData[] = [];\n\n autorun(): void {\n const { activatedNode } = this.selectionService;\n this.nodeTransformsWithSort = this.nodeTransforms\n .filter((n) => n.entity.id !== 'root' && n.entity.flowNodeType !== FlowNodeBaseType.GROUP)\n .reverse() // 后创建的排在前面\n .sort((n1) => (n1.entity === activatedNode ? -1 : 0));\n }\n\n /**\n * 监听线条\n */\n @observeEntities(WorkflowLineEntity)\n protected readonly lines: WorkflowLineEntity[];\n\n /**\n * 是否正在调整线条\n * @protected\n */\n get isDrawing(): boolean {\n return this.linesManager.isDrawing;\n }\n\n onReady(): void {\n this.options = {\n ...HoverLayerOptions.DEFAULT,\n ...this.options,\n };\n this.toDispose.pushAll([\n // 监听主动触发的 hover 事件\n this.hoverService.onUpdateHoverPosition((hoverPosition) => {\n const { position, target } = hoverPosition;\n const canvasPosition = this.config.getPosFromMouseEvent({\n clientX: position.x,\n clientY: position.y,\n });\n this.updateHoveredState(canvasPosition, target);\n }),\n // 监听画布鼠标移动事件\n this.listenPlaygroundEvent('mousemove', (e: MouseEvent) => {\n this.hoverService.hoveredPos = this.config.getPosFromMouseEvent(e);\n if (!this.isEnabled()) {\n return;\n }\n if (!this.options.canHovered!(e, this.hoverService)) {\n return;\n }\n const mousePos = this.config.getPosFromMouseEvent(e);\n // 更新 hover 状态\n this.updateHoveredState(mousePos, e?.target as HTMLElement);\n }),\n this.selectionService.onSelectionChanged(() => this.autorun()),\n // 控制触控\n this.listenPlaygroundEvent('touchstart', (e: MouseEvent): boolean | undefined => {\n if (!this.isEnabled() || this.isDrawing) {\n return undefined;\n }\n return this.handleDragLine(e);\n }),\n // 控制选中逻辑\n this.listenPlaygroundEvent('mousedown', (e: MouseEvent): boolean | undefined => {\n if (!this.isEnabled() || this.isDrawing) {\n return undefined;\n }\n const { hoveredNode } = this.hoverService;\n const lineDrag = this.handleDragLine(e);\n if (lineDrag) {\n return true;\n }\n const mousePos = this.config.getPosFromMouseEvent(e);\n const selectionBounds = getSelectionBounds(\n this.selectionService.selection,\n // 这里只考虑多选模式,单选模式已经下沉到 use-node-render 中\n true\n );\n if (selectionBounds.width > 0 && selectionBounds.contains(mousePos.x, mousePos.y)) {\n /**\n * 拖拽选择框\n */\n this.dragService.startDragSelectedNodes(e)?.then((dragSuccess) => {\n if (!dragSuccess) {\n // 拖拽没有成功触发了点击\n if (hoveredNode && hoveredNode instanceof WorkflowNodeEntity) {\n // 追加选择\n if (e.shiftKey) {\n this.selectionService.toggleSelect(hoveredNode);\n } else {\n this.selectionService.selectNode(hoveredNode);\n }\n } else {\n this.selectionService.clear();\n }\n }\n });\n // 这里会组织触发 selector box\n return true;\n } else {\n if (!hoveredNode) {\n this.selectionService.clear();\n }\n }\n return undefined;\n }),\n ]);\n }\n\n /**\n * 更新 hoverd\n * @param mousePos\n */\n updateHoveredState(mousePos: IPoint, target?: HTMLElement): void {\n const { hoverService } = this;\n const nodeTransforms = this.nodeTransformsWithSort;\n const outputPortHovered = this.linesManager.getPortFromMousePos(mousePos, 'output');\n const inputPortHovered = this.linesManager.getPortFromMousePos(mousePos, 'input');\n // 在两个端口叠加情况,优先使用 outputPort\n const portHovered = outputPortHovered || inputPortHovered;\n\n const lineDomNodes = this.playgroundNode.querySelectorAll(LINE_CLASS_NAME);\n const checkTargetFromLine = [...lineDomNodes].some((lineDom) =>\n lineDom.contains(target as HTMLElement)\n );\n if (portHovered) {\n if (this.document.options.twoWayConnection) {\n hoverService.updateHoveredKey(portHovered.id);\n } else {\n // 默认 只有 output 点位可以 hover\n if (portHovered.portType === 'output') {\n hoverService.updateHoveredKey(portHovered.id);\n } else if (checkTargetFromLine || target?.className?.includes?.(PORT_BG_CLASS_NAME)) {\n // 输入点采用获取最接近的线条\n const lineHovered = this.linesManager.getCloseInLineFromMousePos(mousePos);\n if (lineHovered) {\n this.updateHoveredKey(lineHovered.id);\n }\n }\n }\n return;\n }\n\n // Drawing 情况,不能选中节点和线条\n if (this.isDrawing) {\n return;\n }\n\n const nodeHovered = nodeTransforms.find((trans: FlowNodeTransformData) =>\n trans.bounds.contains(mousePos.x, mousePos.y)\n )?.entity as WorkflowNodeEntity;\n\n // 判断当前鼠标位置所在元素是否在节点内部\n const nodeDomNodes = this.playgroundNode.querySelectorAll(NODE_CLASS_NAME);\n const checkTargetFromNode = [...nodeDomNodes].some((nodeDom) =>\n nodeDom.contains(target as HTMLElement)\n );\n\n if (nodeHovered || checkTargetFromNode) {\n if (nodeHovered?.id) {\n this.updateHoveredKey(nodeHovered.id);\n }\n }\n\n // 获取最接近的线条\n // 线条会相交需要获取最接近点位的线条,不能删除的线条不能被选中\n const lineHovered = checkTargetFromLine\n ? this.linesManager.getCloseInLineFromMousePos(mousePos)\n : undefined;\n\n if (nodeHovered && lineHovered) {\n const nodeStackIndex = nodeHovered.renderData.stackIndex;\n const lineStackIndex = lineHovered.stackIndex;\n if (nodeStackIndex > lineStackIndex) {\n return this.updateHoveredKey(nodeHovered.id);\n } else {\n return this.updateHoveredKey(lineHovered.id);\n }\n }\n\n // 判断节点是否 hover\n if (nodeHovered) {\n return this.updateHoveredKey(nodeHovered.id);\n }\n // 判断线条是否 hover\n if (lineHovered) {\n return this.updateHoveredKey(lineHovered.id);\n }\n\n // 上述逻辑都未命中 则清空 hovered\n hoverService.clearHovered();\n\n const currentState = this.editorStateConfig.getCurrentState();\n const isMouseFriendly = currentState === EditorState.STATE_MOUSE_FRIENDLY_SELECT;\n\n // 鼠标优先,并且不是按住 shift 键,更新为小手\n if (isMouseFriendly && !this.editorStateConfig.isPressingShift) {\n this.configEntity.updateCursor('grab');\n }\n }\n\n updateHoveredKey(key: string): void {\n // 鼠标优先交互模式,如果是 hover,需要将鼠标的小手去掉,还原鼠标原有样式\n this.configEntity.updateCursor('default');\n this.hoverService.updateHoveredKey(key);\n }\n\n /**\n * 判断是否能够 hover\n * @returns 是否能 hover\n */\n isEnabled(): boolean {\n const currentState = this.editorStateConfig.getCurrentState();\n // 选择框情况禁止 hover\n return (\n // 鼠标友好模式下,也需要支持 hover 效果,不然线条选择不到\n // Coze 中没有使用该插件,需要在 workflow/render 包相应位置改动\n (currentState === EditorState.STATE_SELECT ||\n currentState === EditorState.STATE_MOUSE_FRIENDLY_SELECT) &&\n !this.selectorBoxConfigEntity.isStart &&\n !this.dragService.isDragging\n );\n }\n\n private handleDragLine(e: MouseEvent): boolean | undefined {\n const { someHovered } = this.hoverService;\n // 重置线条\n if (someHovered && someHovered instanceof WorkflowLineEntity) {\n this.dragService.resetLine(someHovered, e);\n return true;\n }\n if (\n someHovered &&\n someHovered instanceof WorkflowPortEntity &&\n !someHovered.disabled &&\n e.button !== 1\n ) {\n e.stopPropagation();\n e.preventDefault();\n this.dragService.startDrawingLine(someHovered, e);\n return true;\n }\n }\n}\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { Rectangle } from '@flowgram.ai/utils';\nimport { WorkflowNodeEntity } from '@flowgram.ai/free-layout-core';\nimport { FlowNodeTransformData } from '@flowgram.ai/document';\nimport { type Entity } from '@flowgram.ai/core';\n\nconst BOUNDS_PADDING = 2;\n\nexport function getSelectionBounds(\n selection: Entity[],\n ignoreOneSelect: boolean = true // 忽略单选\n): Rectangle {\n const selectedNodes = selection.filter((node) => node instanceof WorkflowNodeEntity);\n\n // 选中单个的时候不显示\n return selectedNodes.length > (ignoreOneSelect ? 1 : 0)\n ? Rectangle.enlarge(selectedNodes.map((n) => n.getData(FlowNodeTransformData)!.bounds)).pad(\n BOUNDS_PADDING\n )\n : Rectangle.EMPTY;\n}\n"],"mappings":";;;;;;;;;;;;AAKA,SAAS,2BAA2B;;;ACCpC,SAAS,QAAQ,kBAAkB;AAEnC,SAAS,+BAA+B;AACxC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,sBAAAA;AAAA,EACA;AAAA,OACK;AACP,SAAS,0BAA0B;AACnC,SAAS,kBAAkB,yBAAAC,8BAA6B;AACxD;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAEK;;;ACxBP,SAAS,iBAAiB;AAC1B,SAAS,0BAA0B;AACnC,SAAS,6BAA6B;AAGtC,IAAM,iBAAiB;AAEhB,SAAS,mBACd,WACA,kBAA2B,MAChB;AACX,QAAM,gBAAgB,UAAU,OAAO,CAAC,SAAS,gBAAgB,kBAAkB;AAGnF,SAAO,cAAc,UAAU,kBAAkB,IAAI,KACjD,UAAU,QAAQ,cAAc,IAAI,CAAC,MAAM,EAAE,QAAQ,qBAAqB,EAAG,MAAM,CAAC,EAAE;AAAA,IACpF;AAAA,EACF,IACA,UAAU;AAChB;;;ADQA,IAAM,qBAAqB;AAOpB,IAAU;AAAA,CAAV,CAAUC,uBAAV;AACE,EAAMA,mBAAA,UAA6B;AAAA,IACxC,YAAY,MAAM;AAAA,EACpB;AAAA,GAHe;AAMjB,IAAM,kBAAkB;AACxB,IAAM,kBAAkB;AAGjB,IAAM,aAAN,cAAyB,MAAyB;AAAA,EAAlD;AAAA;AAgCL;AAAA;AAAA;AAAA;AAAA,SAAU,yBAAkD,CAAC;AAAA;AAAA,EAE7D,UAAgB;AACd,UAAM,EAAE,cAAc,IAAI,KAAK;AAC/B,SAAK,yBAAyB,KAAK,eAChC,OAAO,CAAC,MAAM,EAAE,OAAO,OAAO,UAAU,EAAE,OAAO,iBAAiB,iBAAiB,KAAK,EACxF,QAAQ,EACR,KAAK,CAAC,OAAQ,GAAG,WAAW,gBAAgB,KAAK,CAAE;AAAA,EACxD;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,IAAI,YAAqB;AACvB,WAAO,KAAK,aAAa;AAAA,EAC3B;AAAA,EAEA,UAAgB;AACd,SAAK,UAAU;AAAA,MACb,GAAG,kBAAkB;AAAA,MACrB,GAAG,KAAK;AAAA,IACV;AACA,SAAK,UAAU,QAAQ;AAAA;AAAA,MAErB,KAAK,aAAa,sBAAsB,CAAC,kBAAkB;AACzD,cAAM,EAAE,UAAU,OAAO,IAAI;AAC7B,cAAM,iBAAiB,KAAK,OAAO,qBAAqB;AAAA,UACtD,SAAS,SAAS;AAAA,UAClB,SAAS,SAAS;AAAA,QACpB,CAAC;AACD,aAAK,mBAAmB,gBAAgB,MAAM;AAAA,MAChD,CAAC;AAAA;AAAA,MAED,KAAK,sBAAsB,aAAa,CAAC,MAAkB;AACzD,aAAK,aAAa,aAAa,KAAK,OAAO,qBAAqB,CAAC;AACjE,YAAI,CAAC,KAAK,UAAU,GAAG;AACrB;AAAA,QACF;AACA,YAAI,CAAC,KAAK,QAAQ,WAAY,GAAG,KAAK,YAAY,GAAG;AACnD;AAAA,QACF;AACA,cAAM,WAAW,KAAK,OAAO,qBAAqB,CAAC;AAEnD,aAAK,mBAAmB,UAAU,GAAG,MAAqB;AAAA,MAC5D,CAAC;AAAA,MACD,KAAK,iBAAiB,mBAAmB,MAAM,KAAK,QAAQ,CAAC;AAAA;AAAA,MAE7D,KAAK,sBAAsB,cAAc,CAAC,MAAuC;AAC/E,YAAI,CAAC,KAAK,UAAU,KAAK,KAAK,WAAW;AACvC,iBAAO;AAAA,QACT;AACA,eAAO,KAAK,eAAe,CAAC;AAAA,MAC9B,CAAC;AAAA;AAAA,MAED,KAAK,sBAAsB,aAAa,CAAC,MAAuC;AAC9E,YAAI,CAAC,KAAK,UAAU,KAAK,KAAK,WAAW;AACvC,iBAAO;AAAA,QACT;AACA,cAAM,EAAE,YAAY,IAAI,KAAK;AAC7B,cAAM,WAAW,KAAK,eAAe,CAAC;AACtC,YAAI,UAAU;AACZ,iBAAO;AAAA,QACT;AACA,cAAM,WAAW,KAAK,OAAO,qBAAqB,CAAC;AACnD,cAAM,kBAAkB;AAAA,UACtB,KAAK,iBAAiB;AAAA;AAAA,UAEtB;AAAA,QACF;AACA,YAAI,gBAAgB,QAAQ,KAAK,gBAAgB,SAAS,SAAS,GAAG,SAAS,CAAC,GAAG;AAIjF,eAAK,YAAY,uBAAuB,CAAC,GAAG,KAAK,CAAC,gBAAgB;AAChE,gBAAI,CAAC,aAAa;AAEhB,kBAAI,eAAe,uBAAuBC,qBAAoB;AAE5D,oBAAI,EAAE,UAAU;AACd,uBAAK,iBAAiB,aAAa,WAAW;AAAA,gBAChD,OAAO;AACL,uBAAK,iBAAiB,WAAW,WAAW;AAAA,gBAC9C;AAAA,cACF,OAAO;AACL,qBAAK,iBAAiB,MAAM;AAAA,cAC9B;AAAA,YACF;AAAA,UACF,CAAC;AAED,iBAAO;AAAA,QACT,OAAO;AACL,cAAI,CAAC,aAAa;AAChB,iBAAK,iBAAiB,MAAM;AAAA,UAC9B;AAAA,QACF;AACA,eAAO;AAAA,MACT,CAAC;AAAA,IACH,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,mBAAmB,UAAkB,QAA4B;AAC/D,UAAM,EAAE,aAAa,IAAI;AACzB,UAAM,iBAAiB,KAAK;AAC5B,UAAM,oBAAoB,KAAK,aAAa,oBAAoB,UAAU,QAAQ;AAClF,UAAM,mBAAmB,KAAK,aAAa,oBAAoB,UAAU,OAAO;AAEhF,UAAM,cAAc,qBAAqB;AAEzC,UAAM,eAAe,KAAK,eAAe,iBAAiB,eAAe;AACzE,UAAM,sBAAsB,CAAC,GAAG,YAAY,EAAE;AAAA,MAAK,CAAC,YAClD,QAAQ,SAAS,MAAqB;AAAA,IACxC;AACA,QAAI,aAAa;AACf,UAAI,KAAK,SAAS,QAAQ,kBAAkB;AAC1C,qBAAa,iBAAiB,YAAY,EAAE;AAAA,MAC9C,OAAO;AAEL,YAAI,YAAY,aAAa,UAAU;AACrC,uBAAa,iBAAiB,YAAY,EAAE;AAAA,QAC9C,WAAW,uBAAuB,QAAQ,WAAW,WAAW,kBAAkB,GAAG;AAEnF,gBAAMC,eAAc,KAAK,aAAa,2BAA2B,QAAQ;AACzE,cAAIA,cAAa;AACf,iBAAK,iBAAiBA,aAAY,EAAE;AAAA,UACtC;AAAA,QACF;AAAA,MACF;AACA;AAAA,IACF;AAGA,QAAI,KAAK,WAAW;AAClB;AAAA,IACF;AAEA,UAAM,cAAc,eAAe;AAAA,MAAK,CAAC,UACvC,MAAM,OAAO,SAAS,SAAS,GAAG,SAAS,CAAC;AAAA,IAC9C,GAAG;AAGH,UAAM,eAAe,KAAK,eAAe,iBAAiB,eAAe;AACzE,UAAM,sBAAsB,CAAC,GAAG,YAAY,EAAE;AAAA,MAAK,CAAC,YAClD,QAAQ,SAAS,MAAqB;AAAA,IACxC;AAEA,QAAI,eAAe,qBAAqB;AACtC,UAAI,aAAa,IAAI;AACnB,aAAK,iBAAiB,YAAY,EAAE;AAAA,MACtC;AAAA,IACF;AAIA,UAAM,cAAc,sBAChB,KAAK,aAAa,2BAA2B,QAAQ,IACrD;AAEJ,QAAI,eAAe,aAAa;AAC9B,YAAM,iBAAiB,YAAY,WAAW;AAC9C,YAAM,iBAAiB,YAAY;AACnC,UAAI,iBAAiB,gBAAgB;AACnC,eAAO,KAAK,iBAAiB,YAAY,EAAE;AAAA,MAC7C,OAAO;AACL,eAAO,KAAK,iBAAiB,YAAY,EAAE;AAAA,MAC7C;AAAA,IACF;AAGA,QAAI,aAAa;AACf,aAAO,KAAK,iBAAiB,YAAY,EAAE;AAAA,IAC7C;AAEA,QAAI,aAAa;AACf,aAAO,KAAK,iBAAiB,YAAY,EAAE;AAAA,IAC7C;AAGA,iBAAa,aAAa;AAE1B,UAAM,eAAe,KAAK,kBAAkB,gBAAgB;AAC5D,UAAM,kBAAkB,iBAAiB,YAAY;AAGrD,QAAI,mBAAmB,CAAC,KAAK,kBAAkB,iBAAiB;AAC9D,WAAK,aAAa,aAAa,MAAM;AAAA,IACvC;AAAA,EACF;AAAA,EAEA,iBAAiB,KAAmB;AAElC,SAAK,aAAa,aAAa,SAAS;AACxC,SAAK,aAAa,iBAAiB,GAAG;AAAA,EACxC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,YAAqB;AACnB,UAAM,eAAe,KAAK,kBAAkB,gBAAgB;AAE5D;AAAA;AAAA;AAAA,OAGG,iBAAiB,YAAY,gBAC5B,iBAAiB,YAAY,gCAC/B,CAAC,KAAK,wBAAwB,WAC9B,CAAC,KAAK,YAAY;AAAA;AAAA,EAEtB;AAAA,EAEQ,eAAe,GAAoC;AACzD,UAAM,EAAE,YAAY,IAAI,KAAK;AAE7B,QAAI,eAAe,uBAAuB,oBAAoB;AAC5D,WAAK,YAAY,UAAU,aAAa,CAAC;AACzC,aAAO;AAAA,IACT;AACA,QACE,eACA,uBAAuB,sBACvB,CAAC,YAAY,YACb,EAAE,WAAW,GACb;AACA,QAAE,gBAAgB;AAClB,QAAE,eAAe;AACjB,WAAK,YAAY,iBAAiB,aAAa,CAAC;AAChD,aAAO;AAAA,IACT;AAAA,EACF;AACF;AAjRa,WACJ,OAAO;AAEY;AAAA,EAAzB,OAAO,gBAAgB;AAAA,GAHb,WAGe;AAEK;AAAA,EAA9B,OAAO,qBAAqB;AAAA,GALlB,WAKoB;AAEF;AAAA,EAA5B,OAAO,mBAAmB;AAAA,GAPhB,WAOkB;AAEC;AAAA,EAA7B,OAAO,oBAAoB;AAAA,GATjB,WASmB;AAG9B;AAAA,EADC,OAAO,oBAAoB;AAAA,GAXjB,WAYX;AAGU;AAAA,EADT,cAAc,uBAAuB;AAAA,GAd3B,WAeD;AAGA;AAAA,EADT,cAAc,uBAAuB;AAAA,GAjB3B,WAkBD;AAEsB;AAAA,EAA/B,OAAO,sBAAsB;AAAA,GApBnB,WAoBqB;AAMb;AAAA,EADlB,mBAAmBD,qBAAoBE,sBAAqB;AAAA,GAzBlD,WA0BQ;AAoBA;AAAA,EADlB,gBAAgB,kBAAkB;AAAA,GA7CxB,WA8CQ;AA9CR,aAAN;AAAA,EADN,WAAW;AAAA,GACC;;;ADxCN,IAAM,wBAAwB,oBAAoB;AAAA,EACvD,OAAO,KAAW;AAChB,QAAI,WAAW,cAAc,UAAU;AAAA,EACzC;AACF,CAAC;","names":["WorkflowNodeEntity","FlowNodeTransformData","HoverLayerOptions","WorkflowNodeEntity","lineHovered","FlowNodeTransformData"]}
|
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import * as _flowgram_ai_core from '@flowgram.ai/core';
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
|
|
5
|
+
* SPDX-License-Identifier: MIT
|
|
6
|
+
*/
|
|
3
7
|
declare const createFreeHoverPlugin: _flowgram_ai_core.PluginCreator<unknown>;
|
|
4
8
|
|
|
5
9
|
export { createFreeHoverPlugin };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import * as _flowgram_ai_core from '@flowgram.ai/core';
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
|
|
5
|
+
* SPDX-License-Identifier: MIT
|
|
6
|
+
*/
|
|
3
7
|
declare const createFreeHoverPlugin: _flowgram_ai_core.PluginCreator<unknown>;
|
|
4
8
|
|
|
5
9
|
export { createFreeHoverPlugin };
|
package/dist/index.js
CHANGED
|
@@ -26,11 +26,11 @@ var __decorateClass = (decorators, target, key, kind) => {
|
|
|
26
26
|
};
|
|
27
27
|
|
|
28
28
|
// src/index.ts
|
|
29
|
-
var
|
|
30
|
-
__export(
|
|
29
|
+
var index_exports = {};
|
|
30
|
+
__export(index_exports, {
|
|
31
31
|
createFreeHoverPlugin: () => createFreeHoverPlugin
|
|
32
32
|
});
|
|
33
|
-
module.exports = __toCommonJS(
|
|
33
|
+
module.exports = __toCommonJS(index_exports);
|
|
34
34
|
|
|
35
35
|
// src/create-free-hover-plugin.ts
|
|
36
36
|
var import_core2 = require("@flowgram.ai/core");
|
|
@@ -38,27 +38,21 @@ var import_core2 = require("@flowgram.ai/core");
|
|
|
38
38
|
// src/hover-layer.tsx
|
|
39
39
|
var import_inversify = require("inversify");
|
|
40
40
|
var import_renderer = require("@flowgram.ai/renderer");
|
|
41
|
+
var import_free_layout_core2 = require("@flowgram.ai/free-layout-core");
|
|
42
|
+
var import_free_layout_core3 = require("@flowgram.ai/free-layout-core");
|
|
41
43
|
var import_document2 = require("@flowgram.ai/document");
|
|
42
44
|
var import_core = require("@flowgram.ai/core");
|
|
43
|
-
var import_free_layout_core = require("@flowgram.ai/free-layout-core");
|
|
44
|
-
var import_free_layout_core2 = require("@flowgram.ai/free-layout-core");
|
|
45
45
|
|
|
46
46
|
// src/selection-utils.ts
|
|
47
|
-
var import_document = require("@flowgram.ai/document");
|
|
48
47
|
var import_utils = require("@flowgram.ai/utils");
|
|
48
|
+
var import_free_layout_core = require("@flowgram.ai/free-layout-core");
|
|
49
|
+
var import_document = require("@flowgram.ai/document");
|
|
49
50
|
var BOUNDS_PADDING = 2;
|
|
50
|
-
function getSelectionBounds(selection, ignoreOneSelect) {
|
|
51
|
-
const selectedNodes = selection.filter((node) => node instanceof
|
|
52
|
-
|
|
53
|
-
return import_utils.Rectangle.EMPTY;
|
|
54
|
-
}
|
|
55
|
-
if (ignoreOneSelect && selectedNodes.length === 1 && // 选中的节点不包含多个子节点
|
|
56
|
-
selectedNodes[0].childrenLength <= 1) {
|
|
57
|
-
return import_utils.Rectangle.EMPTY;
|
|
58
|
-
}
|
|
59
|
-
return import_utils.Rectangle.enlarge(selectedNodes.map((n) => n.getData(import_document.FlowNodeTransformData).bounds)).pad(
|
|
51
|
+
function getSelectionBounds(selection, ignoreOneSelect = true) {
|
|
52
|
+
const selectedNodes = selection.filter((node) => node instanceof import_free_layout_core.WorkflowNodeEntity);
|
|
53
|
+
return selectedNodes.length > (ignoreOneSelect ? 1 : 0) ? import_utils.Rectangle.enlarge(selectedNodes.map((n) => n.getData(import_document.FlowNodeTransformData).bounds)).pad(
|
|
60
54
|
BOUNDS_PADDING
|
|
61
|
-
);
|
|
55
|
+
) : import_utils.Rectangle.EMPTY;
|
|
62
56
|
}
|
|
63
57
|
|
|
64
58
|
// src/hover-layer.tsx
|
|
@@ -82,7 +76,7 @@ var HoverLayer = class extends import_core.Layer {
|
|
|
82
76
|
}
|
|
83
77
|
autorun() {
|
|
84
78
|
const { activatedNode } = this.selectionService;
|
|
85
|
-
this.nodeTransformsWithSort = this.nodeTransforms.filter((n) => n.entity.id !== "root").reverse().sort((n1) => n1.entity === activatedNode ? -1 : 0);
|
|
79
|
+
this.nodeTransformsWithSort = this.nodeTransforms.filter((n) => n.entity.id !== "root" && n.entity.flowNodeType !== import_document2.FlowNodeBaseType.GROUP).reverse().sort((n1) => n1.entity === activatedNode ? -1 : 0);
|
|
86
80
|
}
|
|
87
81
|
/**
|
|
88
82
|
* 是否正在调整线条
|
|
@@ -97,6 +91,15 @@ var HoverLayer = class extends import_core.Layer {
|
|
|
97
91
|
...this.options
|
|
98
92
|
};
|
|
99
93
|
this.toDispose.pushAll([
|
|
94
|
+
// 监听主动触发的 hover 事件
|
|
95
|
+
this.hoverService.onUpdateHoverPosition((hoverPosition) => {
|
|
96
|
+
const { position, target } = hoverPosition;
|
|
97
|
+
const canvasPosition = this.config.getPosFromMouseEvent({
|
|
98
|
+
clientX: position.x,
|
|
99
|
+
clientY: position.y
|
|
100
|
+
});
|
|
101
|
+
this.updateHoveredState(canvasPosition, target);
|
|
102
|
+
}),
|
|
100
103
|
// 监听画布鼠标移动事件
|
|
101
104
|
this.listenPlaygroundEvent("mousemove", (e) => {
|
|
102
105
|
this.hoverService.hoveredPos = this.config.getPosFromMouseEvent(e);
|
|
@@ -110,20 +113,21 @@ var HoverLayer = class extends import_core.Layer {
|
|
|
110
113
|
this.updateHoveredState(mousePos, e?.target);
|
|
111
114
|
}),
|
|
112
115
|
this.selectionService.onSelectionChanged(() => this.autorun()),
|
|
116
|
+
// 控制触控
|
|
117
|
+
this.listenPlaygroundEvent("touchstart", (e) => {
|
|
118
|
+
if (!this.isEnabled() || this.isDrawing) {
|
|
119
|
+
return void 0;
|
|
120
|
+
}
|
|
121
|
+
return this.handleDragLine(e);
|
|
122
|
+
}),
|
|
113
123
|
// 控制选中逻辑
|
|
114
124
|
this.listenPlaygroundEvent("mousedown", (e) => {
|
|
115
125
|
if (!this.isEnabled() || this.isDrawing) {
|
|
116
126
|
return void 0;
|
|
117
127
|
}
|
|
118
128
|
const { hoveredNode } = this.hoverService;
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
return true;
|
|
122
|
-
}
|
|
123
|
-
if (hoveredNode && hoveredNode instanceof import_free_layout_core2.WorkflowPortEntity && hoveredNode.portType !== "input" && !hoveredNode.disabled && e.button !== 1) {
|
|
124
|
-
e.stopPropagation();
|
|
125
|
-
e.preventDefault();
|
|
126
|
-
this.dragService.startDrawingLine(hoveredNode, e);
|
|
129
|
+
const lineDrag = this.handleDragLine(e);
|
|
130
|
+
if (lineDrag) {
|
|
127
131
|
return true;
|
|
128
132
|
}
|
|
129
133
|
const mousePos = this.config.getPosFromMouseEvent(e);
|
|
@@ -133,10 +137,10 @@ var HoverLayer = class extends import_core.Layer {
|
|
|
133
137
|
true
|
|
134
138
|
);
|
|
135
139
|
if (selectionBounds.width > 0 && selectionBounds.contains(mousePos.x, mousePos.y)) {
|
|
136
|
-
this.dragService.startDragSelectedNodes(e)
|
|
140
|
+
this.dragService.startDragSelectedNodes(e)?.then((dragSuccess) => {
|
|
137
141
|
if (!dragSuccess) {
|
|
138
|
-
if (hoveredNode && hoveredNode instanceof
|
|
139
|
-
if (e.
|
|
142
|
+
if (hoveredNode && hoveredNode instanceof import_free_layout_core2.WorkflowNodeEntity) {
|
|
143
|
+
if (e.shiftKey) {
|
|
140
144
|
this.selectionService.toggleSelect(hoveredNode);
|
|
141
145
|
} else {
|
|
142
146
|
this.selectionService.selectNode(hoveredNode);
|
|
@@ -163,18 +167,24 @@ var HoverLayer = class extends import_core.Layer {
|
|
|
163
167
|
updateHoveredState(mousePos, target) {
|
|
164
168
|
const { hoverService } = this;
|
|
165
169
|
const nodeTransforms = this.nodeTransformsWithSort;
|
|
166
|
-
const
|
|
170
|
+
const outputPortHovered = this.linesManager.getPortFromMousePos(mousePos, "output");
|
|
171
|
+
const inputPortHovered = this.linesManager.getPortFromMousePos(mousePos, "input");
|
|
172
|
+
const portHovered = outputPortHovered || inputPortHovered;
|
|
167
173
|
const lineDomNodes = this.playgroundNode.querySelectorAll(LINE_CLASS_NAME);
|
|
168
174
|
const checkTargetFromLine = [...lineDomNodes].some(
|
|
169
175
|
(lineDom) => lineDom.contains(target)
|
|
170
176
|
);
|
|
171
177
|
if (portHovered) {
|
|
172
|
-
if (
|
|
178
|
+
if (this.document.options.twoWayConnection) {
|
|
173
179
|
hoverService.updateHoveredKey(portHovered.id);
|
|
174
|
-
} else
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
180
|
+
} else {
|
|
181
|
+
if (portHovered.portType === "output") {
|
|
182
|
+
hoverService.updateHoveredKey(portHovered.id);
|
|
183
|
+
} else if (checkTargetFromLine || target?.className?.includes?.(PORT_BG_CLASS_NAME)) {
|
|
184
|
+
const lineHovered2 = this.linesManager.getCloseInLineFromMousePos(mousePos);
|
|
185
|
+
if (lineHovered2) {
|
|
186
|
+
this.updateHoveredKey(lineHovered2.id);
|
|
187
|
+
}
|
|
178
188
|
}
|
|
179
189
|
}
|
|
180
190
|
return;
|
|
@@ -194,24 +204,21 @@ var HoverLayer = class extends import_core.Layer {
|
|
|
194
204
|
this.updateHoveredKey(nodeHovered.id);
|
|
195
205
|
}
|
|
196
206
|
}
|
|
197
|
-
const nodeInContainer = !!(nodeHovered?.parent && nodeHovered.parent.flowNodeType !== "root");
|
|
198
207
|
const lineHovered = checkTargetFromLine ? this.linesManager.getCloseInLineFromMousePos(mousePos) : void 0;
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
208
|
+
if (nodeHovered && lineHovered) {
|
|
209
|
+
const nodeStackIndex = nodeHovered.renderData.stackIndex;
|
|
210
|
+
const lineStackIndex = lineHovered.stackIndex;
|
|
211
|
+
if (nodeStackIndex > lineStackIndex) {
|
|
212
|
+
return this.updateHoveredKey(nodeHovered.id);
|
|
213
|
+
} else {
|
|
214
|
+
return this.updateHoveredKey(lineHovered.id);
|
|
215
|
+
}
|
|
207
216
|
}
|
|
208
217
|
if (nodeHovered) {
|
|
209
|
-
this.updateHoveredKey(nodeHovered.id);
|
|
210
|
-
return;
|
|
218
|
+
return this.updateHoveredKey(nodeHovered.id);
|
|
211
219
|
}
|
|
212
220
|
if (lineHovered) {
|
|
213
|
-
this.
|
|
214
|
-
return;
|
|
221
|
+
return this.updateHoveredKey(lineHovered.id);
|
|
215
222
|
}
|
|
216
223
|
hoverService.clearHovered();
|
|
217
224
|
const currentState = this.editorStateConfig.getCurrentState();
|
|
@@ -236,22 +243,35 @@ var HoverLayer = class extends import_core.Layer {
|
|
|
236
243
|
(currentState === import_core.EditorState.STATE_SELECT || currentState === import_core.EditorState.STATE_MOUSE_FRIENDLY_SELECT) && !this.selectorBoxConfigEntity.isStart && !this.dragService.isDragging
|
|
237
244
|
);
|
|
238
245
|
}
|
|
246
|
+
handleDragLine(e) {
|
|
247
|
+
const { someHovered } = this.hoverService;
|
|
248
|
+
if (someHovered && someHovered instanceof import_free_layout_core2.WorkflowLineEntity) {
|
|
249
|
+
this.dragService.resetLine(someHovered, e);
|
|
250
|
+
return true;
|
|
251
|
+
}
|
|
252
|
+
if (someHovered && someHovered instanceof import_free_layout_core3.WorkflowPortEntity && !someHovered.disabled && e.button !== 1) {
|
|
253
|
+
e.stopPropagation();
|
|
254
|
+
e.preventDefault();
|
|
255
|
+
this.dragService.startDrawingLine(someHovered, e);
|
|
256
|
+
return true;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
239
259
|
};
|
|
240
260
|
HoverLayer.type = "HoverLayer";
|
|
241
261
|
__decorateClass([
|
|
242
|
-
(0, import_inversify.inject)(
|
|
262
|
+
(0, import_inversify.inject)(import_free_layout_core2.WorkflowDocument)
|
|
243
263
|
], HoverLayer.prototype, "document", 2);
|
|
244
264
|
__decorateClass([
|
|
245
|
-
(0, import_inversify.inject)(
|
|
265
|
+
(0, import_inversify.inject)(import_free_layout_core2.WorkflowSelectService)
|
|
246
266
|
], HoverLayer.prototype, "selectionService", 2);
|
|
247
267
|
__decorateClass([
|
|
248
|
-
(0, import_inversify.inject)(
|
|
268
|
+
(0, import_inversify.inject)(import_free_layout_core2.WorkflowDragService)
|
|
249
269
|
], HoverLayer.prototype, "dragService", 2);
|
|
250
270
|
__decorateClass([
|
|
251
|
-
(0, import_inversify.inject)(
|
|
271
|
+
(0, import_inversify.inject)(import_free_layout_core2.WorkflowHoverService)
|
|
252
272
|
], HoverLayer.prototype, "hoverService", 2);
|
|
253
273
|
__decorateClass([
|
|
254
|
-
(0, import_inversify.inject)(
|
|
274
|
+
(0, import_inversify.inject)(import_free_layout_core2.WorkflowLinesManager)
|
|
255
275
|
], HoverLayer.prototype, "linesManager", 2);
|
|
256
276
|
__decorateClass([
|
|
257
277
|
(0, import_core.observeEntity)(import_core.EditorStateConfigEntity)
|
|
@@ -263,10 +283,10 @@ __decorateClass([
|
|
|
263
283
|
(0, import_inversify.inject)(import_core.PlaygroundConfigEntity)
|
|
264
284
|
], HoverLayer.prototype, "configEntity", 2);
|
|
265
285
|
__decorateClass([
|
|
266
|
-
(0, import_core.observeEntityDatas)(
|
|
286
|
+
(0, import_core.observeEntityDatas)(import_free_layout_core2.WorkflowNodeEntity, import_document2.FlowNodeTransformData)
|
|
267
287
|
], HoverLayer.prototype, "nodeTransforms", 2);
|
|
268
288
|
__decorateClass([
|
|
269
|
-
(0, import_core.observeEntities)(
|
|
289
|
+
(0, import_core.observeEntities)(import_free_layout_core2.WorkflowLineEntity)
|
|
270
290
|
], HoverLayer.prototype, "lines", 2);
|
|
271
291
|
HoverLayer = __decorateClass([
|
|
272
292
|
(0, import_inversify.injectable)()
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/create-free-hover-plugin.ts","../src/hover-layer.tsx","../src/selection-utils.ts"],"sourcesContent":["export * from './create-free-hover-plugin';\n","import { definePluginCreator } from '@flowgram.ai/core';\n\nimport { HoverLayer } from './hover-layer';\n\nexport const createFreeHoverPlugin = definePluginCreator({\n onInit(ctx): void {\n ctx.playground.registerLayer(HoverLayer);\n },\n});\n","/* eslint-disable complexity */\nimport { inject, injectable } from 'inversify';\nimport { SelectorBoxConfigEntity } from '@flowgram.ai/renderer';\nimport { FlowNodeTransformData } from '@flowgram.ai/document';\nimport {\n EditorState,\n EditorStateConfigEntity,\n Layer,\n PlaygroundConfigEntity,\n observeEntities,\n observeEntity,\n observeEntityDatas,\n type LayerOptions,\n} from '@flowgram.ai/core';\nimport {\n WorkflowDocument,\n WorkflowDragService,\n WorkflowHoverService,\n WorkflowLineEntity,\n WorkflowLinesManager,\n WorkflowNodeEntity,\n WorkflowSelectService,\n} from '@flowgram.ai/free-layout-core';\nimport { WorkflowPortEntity } from '@flowgram.ai/free-layout-core';\nimport { type IPoint } from '@flowgram.ai/utils';\n\nimport { getSelectionBounds } from './selection-utils';\nconst PORT_BG_CLASS_NAME = 'workflow-port-bg';\n\nexport interface HoverLayerOptions extends LayerOptions {\n canHovered?: (e: MouseEvent, service: WorkflowHoverService) => boolean;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-namespace\nexport namespace HoverLayerOptions {\n export const DEFAULT: HoverLayerOptions = {\n canHovered: () => true,\n };\n}\n\nconst LINE_CLASS_NAME = '.gedit-flow-activity-line';\nconst NODE_CLASS_NAME = '.gedit-flow-activity-node';\n\n@injectable()\nexport class HoverLayer extends Layer<HoverLayerOptions> {\n static type = 'HoverLayer';\n\n @inject(WorkflowDocument) document: WorkflowDocument;\n\n @inject(WorkflowSelectService) selectionService: WorkflowSelectService;\n\n @inject(WorkflowDragService) dragService: WorkflowDragService;\n\n @inject(WorkflowHoverService) hoverService: WorkflowHoverService;\n\n @inject(WorkflowLinesManager)\n linesManager: WorkflowLinesManager;\n\n @observeEntity(EditorStateConfigEntity)\n protected editorStateConfig: EditorStateConfigEntity;\n\n @observeEntity(SelectorBoxConfigEntity)\n protected selectorBoxConfigEntity: SelectorBoxConfigEntity;\n\n @inject(PlaygroundConfigEntity) configEntity: PlaygroundConfigEntity;\n\n /**\n * 监听节点 transform\n */\n @observeEntityDatas(WorkflowNodeEntity, FlowNodeTransformData)\n protected readonly nodeTransforms: FlowNodeTransformData[];\n\n /**\n * 按选中排序\n * @private\n */\n protected nodeTransformsWithSort: FlowNodeTransformData[] = [];\n\n autorun(): void {\n const { activatedNode } = this.selectionService;\n this.nodeTransformsWithSort = this.nodeTransforms\n .filter(n => n.entity.id !== 'root')\n .reverse() // 后创建的排在前面\n .sort(n1 => (n1.entity === activatedNode ? -1 : 0));\n }\n\n /**\n * 监听线条\n */\n @observeEntities(WorkflowLineEntity)\n protected readonly lines: WorkflowLineEntity[];\n\n /**\n * 是否正在调整线条\n * @protected\n */\n get isDrawing(): boolean {\n return this.linesManager.isDrawing;\n }\n\n onReady(): void {\n this.options = {\n ...HoverLayerOptions.DEFAULT,\n ...this.options,\n };\n this.toDispose.pushAll([\n // 监听画布鼠标移动事件\n this.listenPlaygroundEvent('mousemove', (e: MouseEvent) => {\n this.hoverService.hoveredPos = this.config.getPosFromMouseEvent(e);\n if (!this.isEnabled()) {\n return;\n }\n if (!this.options.canHovered!(e, this.hoverService)) {\n return;\n }\n const mousePos = this.config.getPosFromMouseEvent(e);\n // 更新 hover 状态\n this.updateHoveredState(mousePos, e?.target as HTMLElement);\n }),\n this.selectionService.onSelectionChanged(() => this.autorun()),\n // 控制选中逻辑\n this.listenPlaygroundEvent('mousedown', (e: MouseEvent): boolean | undefined => {\n if (!this.isEnabled() || this.isDrawing) {\n return undefined;\n }\n const { hoveredNode } = this.hoverService;\n // 重置线条\n if (hoveredNode && hoveredNode instanceof WorkflowLineEntity) {\n this.dragService.resetLine(hoveredNode, e);\n return true;\n }\n if (\n hoveredNode &&\n hoveredNode instanceof WorkflowPortEntity &&\n hoveredNode.portType !== 'input' &&\n !hoveredNode.disabled &&\n e.button !== 1\n ) {\n e.stopPropagation();\n e.preventDefault();\n this.dragService.startDrawingLine(hoveredNode, e);\n return true;\n }\n const mousePos = this.config.getPosFromMouseEvent(e);\n const selectionBounds = getSelectionBounds(\n this.selectionService.selection,\n // 这里只考虑多选模式,单选模式已经下沉到 use-node-render 中\n true,\n );\n if (selectionBounds.width > 0 && selectionBounds.contains(mousePos.x, mousePos.y)) {\n /**\n * 拖拽选择框\n */\n this.dragService.startDragSelectedNodes(e).then(dragSuccess => {\n if (!dragSuccess) {\n // 拖拽没有成功触发了点击\n if (hoveredNode && hoveredNode instanceof WorkflowNodeEntity) {\n if (e.metaKey || e.shiftKey || e.ctrlKey) {\n this.selectionService.toggleSelect(hoveredNode);\n } else {\n this.selectionService.selectNode(hoveredNode);\n }\n } else {\n this.selectionService.clear();\n }\n }\n });\n // 这里会组织触发 selector box\n return true;\n } else {\n if (!hoveredNode) {\n this.selectionService.clear();\n }\n }\n return undefined;\n }),\n ]);\n }\n\n /**\n * 更新 hoverd\n * @param mousePos\n */\n updateHoveredState(mousePos: IPoint, target?: HTMLElement): void {\n const { hoverService } = this;\n const nodeTransforms = this.nodeTransformsWithSort;\n // // 判断连接点是否 hover\n const portHovered = this.linesManager.getPortFromMousePos(mousePos);\n\n const lineDomNodes = this.playgroundNode.querySelectorAll(LINE_CLASS_NAME);\n const checkTargetFromLine = [...lineDomNodes].some(lineDom =>\n lineDom.contains(target as HTMLElement),\n );\n // 默认 只有 output 点位可以 hover\n if (portHovered) {\n // 输出点可以直接选中\n if (portHovered.portType === 'output') {\n hoverService.updateHoveredKey(portHovered.id);\n } else if (checkTargetFromLine || target?.className?.includes?.(PORT_BG_CLASS_NAME)) {\n // 输入点采用获取最接近的线条\n const lineHovered = this.linesManager.getCloseInLineFromMousePos(mousePos);\n if (lineHovered) {\n this.updateHoveredKey(lineHovered.id);\n }\n }\n return;\n }\n\n // Drawing 情况,不能选中节点和线条\n if (this.isDrawing) {\n return;\n }\n\n const nodeHovered = nodeTransforms.find((trans: FlowNodeTransformData) =>\n trans.bounds.contains(mousePos.x, mousePos.y),\n )?.entity as WorkflowNodeEntity;\n\n // 判断当前鼠标位置所在元素是否在节点内部\n const nodeDomNodes = this.playgroundNode.querySelectorAll(NODE_CLASS_NAME);\n const checkTargetFromNode = [...nodeDomNodes].some(nodeDom =>\n nodeDom.contains(target as HTMLElement),\n );\n\n if (nodeHovered || checkTargetFromNode) {\n if (nodeHovered?.id) {\n this.updateHoveredKey(nodeHovered.id);\n }\n }\n\n const nodeInContainer = !!(nodeHovered?.parent && nodeHovered.parent.flowNodeType !== 'root');\n\n // 获取最接近的线条\n // 线条会相交需要获取最接近点位的线条,不能删除的线条不能被选中\n const lineHovered = checkTargetFromLine\n ? this.linesManager.getCloseInLineFromMousePos(mousePos)\n : undefined;\n const lineInContainer = !!lineHovered?.inContainer;\n\n // 判断容器内节点是否 hover\n if (nodeHovered && nodeInContainer) {\n this.updateHoveredKey(nodeHovered.id);\n return;\n }\n // 判断容器内线条是否 hover\n if (lineHovered && lineInContainer) {\n this.updateHoveredKey(lineHovered.id);\n return;\n }\n\n // 判断节点是否 hover\n if (nodeHovered) {\n this.updateHoveredKey(nodeHovered.id);\n return;\n }\n // 判断线条是否 hover\n if (lineHovered) {\n this.hoverService.updateHoveredKey(lineHovered.id);\n return;\n }\n\n // 上述逻辑都未命中 则清空 hoverd\n hoverService.clearHovered();\n\n const currentState = this.editorStateConfig.getCurrentState();\n const isMouseFriendly = currentState === EditorState.STATE_MOUSE_FRIENDLY_SELECT;\n\n // 鼠标优先,并且不是按住 shift 键,更新为小手\n if (isMouseFriendly && !this.editorStateConfig.isPressingShift) {\n this.configEntity.updateCursor('grab');\n }\n }\n\n updateHoveredKey(key: string): void {\n // 鼠标优先交互模式,如果是 hover,需要将鼠标的小手去掉,还原鼠标原有样式\n this.configEntity.updateCursor('default');\n this.hoverService.updateHoveredKey(key);\n }\n\n /**\n * 判断是否能够 hover\n * @returns 是否能 hover\n */\n isEnabled(): boolean {\n const currentState = this.editorStateConfig.getCurrentState();\n // 选择框情况禁止 hover\n return (\n // 鼠标友好模式下,也需要支持 hover 效果,不然线条选择不到\n // Coze 中没有使用该插件,需要在 workflow/render 包相应位置改动\n (currentState === EditorState.STATE_SELECT ||\n currentState === EditorState.STATE_MOUSE_FRIENDLY_SELECT) &&\n !this.selectorBoxConfigEntity.isStart &&\n !this.dragService.isDragging\n );\n }\n}\n","import { FlowNodeTransformData, FlowNodeEntity } from '@flowgram.ai/document';\nimport { type Entity } from '@flowgram.ai/core';\nimport { Rectangle } from '@flowgram.ai/utils';\n\nconst BOUNDS_PADDING = 2;\n\nexport function getSelectionBounds(\n selection: Entity[],\n ignoreOneSelect?: boolean, // 忽略单选\n): Rectangle {\n const selectedNodes = selection.filter(node => node instanceof FlowNodeEntity);\n\n if (!selectedNodes?.length) {\n return Rectangle.EMPTY;\n }\n\n // 选中单个的时候不显示\n if (\n ignoreOneSelect &&\n selectedNodes.length === 1 &&\n // 选中的节点不包含多个子节点\n (selectedNodes[0] as FlowNodeEntity).childrenLength <= 1\n ) {\n return Rectangle.EMPTY;\n }\n\n return Rectangle.enlarge(selectedNodes.map(n => n.getData(FlowNodeTransformData)!.bounds)).pad(\n BOUNDS_PADDING,\n );\n}\n"],"mappings":"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","names":["import_core","import_document","import_free_layout_core","HoverLayerOptions","lineHovered"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/create-free-hover-plugin.ts","../src/hover-layer.tsx","../src/selection-utils.ts"],"sourcesContent":["/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nexport * from './create-free-hover-plugin';\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { definePluginCreator } from '@flowgram.ai/core';\n\nimport { HoverLayer } from './hover-layer';\n\nexport const createFreeHoverPlugin = definePluginCreator({\n onInit(ctx): void {\n ctx.playground.registerLayer(HoverLayer);\n },\n});\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\n/* eslint-disable complexity */\nimport { inject, injectable } from 'inversify';\nimport { type IPoint } from '@flowgram.ai/utils';\nimport { SelectorBoxConfigEntity } from '@flowgram.ai/renderer';\nimport {\n WorkflowDocument,\n WorkflowDragService,\n WorkflowHoverService,\n WorkflowLineEntity,\n WorkflowLinesManager,\n WorkflowNodeEntity,\n WorkflowSelectService,\n} from '@flowgram.ai/free-layout-core';\nimport { WorkflowPortEntity } from '@flowgram.ai/free-layout-core';\nimport { FlowNodeBaseType, FlowNodeTransformData } from '@flowgram.ai/document';\nimport {\n EditorState,\n EditorStateConfigEntity,\n Layer,\n PlaygroundConfigEntity,\n observeEntities,\n observeEntity,\n observeEntityDatas,\n type LayerOptions,\n} from '@flowgram.ai/core';\n\nimport { getSelectionBounds } from './selection-utils';\nconst PORT_BG_CLASS_NAME = 'workflow-port-bg';\n\nexport interface HoverLayerOptions extends LayerOptions {\n canHovered?: (e: MouseEvent, service: WorkflowHoverService) => boolean;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-namespace\nexport namespace HoverLayerOptions {\n export const DEFAULT: HoverLayerOptions = {\n canHovered: () => true,\n };\n}\n\nconst LINE_CLASS_NAME = '.gedit-flow-activity-line';\nconst NODE_CLASS_NAME = '.gedit-flow-activity-node';\n\n@injectable()\nexport class HoverLayer extends Layer<HoverLayerOptions> {\n static type = 'HoverLayer';\n\n @inject(WorkflowDocument) document: WorkflowDocument;\n\n @inject(WorkflowSelectService) selectionService: WorkflowSelectService;\n\n @inject(WorkflowDragService) dragService: WorkflowDragService;\n\n @inject(WorkflowHoverService) hoverService: WorkflowHoverService;\n\n @inject(WorkflowLinesManager)\n linesManager: WorkflowLinesManager;\n\n @observeEntity(EditorStateConfigEntity)\n protected editorStateConfig: EditorStateConfigEntity;\n\n @observeEntity(SelectorBoxConfigEntity)\n protected selectorBoxConfigEntity: SelectorBoxConfigEntity;\n\n @inject(PlaygroundConfigEntity) configEntity: PlaygroundConfigEntity;\n\n /**\n * 监听节点 transform\n */\n @observeEntityDatas(WorkflowNodeEntity, FlowNodeTransformData)\n protected readonly nodeTransforms: FlowNodeTransformData[];\n\n /**\n * 按选中排序\n * @private\n */\n protected nodeTransformsWithSort: FlowNodeTransformData[] = [];\n\n autorun(): void {\n const { activatedNode } = this.selectionService;\n this.nodeTransformsWithSort = this.nodeTransforms\n .filter((n) => n.entity.id !== 'root' && n.entity.flowNodeType !== FlowNodeBaseType.GROUP)\n .reverse() // 后创建的排在前面\n .sort((n1) => (n1.entity === activatedNode ? -1 : 0));\n }\n\n /**\n * 监听线条\n */\n @observeEntities(WorkflowLineEntity)\n protected readonly lines: WorkflowLineEntity[];\n\n /**\n * 是否正在调整线条\n * @protected\n */\n get isDrawing(): boolean {\n return this.linesManager.isDrawing;\n }\n\n onReady(): void {\n this.options = {\n ...HoverLayerOptions.DEFAULT,\n ...this.options,\n };\n this.toDispose.pushAll([\n // 监听主动触发的 hover 事件\n this.hoverService.onUpdateHoverPosition((hoverPosition) => {\n const { position, target } = hoverPosition;\n const canvasPosition = this.config.getPosFromMouseEvent({\n clientX: position.x,\n clientY: position.y,\n });\n this.updateHoveredState(canvasPosition, target);\n }),\n // 监听画布鼠标移动事件\n this.listenPlaygroundEvent('mousemove', (e: MouseEvent) => {\n this.hoverService.hoveredPos = this.config.getPosFromMouseEvent(e);\n if (!this.isEnabled()) {\n return;\n }\n if (!this.options.canHovered!(e, this.hoverService)) {\n return;\n }\n const mousePos = this.config.getPosFromMouseEvent(e);\n // 更新 hover 状态\n this.updateHoveredState(mousePos, e?.target as HTMLElement);\n }),\n this.selectionService.onSelectionChanged(() => this.autorun()),\n // 控制触控\n this.listenPlaygroundEvent('touchstart', (e: MouseEvent): boolean | undefined => {\n if (!this.isEnabled() || this.isDrawing) {\n return undefined;\n }\n return this.handleDragLine(e);\n }),\n // 控制选中逻辑\n this.listenPlaygroundEvent('mousedown', (e: MouseEvent): boolean | undefined => {\n if (!this.isEnabled() || this.isDrawing) {\n return undefined;\n }\n const { hoveredNode } = this.hoverService;\n const lineDrag = this.handleDragLine(e);\n if (lineDrag) {\n return true;\n }\n const mousePos = this.config.getPosFromMouseEvent(e);\n const selectionBounds = getSelectionBounds(\n this.selectionService.selection,\n // 这里只考虑多选模式,单选模式已经下沉到 use-node-render 中\n true\n );\n if (selectionBounds.width > 0 && selectionBounds.contains(mousePos.x, mousePos.y)) {\n /**\n * 拖拽选择框\n */\n this.dragService.startDragSelectedNodes(e)?.then((dragSuccess) => {\n if (!dragSuccess) {\n // 拖拽没有成功触发了点击\n if (hoveredNode && hoveredNode instanceof WorkflowNodeEntity) {\n // 追加选择\n if (e.shiftKey) {\n this.selectionService.toggleSelect(hoveredNode);\n } else {\n this.selectionService.selectNode(hoveredNode);\n }\n } else {\n this.selectionService.clear();\n }\n }\n });\n // 这里会组织触发 selector box\n return true;\n } else {\n if (!hoveredNode) {\n this.selectionService.clear();\n }\n }\n return undefined;\n }),\n ]);\n }\n\n /**\n * 更新 hoverd\n * @param mousePos\n */\n updateHoveredState(mousePos: IPoint, target?: HTMLElement): void {\n const { hoverService } = this;\n const nodeTransforms = this.nodeTransformsWithSort;\n const outputPortHovered = this.linesManager.getPortFromMousePos(mousePos, 'output');\n const inputPortHovered = this.linesManager.getPortFromMousePos(mousePos, 'input');\n // 在两个端口叠加情况,优先使用 outputPort\n const portHovered = outputPortHovered || inputPortHovered;\n\n const lineDomNodes = this.playgroundNode.querySelectorAll(LINE_CLASS_NAME);\n const checkTargetFromLine = [...lineDomNodes].some((lineDom) =>\n lineDom.contains(target as HTMLElement)\n );\n if (portHovered) {\n if (this.document.options.twoWayConnection) {\n hoverService.updateHoveredKey(portHovered.id);\n } else {\n // 默认 只有 output 点位可以 hover\n if (portHovered.portType === 'output') {\n hoverService.updateHoveredKey(portHovered.id);\n } else if (checkTargetFromLine || target?.className?.includes?.(PORT_BG_CLASS_NAME)) {\n // 输入点采用获取最接近的线条\n const lineHovered = this.linesManager.getCloseInLineFromMousePos(mousePos);\n if (lineHovered) {\n this.updateHoveredKey(lineHovered.id);\n }\n }\n }\n return;\n }\n\n // Drawing 情况,不能选中节点和线条\n if (this.isDrawing) {\n return;\n }\n\n const nodeHovered = nodeTransforms.find((trans: FlowNodeTransformData) =>\n trans.bounds.contains(mousePos.x, mousePos.y)\n )?.entity as WorkflowNodeEntity;\n\n // 判断当前鼠标位置所在元素是否在节点内部\n const nodeDomNodes = this.playgroundNode.querySelectorAll(NODE_CLASS_NAME);\n const checkTargetFromNode = [...nodeDomNodes].some((nodeDom) =>\n nodeDom.contains(target as HTMLElement)\n );\n\n if (nodeHovered || checkTargetFromNode) {\n if (nodeHovered?.id) {\n this.updateHoveredKey(nodeHovered.id);\n }\n }\n\n // 获取最接近的线条\n // 线条会相交需要获取最接近点位的线条,不能删除的线条不能被选中\n const lineHovered = checkTargetFromLine\n ? this.linesManager.getCloseInLineFromMousePos(mousePos)\n : undefined;\n\n if (nodeHovered && lineHovered) {\n const nodeStackIndex = nodeHovered.renderData.stackIndex;\n const lineStackIndex = lineHovered.stackIndex;\n if (nodeStackIndex > lineStackIndex) {\n return this.updateHoveredKey(nodeHovered.id);\n } else {\n return this.updateHoveredKey(lineHovered.id);\n }\n }\n\n // 判断节点是否 hover\n if (nodeHovered) {\n return this.updateHoveredKey(nodeHovered.id);\n }\n // 判断线条是否 hover\n if (lineHovered) {\n return this.updateHoveredKey(lineHovered.id);\n }\n\n // 上述逻辑都未命中 则清空 hovered\n hoverService.clearHovered();\n\n const currentState = this.editorStateConfig.getCurrentState();\n const isMouseFriendly = currentState === EditorState.STATE_MOUSE_FRIENDLY_SELECT;\n\n // 鼠标优先,并且不是按住 shift 键,更新为小手\n if (isMouseFriendly && !this.editorStateConfig.isPressingShift) {\n this.configEntity.updateCursor('grab');\n }\n }\n\n updateHoveredKey(key: string): void {\n // 鼠标优先交互模式,如果是 hover,需要将鼠标的小手去掉,还原鼠标原有样式\n this.configEntity.updateCursor('default');\n this.hoverService.updateHoveredKey(key);\n }\n\n /**\n * 判断是否能够 hover\n * @returns 是否能 hover\n */\n isEnabled(): boolean {\n const currentState = this.editorStateConfig.getCurrentState();\n // 选择框情况禁止 hover\n return (\n // 鼠标友好模式下,也需要支持 hover 效果,不然线条选择不到\n // Coze 中没有使用该插件,需要在 workflow/render 包相应位置改动\n (currentState === EditorState.STATE_SELECT ||\n currentState === EditorState.STATE_MOUSE_FRIENDLY_SELECT) &&\n !this.selectorBoxConfigEntity.isStart &&\n !this.dragService.isDragging\n );\n }\n\n private handleDragLine(e: MouseEvent): boolean | undefined {\n const { someHovered } = this.hoverService;\n // 重置线条\n if (someHovered && someHovered instanceof WorkflowLineEntity) {\n this.dragService.resetLine(someHovered, e);\n return true;\n }\n if (\n someHovered &&\n someHovered instanceof WorkflowPortEntity &&\n !someHovered.disabled &&\n e.button !== 1\n ) {\n e.stopPropagation();\n e.preventDefault();\n this.dragService.startDrawingLine(someHovered, e);\n return true;\n }\n }\n}\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { Rectangle } from '@flowgram.ai/utils';\nimport { WorkflowNodeEntity } from '@flowgram.ai/free-layout-core';\nimport { FlowNodeTransformData } from '@flowgram.ai/document';\nimport { type Entity } from '@flowgram.ai/core';\n\nconst BOUNDS_PADDING = 2;\n\nexport function getSelectionBounds(\n selection: Entity[],\n ignoreOneSelect: boolean = true // 忽略单选\n): Rectangle {\n const selectedNodes = selection.filter((node) => node instanceof WorkflowNodeEntity);\n\n // 选中单个的时候不显示\n return selectedNodes.length > (ignoreOneSelect ? 1 : 0)\n ? Rectangle.enlarge(selectedNodes.map((n) => n.getData(FlowNodeTransformData)!.bounds)).pad(\n BOUNDS_PADDING\n )\n : Rectangle.EMPTY;\n}\n"],"mappings":"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","names":["import_core","import_free_layout_core","import_document","HoverLayerOptions","lineHovered"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@flowgram.ai/free-hover-plugin",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.20",
|
|
4
4
|
"homepage": "https://flowgram.ai/",
|
|
5
5
|
"repository": "https://github.com/bytedance/flowgram.ai",
|
|
6
6
|
"license": "MIT",
|
|
@@ -18,31 +18,30 @@
|
|
|
18
18
|
"dependencies": {
|
|
19
19
|
"inversify": "^6.0.1",
|
|
20
20
|
"reflect-metadata": "~0.2.2",
|
|
21
|
-
"@flowgram.ai/core": "0.1.0-alpha.
|
|
22
|
-
"@flowgram.ai/document": "0.1.0-alpha.
|
|
23
|
-
"@flowgram.ai/renderer": "0.1.0-alpha.
|
|
24
|
-
"@flowgram.ai/
|
|
25
|
-
"@flowgram.ai/utils": "0.1.0-alpha.
|
|
26
|
-
"@flowgram.ai/free-layout-core": "0.1.0-alpha.2"
|
|
21
|
+
"@flowgram.ai/core": "0.1.0-alpha.20",
|
|
22
|
+
"@flowgram.ai/document": "0.1.0-alpha.20",
|
|
23
|
+
"@flowgram.ai/renderer": "0.1.0-alpha.20",
|
|
24
|
+
"@flowgram.ai/free-layout-core": "0.1.0-alpha.20",
|
|
25
|
+
"@flowgram.ai/utils": "0.1.0-alpha.20"
|
|
27
26
|
},
|
|
28
27
|
"devDependencies": {
|
|
29
28
|
"@types/bezier-js": "4.1.3",
|
|
30
|
-
"@types/lodash": "^4.
|
|
29
|
+
"@types/lodash-es": "^4.17.12",
|
|
31
30
|
"@types/react": "^18",
|
|
32
31
|
"@types/react-dom": "^18",
|
|
33
|
-
"@vitest/coverage-v8": "^
|
|
32
|
+
"@vitest/coverage-v8": "^3.2.4",
|
|
34
33
|
"eslint": "^8.54.0",
|
|
35
34
|
"react": "^18",
|
|
36
35
|
"react-dom": "^18",
|
|
37
36
|
"tsup": "^8.0.1",
|
|
38
|
-
"typescript": "^5.
|
|
39
|
-
"vitest": "^
|
|
40
|
-
"@flowgram.ai/eslint-config": "0.1.0-alpha.
|
|
41
|
-
"@flowgram.ai/ts-config": "0.1.0-alpha.
|
|
37
|
+
"typescript": "^5.8.3",
|
|
38
|
+
"vitest": "^3.2.4",
|
|
39
|
+
"@flowgram.ai/eslint-config": "0.1.0-alpha.20",
|
|
40
|
+
"@flowgram.ai/ts-config": "0.1.0-alpha.20"
|
|
42
41
|
},
|
|
43
42
|
"peerDependencies": {
|
|
44
|
-
"react": ">=
|
|
45
|
-
"react-dom": ">=
|
|
43
|
+
"react": ">=16.8",
|
|
44
|
+
"react-dom": ">=16.8"
|
|
46
45
|
},
|
|
47
46
|
"publishConfig": {
|
|
48
47
|
"access": "public",
|