@flowgram.ai/free-hover-plugin 0.1.0

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.
@@ -0,0 +1,277 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __decorateClass = (decorators, target, key, kind) => {
4
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
5
+ for (var i = decorators.length - 1, decorator; i >= 0; i--)
6
+ if (decorator = decorators[i])
7
+ result = (kind ? decorator(target, key, result) : decorator(result)) || result;
8
+ if (kind && result) __defProp(target, key, result);
9
+ return result;
10
+ };
11
+
12
+ // src/create-free-hover-plugin.ts
13
+ import { definePluginCreator } from "@flowgram.ai/core";
14
+
15
+ // src/hover-layer.tsx
16
+ import { inject, injectable } from "inversify";
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
+ import {
29
+ WorkflowDocument,
30
+ WorkflowDragService,
31
+ WorkflowHoverService,
32
+ WorkflowLineEntity,
33
+ WorkflowLinesManager,
34
+ WorkflowNodeEntity,
35
+ WorkflowSelectService
36
+ } from "@flowgram.ai/free-layout-core";
37
+ import { WorkflowPortEntity } from "@flowgram.ai/free-layout-core";
38
+
39
+ // src/selection-utils.ts
40
+ import { FlowNodeTransformData, FlowNodeEntity } from "@flowgram.ai/document";
41
+ import { Rectangle } from "@flowgram.ai/utils";
42
+ var BOUNDS_PADDING = 2;
43
+ function getSelectionBounds(selection, ignoreOneSelect) {
44
+ const selectedNodes = selection.filter((node) => node instanceof FlowNodeEntity);
45
+ if (!selectedNodes?.length) {
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(
53
+ BOUNDS_PADDING
54
+ );
55
+ }
56
+
57
+ // src/hover-layer.tsx
58
+ var PORT_BG_CLASS_NAME = "workflow-port-bg";
59
+ var HoverLayerOptions;
60
+ ((HoverLayerOptions2) => {
61
+ HoverLayerOptions2.DEFAULT = {
62
+ canHovered: () => true
63
+ };
64
+ })(HoverLayerOptions || (HoverLayerOptions = {}));
65
+ var LINE_CLASS_NAME = ".gedit-flow-activity-line";
66
+ var NODE_CLASS_NAME = ".gedit-flow-activity-node";
67
+ var HoverLayer = class extends Layer {
68
+ constructor() {
69
+ super(...arguments);
70
+ /**
71
+ * 按选中排序
72
+ * @private
73
+ */
74
+ this.nodeTransformsWithSort = [];
75
+ }
76
+ autorun() {
77
+ const { activatedNode } = this.selectionService;
78
+ this.nodeTransformsWithSort = this.nodeTransforms.filter((n) => n.entity.id !== "root").reverse().sort((n1) => n1.entity === activatedNode ? -1 : 0);
79
+ }
80
+ /**
81
+ * 是否正在调整线条
82
+ * @protected
83
+ */
84
+ get isDrawing() {
85
+ return this.linesManager.isDrawing;
86
+ }
87
+ onReady() {
88
+ this.options = {
89
+ ...HoverLayerOptions.DEFAULT,
90
+ ...this.options
91
+ };
92
+ this.toDispose.pushAll([
93
+ // 监听画布鼠标移动事件
94
+ this.listenPlaygroundEvent("mousemove", (e) => {
95
+ this.hoverService.hoveredPos = this.config.getPosFromMouseEvent(e);
96
+ if (!this.isEnabled()) {
97
+ return;
98
+ }
99
+ if (!this.options.canHovered(e, this.hoverService)) {
100
+ return;
101
+ }
102
+ const mousePos = this.config.getPosFromMouseEvent(e);
103
+ this.updateHoveredState(mousePos, e?.target);
104
+ }),
105
+ this.selectionService.onSelectionChanged(() => this.autorun()),
106
+ // 控制选中逻辑
107
+ this.listenPlaygroundEvent("mousedown", (e) => {
108
+ if (!this.isEnabled() || this.isDrawing) {
109
+ return void 0;
110
+ }
111
+ const { hoveredNode } = this.hoverService;
112
+ if (hoveredNode && hoveredNode instanceof WorkflowLineEntity) {
113
+ this.dragService.resetLine(hoveredNode, e);
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);
120
+ return true;
121
+ }
122
+ const mousePos = this.config.getPosFromMouseEvent(e);
123
+ const selectionBounds = getSelectionBounds(
124
+ this.selectionService.selection,
125
+ // 这里只考虑多选模式,单选模式已经下沉到 use-node-render 中
126
+ true
127
+ );
128
+ if (selectionBounds.width > 0 && selectionBounds.contains(mousePos.x, mousePos.y)) {
129
+ this.dragService.startDragSelectedNodes(e).then((dragSuccess) => {
130
+ if (!dragSuccess) {
131
+ if (hoveredNode && hoveredNode instanceof WorkflowNodeEntity) {
132
+ if (e.metaKey || e.shiftKey || e.ctrlKey) {
133
+ this.selectionService.toggleSelect(hoveredNode);
134
+ } else {
135
+ this.selectionService.selectNode(hoveredNode);
136
+ }
137
+ } else {
138
+ this.selectionService.clear();
139
+ }
140
+ }
141
+ });
142
+ return true;
143
+ } else {
144
+ if (!hoveredNode) {
145
+ this.selectionService.clear();
146
+ }
147
+ }
148
+ return void 0;
149
+ })
150
+ ]);
151
+ }
152
+ /**
153
+ * 更新 hoverd
154
+ * @param mousePos
155
+ */
156
+ updateHoveredState(mousePos, target) {
157
+ const { hoverService } = this;
158
+ const nodeTransforms = this.nodeTransformsWithSort;
159
+ const portHovered = this.linesManager.getPortFromMousePos(mousePos);
160
+ const lineDomNodes = this.playgroundNode.querySelectorAll(LINE_CLASS_NAME);
161
+ const checkTargetFromLine = [...lineDomNodes].some(
162
+ (lineDom) => lineDom.contains(target)
163
+ );
164
+ if (portHovered) {
165
+ if (portHovered.portType === "output") {
166
+ hoverService.updateHoveredKey(portHovered.id);
167
+ } else if (checkTargetFromLine || target?.className?.includes?.(PORT_BG_CLASS_NAME)) {
168
+ const lineHovered2 = this.linesManager.getCloseInLineFromMousePos(mousePos);
169
+ if (lineHovered2) {
170
+ this.updateHoveredKey(lineHovered2.id);
171
+ }
172
+ }
173
+ return;
174
+ }
175
+ if (this.isDrawing) {
176
+ return;
177
+ }
178
+ const nodeHovered = nodeTransforms.find(
179
+ (trans) => trans.bounds.contains(mousePos.x, mousePos.y)
180
+ )?.entity;
181
+ const nodeDomNodes = this.playgroundNode.querySelectorAll(NODE_CLASS_NAME);
182
+ const checkTargetFromNode = [...nodeDomNodes].some(
183
+ (nodeDom) => nodeDom.contains(target)
184
+ );
185
+ if (nodeHovered || checkTargetFromNode) {
186
+ if (nodeHovered?.id) {
187
+ this.updateHoveredKey(nodeHovered.id);
188
+ }
189
+ }
190
+ const nodeInContainer = !!(nodeHovered?.parent && nodeHovered.parent.flowNodeType !== "root");
191
+ const lineHovered = checkTargetFromLine ? this.linesManager.getCloseInLineFromMousePos(mousePos) : void 0;
192
+ const lineInContainer = !!lineHovered?.inContainer;
193
+ if (nodeHovered && nodeInContainer) {
194
+ this.updateHoveredKey(nodeHovered.id);
195
+ return;
196
+ }
197
+ if (lineHovered && lineInContainer) {
198
+ this.updateHoveredKey(lineHovered.id);
199
+ return;
200
+ }
201
+ if (nodeHovered) {
202
+ this.updateHoveredKey(nodeHovered.id);
203
+ return;
204
+ }
205
+ if (lineHovered) {
206
+ this.hoverService.updateHoveredKey(lineHovered.id);
207
+ return;
208
+ }
209
+ hoverService.clearHovered();
210
+ const currentState = this.editorStateConfig.getCurrentState();
211
+ const isMouseFriendly = currentState === EditorState.STATE_MOUSE_FRIENDLY_SELECT;
212
+ if (isMouseFriendly && !this.editorStateConfig.isPressingShift) {
213
+ this.configEntity.updateCursor("grab");
214
+ }
215
+ }
216
+ updateHoveredKey(key) {
217
+ this.configEntity.updateCursor("default");
218
+ this.hoverService.updateHoveredKey(key);
219
+ }
220
+ /**
221
+ * 判断是否能够 hover
222
+ * @returns 是否能 hover
223
+ */
224
+ isEnabled() {
225
+ const currentState = this.editorStateConfig.getCurrentState();
226
+ return (
227
+ // 鼠标友好模式下,也需要支持 hover 效果,不然线条选择不到
228
+ // Coze 中没有使用该插件,需要在 workflow/render 包相应位置改动
229
+ (currentState === EditorState.STATE_SELECT || currentState === EditorState.STATE_MOUSE_FRIENDLY_SELECT) && !this.selectorBoxConfigEntity.isStart && !this.dragService.isDragging
230
+ );
231
+ }
232
+ };
233
+ HoverLayer.type = "HoverLayer";
234
+ __decorateClass([
235
+ inject(WorkflowDocument)
236
+ ], HoverLayer.prototype, "document", 2);
237
+ __decorateClass([
238
+ inject(WorkflowSelectService)
239
+ ], HoverLayer.prototype, "selectionService", 2);
240
+ __decorateClass([
241
+ inject(WorkflowDragService)
242
+ ], HoverLayer.prototype, "dragService", 2);
243
+ __decorateClass([
244
+ inject(WorkflowHoverService)
245
+ ], HoverLayer.prototype, "hoverService", 2);
246
+ __decorateClass([
247
+ inject(WorkflowLinesManager)
248
+ ], HoverLayer.prototype, "linesManager", 2);
249
+ __decorateClass([
250
+ observeEntity(EditorStateConfigEntity)
251
+ ], HoverLayer.prototype, "editorStateConfig", 2);
252
+ __decorateClass([
253
+ observeEntity(SelectorBoxConfigEntity)
254
+ ], HoverLayer.prototype, "selectorBoxConfigEntity", 2);
255
+ __decorateClass([
256
+ inject(PlaygroundConfigEntity)
257
+ ], HoverLayer.prototype, "configEntity", 2);
258
+ __decorateClass([
259
+ observeEntityDatas(WorkflowNodeEntity, FlowNodeTransformData2)
260
+ ], HoverLayer.prototype, "nodeTransforms", 2);
261
+ __decorateClass([
262
+ observeEntities(WorkflowLineEntity)
263
+ ], HoverLayer.prototype, "lines", 2);
264
+ HoverLayer = __decorateClass([
265
+ injectable()
266
+ ], HoverLayer);
267
+
268
+ // src/create-free-hover-plugin.ts
269
+ var createFreeHoverPlugin = definePluginCreator({
270
+ onInit(ctx) {
271
+ ctx.playground.registerLayer(HoverLayer);
272
+ }
273
+ });
274
+ export {
275
+ createFreeHoverPlugin
276
+ };
277
+ //# sourceMappingURL=index.js.map
@@ -0,0 +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"]}
@@ -0,0 +1,5 @@
1
+ import * as _flowgram_ai_core from '@flowgram.ai/core';
2
+
3
+ declare const createFreeHoverPlugin: _flowgram_ai_core.PluginCreator<unknown>;
4
+
5
+ export { createFreeHoverPlugin };
@@ -0,0 +1,5 @@
1
+ import * as _flowgram_ai_core from '@flowgram.ai/core';
2
+
3
+ declare const createFreeHoverPlugin: _flowgram_ai_core.PluginCreator<unknown>;
4
+
5
+ export { createFreeHoverPlugin };
package/dist/index.js ADDED
@@ -0,0 +1,285 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var __decorateClass = (decorators, target, key, kind) => {
20
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
21
+ for (var i = decorators.length - 1, decorator; i >= 0; i--)
22
+ if (decorator = decorators[i])
23
+ result = (kind ? decorator(target, key, result) : decorator(result)) || result;
24
+ if (kind && result) __defProp(target, key, result);
25
+ return result;
26
+ };
27
+
28
+ // src/index.ts
29
+ var src_exports = {};
30
+ __export(src_exports, {
31
+ createFreeHoverPlugin: () => createFreeHoverPlugin
32
+ });
33
+ module.exports = __toCommonJS(src_exports);
34
+
35
+ // src/create-free-hover-plugin.ts
36
+ var import_core2 = require("@flowgram.ai/core");
37
+
38
+ // src/hover-layer.tsx
39
+ var import_inversify = require("inversify");
40
+ var import_renderer = require("@flowgram.ai/renderer");
41
+ var import_document2 = require("@flowgram.ai/document");
42
+ 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
+
46
+ // src/selection-utils.ts
47
+ var import_document = require("@flowgram.ai/document");
48
+ var import_utils = require("@flowgram.ai/utils");
49
+ var BOUNDS_PADDING = 2;
50
+ function getSelectionBounds(selection, ignoreOneSelect) {
51
+ const selectedNodes = selection.filter((node) => node instanceof import_document.FlowNodeEntity);
52
+ if (!selectedNodes?.length) {
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(
60
+ BOUNDS_PADDING
61
+ );
62
+ }
63
+
64
+ // src/hover-layer.tsx
65
+ var PORT_BG_CLASS_NAME = "workflow-port-bg";
66
+ var HoverLayerOptions;
67
+ ((HoverLayerOptions2) => {
68
+ HoverLayerOptions2.DEFAULT = {
69
+ canHovered: () => true
70
+ };
71
+ })(HoverLayerOptions || (HoverLayerOptions = {}));
72
+ var LINE_CLASS_NAME = ".gedit-flow-activity-line";
73
+ var NODE_CLASS_NAME = ".gedit-flow-activity-node";
74
+ var HoverLayer = class extends import_core.Layer {
75
+ constructor() {
76
+ super(...arguments);
77
+ /**
78
+ * 按选中排序
79
+ * @private
80
+ */
81
+ this.nodeTransformsWithSort = [];
82
+ }
83
+ autorun() {
84
+ const { activatedNode } = this.selectionService;
85
+ this.nodeTransformsWithSort = this.nodeTransforms.filter((n) => n.entity.id !== "root").reverse().sort((n1) => n1.entity === activatedNode ? -1 : 0);
86
+ }
87
+ /**
88
+ * 是否正在调整线条
89
+ * @protected
90
+ */
91
+ get isDrawing() {
92
+ return this.linesManager.isDrawing;
93
+ }
94
+ onReady() {
95
+ this.options = {
96
+ ...HoverLayerOptions.DEFAULT,
97
+ ...this.options
98
+ };
99
+ this.toDispose.pushAll([
100
+ // 监听画布鼠标移动事件
101
+ this.listenPlaygroundEvent("mousemove", (e) => {
102
+ this.hoverService.hoveredPos = this.config.getPosFromMouseEvent(e);
103
+ if (!this.isEnabled()) {
104
+ return;
105
+ }
106
+ if (!this.options.canHovered(e, this.hoverService)) {
107
+ return;
108
+ }
109
+ const mousePos = this.config.getPosFromMouseEvent(e);
110
+ this.updateHoveredState(mousePos, e?.target);
111
+ }),
112
+ this.selectionService.onSelectionChanged(() => this.autorun()),
113
+ // 控制选中逻辑
114
+ this.listenPlaygroundEvent("mousedown", (e) => {
115
+ if (!this.isEnabled() || this.isDrawing) {
116
+ return void 0;
117
+ }
118
+ const { hoveredNode } = this.hoverService;
119
+ if (hoveredNode && hoveredNode instanceof import_free_layout_core.WorkflowLineEntity) {
120
+ this.dragService.resetLine(hoveredNode, e);
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);
127
+ return true;
128
+ }
129
+ const mousePos = this.config.getPosFromMouseEvent(e);
130
+ const selectionBounds = getSelectionBounds(
131
+ this.selectionService.selection,
132
+ // 这里只考虑多选模式,单选模式已经下沉到 use-node-render 中
133
+ true
134
+ );
135
+ if (selectionBounds.width > 0 && selectionBounds.contains(mousePos.x, mousePos.y)) {
136
+ this.dragService.startDragSelectedNodes(e).then((dragSuccess) => {
137
+ if (!dragSuccess) {
138
+ if (hoveredNode && hoveredNode instanceof import_free_layout_core.WorkflowNodeEntity) {
139
+ if (e.metaKey || e.shiftKey || e.ctrlKey) {
140
+ this.selectionService.toggleSelect(hoveredNode);
141
+ } else {
142
+ this.selectionService.selectNode(hoveredNode);
143
+ }
144
+ } else {
145
+ this.selectionService.clear();
146
+ }
147
+ }
148
+ });
149
+ return true;
150
+ } else {
151
+ if (!hoveredNode) {
152
+ this.selectionService.clear();
153
+ }
154
+ }
155
+ return void 0;
156
+ })
157
+ ]);
158
+ }
159
+ /**
160
+ * 更新 hoverd
161
+ * @param mousePos
162
+ */
163
+ updateHoveredState(mousePos, target) {
164
+ const { hoverService } = this;
165
+ const nodeTransforms = this.nodeTransformsWithSort;
166
+ const portHovered = this.linesManager.getPortFromMousePos(mousePos);
167
+ const lineDomNodes = this.playgroundNode.querySelectorAll(LINE_CLASS_NAME);
168
+ const checkTargetFromLine = [...lineDomNodes].some(
169
+ (lineDom) => lineDom.contains(target)
170
+ );
171
+ if (portHovered) {
172
+ if (portHovered.portType === "output") {
173
+ hoverService.updateHoveredKey(portHovered.id);
174
+ } else if (checkTargetFromLine || target?.className?.includes?.(PORT_BG_CLASS_NAME)) {
175
+ const lineHovered2 = this.linesManager.getCloseInLineFromMousePos(mousePos);
176
+ if (lineHovered2) {
177
+ this.updateHoveredKey(lineHovered2.id);
178
+ }
179
+ }
180
+ return;
181
+ }
182
+ if (this.isDrawing) {
183
+ return;
184
+ }
185
+ const nodeHovered = nodeTransforms.find(
186
+ (trans) => trans.bounds.contains(mousePos.x, mousePos.y)
187
+ )?.entity;
188
+ const nodeDomNodes = this.playgroundNode.querySelectorAll(NODE_CLASS_NAME);
189
+ const checkTargetFromNode = [...nodeDomNodes].some(
190
+ (nodeDom) => nodeDom.contains(target)
191
+ );
192
+ if (nodeHovered || checkTargetFromNode) {
193
+ if (nodeHovered?.id) {
194
+ this.updateHoveredKey(nodeHovered.id);
195
+ }
196
+ }
197
+ const nodeInContainer = !!(nodeHovered?.parent && nodeHovered.parent.flowNodeType !== "root");
198
+ const lineHovered = checkTargetFromLine ? this.linesManager.getCloseInLineFromMousePos(mousePos) : void 0;
199
+ const lineInContainer = !!lineHovered?.inContainer;
200
+ if (nodeHovered && nodeInContainer) {
201
+ this.updateHoveredKey(nodeHovered.id);
202
+ return;
203
+ }
204
+ if (lineHovered && lineInContainer) {
205
+ this.updateHoveredKey(lineHovered.id);
206
+ return;
207
+ }
208
+ if (nodeHovered) {
209
+ this.updateHoveredKey(nodeHovered.id);
210
+ return;
211
+ }
212
+ if (lineHovered) {
213
+ this.hoverService.updateHoveredKey(lineHovered.id);
214
+ return;
215
+ }
216
+ hoverService.clearHovered();
217
+ const currentState = this.editorStateConfig.getCurrentState();
218
+ const isMouseFriendly = currentState === import_core.EditorState.STATE_MOUSE_FRIENDLY_SELECT;
219
+ if (isMouseFriendly && !this.editorStateConfig.isPressingShift) {
220
+ this.configEntity.updateCursor("grab");
221
+ }
222
+ }
223
+ updateHoveredKey(key) {
224
+ this.configEntity.updateCursor("default");
225
+ this.hoverService.updateHoveredKey(key);
226
+ }
227
+ /**
228
+ * 判断是否能够 hover
229
+ * @returns 是否能 hover
230
+ */
231
+ isEnabled() {
232
+ const currentState = this.editorStateConfig.getCurrentState();
233
+ return (
234
+ // 鼠标友好模式下,也需要支持 hover 效果,不然线条选择不到
235
+ // Coze 中没有使用该插件,需要在 workflow/render 包相应位置改动
236
+ (currentState === import_core.EditorState.STATE_SELECT || currentState === import_core.EditorState.STATE_MOUSE_FRIENDLY_SELECT) && !this.selectorBoxConfigEntity.isStart && !this.dragService.isDragging
237
+ );
238
+ }
239
+ };
240
+ HoverLayer.type = "HoverLayer";
241
+ __decorateClass([
242
+ (0, import_inversify.inject)(import_free_layout_core.WorkflowDocument)
243
+ ], HoverLayer.prototype, "document", 2);
244
+ __decorateClass([
245
+ (0, import_inversify.inject)(import_free_layout_core.WorkflowSelectService)
246
+ ], HoverLayer.prototype, "selectionService", 2);
247
+ __decorateClass([
248
+ (0, import_inversify.inject)(import_free_layout_core.WorkflowDragService)
249
+ ], HoverLayer.prototype, "dragService", 2);
250
+ __decorateClass([
251
+ (0, import_inversify.inject)(import_free_layout_core.WorkflowHoverService)
252
+ ], HoverLayer.prototype, "hoverService", 2);
253
+ __decorateClass([
254
+ (0, import_inversify.inject)(import_free_layout_core.WorkflowLinesManager)
255
+ ], HoverLayer.prototype, "linesManager", 2);
256
+ __decorateClass([
257
+ (0, import_core.observeEntity)(import_core.EditorStateConfigEntity)
258
+ ], HoverLayer.prototype, "editorStateConfig", 2);
259
+ __decorateClass([
260
+ (0, import_core.observeEntity)(import_renderer.SelectorBoxConfigEntity)
261
+ ], HoverLayer.prototype, "selectorBoxConfigEntity", 2);
262
+ __decorateClass([
263
+ (0, import_inversify.inject)(import_core.PlaygroundConfigEntity)
264
+ ], HoverLayer.prototype, "configEntity", 2);
265
+ __decorateClass([
266
+ (0, import_core.observeEntityDatas)(import_free_layout_core.WorkflowNodeEntity, import_document2.FlowNodeTransformData)
267
+ ], HoverLayer.prototype, "nodeTransforms", 2);
268
+ __decorateClass([
269
+ (0, import_core.observeEntities)(import_free_layout_core.WorkflowLineEntity)
270
+ ], HoverLayer.prototype, "lines", 2);
271
+ HoverLayer = __decorateClass([
272
+ (0, import_inversify.injectable)()
273
+ ], HoverLayer);
274
+
275
+ // src/create-free-hover-plugin.ts
276
+ var createFreeHoverPlugin = (0, import_core2.definePluginCreator)({
277
+ onInit(ctx) {
278
+ ctx.playground.registerLayer(HoverLayer);
279
+ }
280
+ });
281
+ // Annotate the CommonJS export names for ESM import in node:
282
+ 0 && (module.exports = {
283
+ createFreeHoverPlugin
284
+ });
285
+ //# sourceMappingURL=index.js.map
@@ -0,0 +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"]}
package/package.json ADDED
@@ -0,0 +1,54 @@
1
+ {
2
+ "name": "@flowgram.ai/free-hover-plugin",
3
+ "version": "0.1.0",
4
+ "license": "MIT",
5
+ "exports": {
6
+ "types": "./dist/index.d.ts",
7
+ "import": "./dist/esm/index.js",
8
+ "require": "./dist/index.js"
9
+ },
10
+ "main": "./dist/index.js",
11
+ "module": "./dist/esm/index.js",
12
+ "types": "./dist/index.d.ts",
13
+ "files": [
14
+ "dist"
15
+ ],
16
+ "dependencies": {
17
+ "inversify": "^6.0.1",
18
+ "@flowgram.ai/core": "0.1.0",
19
+ "@flowgram.ai/free-layout-core": "0.1.0",
20
+ "@flowgram.ai/document": "0.1.0",
21
+ "@flowgram.ai/select-box-plugin": "0.1.0",
22
+ "@flowgram.ai/renderer": "0.1.0",
23
+ "@flowgram.ai/utils": "0.1.0"
24
+ },
25
+ "devDependencies": {
26
+ "@types/bezier-js": "4.1.3",
27
+ "@types/lodash": "^4.14.137",
28
+ "@types/react": "^18",
29
+ "@types/react-dom": "^18",
30
+ "@vitest/coverage-v8": "^0.32.0",
31
+ "eslint": "^8.54.0",
32
+ "react": "^18",
33
+ "react-dom": "^18",
34
+ "tsup": "^8.0.1",
35
+ "typescript": "^5.0.4",
36
+ "vitest": "^0.34.6",
37
+ "@flowgram.ai/eslint-config": "0.1.0",
38
+ "@flowgram.ai/ts-config": "0.1.0"
39
+ },
40
+ "peerDependencies": {
41
+ "react": ">=17",
42
+ "react-dom": ">=17"
43
+ },
44
+ "scripts": {
45
+ "build": "npm run build:fast -- --dts-resolve",
46
+ "build:fast": "tsup src/index.ts --format cjs,esm --sourcemap --legacy-output",
47
+ "build:watch": "npm run build:fast -- --dts-resolve",
48
+ "clean": "rimraf dist",
49
+ "test": "exit 0",
50
+ "test:cov": "exit 0",
51
+ "ts-check": "tsc --noEmit",
52
+ "watch": "npm run build:fast -- --dts-resolve --watch --ignore-watch dist"
53
+ }
54
+ }