@flowgram.ai/free-container-plugin 0.1.0-alpha.5
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 +717 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/index.d.mts +122 -0
- package/dist/index.d.ts +122 -0
- package/dist/index.js +751 -0
- package/dist/index.js.map +1 -0
- package/package.json +65 -0
|
@@ -0,0 +1,717 @@
|
|
|
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/container-node-render/constant.ts
|
|
13
|
+
var ContainerNodeRenderKey = "container-node-render-key";
|
|
14
|
+
|
|
15
|
+
// src/container-node-render/render.tsx
|
|
16
|
+
import React7 from "react";
|
|
17
|
+
|
|
18
|
+
// src/container-node-render/components/header/index.tsx
|
|
19
|
+
import React from "react";
|
|
20
|
+
import { useNodeRender } from "@flowgram.ai/free-layout-core";
|
|
21
|
+
|
|
22
|
+
// src/container-node-render/components/header/style.ts
|
|
23
|
+
import styled from "styled-components";
|
|
24
|
+
var ContainerNodeHeaderStyle = styled.div`
|
|
25
|
+
z-index: 0;
|
|
26
|
+
|
|
27
|
+
display: flex;
|
|
28
|
+
gap: 8px;
|
|
29
|
+
align-items: center;
|
|
30
|
+
justify-content: flex-start;
|
|
31
|
+
|
|
32
|
+
width: 100%;
|
|
33
|
+
height: auto;
|
|
34
|
+
|
|
35
|
+
border-radius: 8px 8px 0 0;
|
|
36
|
+
|
|
37
|
+
.container-node-logo {
|
|
38
|
+
position: relative;
|
|
39
|
+
|
|
40
|
+
flex-shrink: 0;
|
|
41
|
+
|
|
42
|
+
width: 24px;
|
|
43
|
+
height: 24px;
|
|
44
|
+
|
|
45
|
+
border-radius: 4px;
|
|
46
|
+
|
|
47
|
+
&::after {
|
|
48
|
+
content: '';
|
|
49
|
+
|
|
50
|
+
position: absolute;
|
|
51
|
+
top: 0;
|
|
52
|
+
left: 0;
|
|
53
|
+
|
|
54
|
+
display: block;
|
|
55
|
+
|
|
56
|
+
width: 100%;
|
|
57
|
+
height: 100%;
|
|
58
|
+
|
|
59
|
+
border-radius: 4px;
|
|
60
|
+
box-shadow: inset 0 0 0 1px var(--coz-stroke-plus);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
> img {
|
|
64
|
+
width: 24px;
|
|
65
|
+
height: 24px;
|
|
66
|
+
border-radius: 4px;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.container-node-title {
|
|
71
|
+
margin: 0;
|
|
72
|
+
padding: 0;
|
|
73
|
+
|
|
74
|
+
font-size: 16px;
|
|
75
|
+
font-weight: 500;
|
|
76
|
+
font-style: normal;
|
|
77
|
+
line-height: 22px;
|
|
78
|
+
color: var(--coz-fg-primary, rgba(6, 7, 9, 80%));
|
|
79
|
+
text-overflow: ellipsis;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.container-node-tooltip {
|
|
83
|
+
height: 100%;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
.container-node-tooltip-icon {
|
|
87
|
+
display: flex;
|
|
88
|
+
align-items: center;
|
|
89
|
+
|
|
90
|
+
width: 16px;
|
|
91
|
+
height: 100%;
|
|
92
|
+
|
|
93
|
+
color: #a7a9b0;
|
|
94
|
+
}
|
|
95
|
+
`;
|
|
96
|
+
|
|
97
|
+
// src/container-node-render/components/header/index.tsx
|
|
98
|
+
var ContainerNodeHeader = ({ children }) => {
|
|
99
|
+
const { startDrag, onFocus, onBlur } = useNodeRender();
|
|
100
|
+
return /* @__PURE__ */ React.createElement(
|
|
101
|
+
ContainerNodeHeaderStyle,
|
|
102
|
+
{
|
|
103
|
+
className: "container-node-header",
|
|
104
|
+
draggable: true,
|
|
105
|
+
onMouseDown: (e) => {
|
|
106
|
+
startDrag(e);
|
|
107
|
+
},
|
|
108
|
+
onFocus,
|
|
109
|
+
onBlur
|
|
110
|
+
},
|
|
111
|
+
children
|
|
112
|
+
);
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
// src/container-node-render/components/background/index.tsx
|
|
116
|
+
import React2 from "react";
|
|
117
|
+
import { useNodeRender as useNodeRender2 } from "@flowgram.ai/free-layout-core";
|
|
118
|
+
|
|
119
|
+
// src/container-node-render/components/background/style.ts
|
|
120
|
+
import styled2 from "styled-components";
|
|
121
|
+
var ContainerNodeBackgroundStyle = styled2.div`
|
|
122
|
+
position: absolute;
|
|
123
|
+
inset: 56px 18px 18px;
|
|
124
|
+
`;
|
|
125
|
+
|
|
126
|
+
// src/container-node-render/components/background/index.tsx
|
|
127
|
+
var ContainerNodeBackground = () => {
|
|
128
|
+
const { node } = useNodeRender2();
|
|
129
|
+
return /* @__PURE__ */ React2.createElement(
|
|
130
|
+
ContainerNodeBackgroundStyle,
|
|
131
|
+
{
|
|
132
|
+
className: "container-node-background",
|
|
133
|
+
"data-flow-editor-selectable": "true"
|
|
134
|
+
},
|
|
135
|
+
/* @__PURE__ */ React2.createElement("svg", { width: "100%", height: "100%" }, /* @__PURE__ */ React2.createElement(
|
|
136
|
+
"pattern",
|
|
137
|
+
{
|
|
138
|
+
id: "container-node-dot-pattern",
|
|
139
|
+
width: "20",
|
|
140
|
+
height: "20",
|
|
141
|
+
patternUnits: "userSpaceOnUse"
|
|
142
|
+
},
|
|
143
|
+
/* @__PURE__ */ React2.createElement("circle", { cx: "1", cy: "1", r: "1", stroke: "#eceeef", fillOpacity: "0.5" })
|
|
144
|
+
), /* @__PURE__ */ React2.createElement(
|
|
145
|
+
"rect",
|
|
146
|
+
{
|
|
147
|
+
width: "100%",
|
|
148
|
+
height: "100%",
|
|
149
|
+
fill: "url(#container-node-dot-pattern)",
|
|
150
|
+
"data-node-panel-container": node.id
|
|
151
|
+
}
|
|
152
|
+
))
|
|
153
|
+
);
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
// src/container-node-render/components/container/index.tsx
|
|
157
|
+
import React3, { useEffect, useState } from "react";
|
|
158
|
+
import { useNodeRender as useNodeRender4, WorkflowNodePortsData } from "@flowgram.ai/free-layout-core";
|
|
159
|
+
import { FlowNodeTransformData } from "@flowgram.ai/document";
|
|
160
|
+
|
|
161
|
+
// src/container-node-render/hooks/use-render-props.ts
|
|
162
|
+
import { useNodeRender as useNodeRender3 } from "@flowgram.ai/free-layout-core";
|
|
163
|
+
var useContainerNodeRenderProps = () => {
|
|
164
|
+
const { node } = useNodeRender3();
|
|
165
|
+
const nodeMeta = node.getNodeMeta();
|
|
166
|
+
const {
|
|
167
|
+
title = "",
|
|
168
|
+
tooltip,
|
|
169
|
+
renderPorts = [],
|
|
170
|
+
style = {}
|
|
171
|
+
} = nodeMeta?.renderContainerNode?.() ?? {};
|
|
172
|
+
return {
|
|
173
|
+
title,
|
|
174
|
+
tooltip,
|
|
175
|
+
renderPorts,
|
|
176
|
+
style
|
|
177
|
+
};
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
// src/container-node-render/components/container/style.ts
|
|
181
|
+
import styled3 from "styled-components";
|
|
182
|
+
var ContainerNodeContainerStyle = styled3.div`
|
|
183
|
+
display: flex;
|
|
184
|
+
align-items: flex-start;
|
|
185
|
+
|
|
186
|
+
box-sizing: border-box;
|
|
187
|
+
min-width: 400px;
|
|
188
|
+
min-height: 300px;
|
|
189
|
+
|
|
190
|
+
background-color: #f2f3f5;
|
|
191
|
+
border-radius: 8px;
|
|
192
|
+
outline: 1px solid var(--coz-stroke-plus, rgba(6, 7, 9, 15%));
|
|
193
|
+
|
|
194
|
+
.container-node-container-selected {
|
|
195
|
+
outline: 1px solid var(--coz-stroke-hglt, #4e40e5);
|
|
196
|
+
}
|
|
197
|
+
`;
|
|
198
|
+
|
|
199
|
+
// src/container-node-render/components/container/index.tsx
|
|
200
|
+
var ContainerNodeContainer = ({ children }) => {
|
|
201
|
+
const { node, selected, selectNode, nodeRef } = useNodeRender4();
|
|
202
|
+
const nodeMeta = node.getNodeMeta();
|
|
203
|
+
const { size = { width: 300, height: 200 } } = nodeMeta;
|
|
204
|
+
const { style = {} } = useContainerNodeRenderProps();
|
|
205
|
+
const transform = node.getData(FlowNodeTransformData);
|
|
206
|
+
const [width, setWidth] = useState(size.width);
|
|
207
|
+
const [height, setHeight] = useState(size.height);
|
|
208
|
+
const updatePorts = () => {
|
|
209
|
+
const portsData = node.getData(WorkflowNodePortsData);
|
|
210
|
+
portsData.updateDynamicPorts();
|
|
211
|
+
};
|
|
212
|
+
const updateSize = () => {
|
|
213
|
+
if (node.blocks.length === 0) {
|
|
214
|
+
setWidth(size.width);
|
|
215
|
+
setHeight(size.height);
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
setWidth(transform.bounds.width);
|
|
219
|
+
setHeight(transform.bounds.height);
|
|
220
|
+
};
|
|
221
|
+
useEffect(() => {
|
|
222
|
+
const dispose = transform.onDataChange(() => {
|
|
223
|
+
updateSize();
|
|
224
|
+
updatePorts();
|
|
225
|
+
});
|
|
226
|
+
return () => dispose.dispose();
|
|
227
|
+
}, [transform, width, height]);
|
|
228
|
+
useEffect(() => {
|
|
229
|
+
updateSize();
|
|
230
|
+
}, []);
|
|
231
|
+
return /* @__PURE__ */ React3.createElement(
|
|
232
|
+
ContainerNodeContainerStyle,
|
|
233
|
+
{
|
|
234
|
+
className: "container-node-container",
|
|
235
|
+
style: {
|
|
236
|
+
width,
|
|
237
|
+
height,
|
|
238
|
+
outline: selected ? "1px solid var(--coz-stroke-hglt, #4E40E5)" : "",
|
|
239
|
+
...style
|
|
240
|
+
},
|
|
241
|
+
ref: nodeRef,
|
|
242
|
+
"data-node-selected": String(selected),
|
|
243
|
+
onMouseDown: selectNode,
|
|
244
|
+
onClick: (e) => {
|
|
245
|
+
selectNode(e);
|
|
246
|
+
}
|
|
247
|
+
},
|
|
248
|
+
children
|
|
249
|
+
);
|
|
250
|
+
};
|
|
251
|
+
|
|
252
|
+
// src/container-node-render/components/border/index.tsx
|
|
253
|
+
import React4 from "react";
|
|
254
|
+
import { useNodeRender as useNodeRender5 } from "@flowgram.ai/free-layout-core";
|
|
255
|
+
import { FlowNodeTransformData as FlowNodeTransformData2 } from "@flowgram.ai/document";
|
|
256
|
+
|
|
257
|
+
// src/container-node-render/components/border/style.ts
|
|
258
|
+
import styled4 from "styled-components";
|
|
259
|
+
var ContainerNodeBorderStyle = styled4.div`
|
|
260
|
+
pointer-events: none;
|
|
261
|
+
|
|
262
|
+
position: absolute;
|
|
263
|
+
|
|
264
|
+
display: flex;
|
|
265
|
+
align-items: center;
|
|
266
|
+
|
|
267
|
+
width: 100%;
|
|
268
|
+
height: 100%;
|
|
269
|
+
|
|
270
|
+
background-color: transparent;
|
|
271
|
+
border: 1px solid var(--coz-stroke-plus, rgba(6, 7, 9, 15%));
|
|
272
|
+
border-color: var(--coz-bg-plus, rgb(249, 249, 249));
|
|
273
|
+
border-style: solid;
|
|
274
|
+
border-width: 8px;
|
|
275
|
+
border-radius: 8px;
|
|
276
|
+
box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 4%), 0 4px 12px 0 rgba(0, 0, 0, 2%);
|
|
277
|
+
|
|
278
|
+
&::before {
|
|
279
|
+
content: '';
|
|
280
|
+
|
|
281
|
+
position: absolute;
|
|
282
|
+
z-index: 0;
|
|
283
|
+
inset: -4px;
|
|
284
|
+
|
|
285
|
+
background-color: transparent;
|
|
286
|
+
border-color: var(--coz-bg-plus, rgb(249, 249, 249));
|
|
287
|
+
border-style: solid;
|
|
288
|
+
border-width: 4px;
|
|
289
|
+
border-radius: 8px;
|
|
290
|
+
}
|
|
291
|
+
`;
|
|
292
|
+
|
|
293
|
+
// src/container-node-render/components/border/index.tsx
|
|
294
|
+
var ContainerNodeBorder = () => {
|
|
295
|
+
const { node } = useNodeRender5();
|
|
296
|
+
const transformData = node.getData(FlowNodeTransformData2);
|
|
297
|
+
const topWidth = Math.max(transformData.padding.top - 50, 50);
|
|
298
|
+
return /* @__PURE__ */ React4.createElement(
|
|
299
|
+
ContainerNodeBorderStyle,
|
|
300
|
+
{
|
|
301
|
+
className: "container-node-border",
|
|
302
|
+
style: {
|
|
303
|
+
borderTopWidth: topWidth
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
);
|
|
307
|
+
};
|
|
308
|
+
|
|
309
|
+
// src/container-node-render/components/ports/index.tsx
|
|
310
|
+
import React5, { useEffect as useEffect2 } from "react";
|
|
311
|
+
import { WorkflowPortRender } from "@flowgram.ai/free-lines-plugin";
|
|
312
|
+
import { WorkflowNodePortsData as WorkflowNodePortsData2, useNodeRender as useNodeRender6 } from "@flowgram.ai/free-layout-core";
|
|
313
|
+
var ContainerNodePorts = () => {
|
|
314
|
+
const { node, ports } = useNodeRender6();
|
|
315
|
+
const { renderPorts } = useContainerNodeRenderProps();
|
|
316
|
+
useEffect2(() => {
|
|
317
|
+
const portsData = node.getData(WorkflowNodePortsData2);
|
|
318
|
+
portsData.updateDynamicPorts();
|
|
319
|
+
}, [node]);
|
|
320
|
+
return /* @__PURE__ */ React5.createElement(React5.Fragment, null, renderPorts.map((p) => /* @__PURE__ */ React5.createElement(
|
|
321
|
+
"div",
|
|
322
|
+
{
|
|
323
|
+
key: `canvas-port${p.id}`,
|
|
324
|
+
className: "container-node-port",
|
|
325
|
+
"data-port-id": p.id,
|
|
326
|
+
"data-port-type": p.type,
|
|
327
|
+
style: p.style
|
|
328
|
+
}
|
|
329
|
+
)), ports.map((p) => /* @__PURE__ */ React5.createElement(WorkflowPortRender, { key: p.id, entity: p })));
|
|
330
|
+
};
|
|
331
|
+
|
|
332
|
+
// src/container-node-render/components/form/index.tsx
|
|
333
|
+
import React6 from "react";
|
|
334
|
+
import { useNodeRender as useNodeRender7 } from "@flowgram.ai/free-layout-core";
|
|
335
|
+
|
|
336
|
+
// src/container-node-render/components/form/style.ts
|
|
337
|
+
import styled5 from "styled-components";
|
|
338
|
+
var ContainerNodeFormStyle = styled5.div`
|
|
339
|
+
background-color: #fff;
|
|
340
|
+
border-radius: 8px 8px 0 0;
|
|
341
|
+
width: 100%;
|
|
342
|
+
`;
|
|
343
|
+
|
|
344
|
+
// src/container-node-render/components/form/index.tsx
|
|
345
|
+
var ContainerNodeForm = () => {
|
|
346
|
+
const { form } = useNodeRender7();
|
|
347
|
+
if (!form) {
|
|
348
|
+
return null;
|
|
349
|
+
}
|
|
350
|
+
return /* @__PURE__ */ React6.createElement(ContainerNodeFormStyle, null, form.render());
|
|
351
|
+
};
|
|
352
|
+
|
|
353
|
+
// src/container-node-render/render.tsx
|
|
354
|
+
var ContainerNodeRender = ({ content }) => /* @__PURE__ */ React7.createElement(ContainerNodeContainer, null, /* @__PURE__ */ React7.createElement(ContainerNodeBackground, null), /* @__PURE__ */ React7.createElement(ContainerNodeBorder, null), /* @__PURE__ */ React7.createElement(ContainerNodeHeader, null, content), /* @__PURE__ */ React7.createElement(ContainerNodePorts, null));
|
|
355
|
+
|
|
356
|
+
// src/node-into-container/constant.ts
|
|
357
|
+
var NodeIntoContainerType = /* @__PURE__ */ ((NodeIntoContainerType2) => {
|
|
358
|
+
NodeIntoContainerType2["In"] = "in";
|
|
359
|
+
NodeIntoContainerType2["Out"] = "out";
|
|
360
|
+
return NodeIntoContainerType2;
|
|
361
|
+
})(NodeIntoContainerType || {});
|
|
362
|
+
|
|
363
|
+
// src/node-into-container/service.ts
|
|
364
|
+
import { throttle } from "lodash";
|
|
365
|
+
import { inject, injectable } from "inversify";
|
|
366
|
+
import {
|
|
367
|
+
Rectangle,
|
|
368
|
+
DisposableCollection,
|
|
369
|
+
Emitter
|
|
370
|
+
} from "@flowgram.ai/utils";
|
|
371
|
+
import {
|
|
372
|
+
WorkflowDocument,
|
|
373
|
+
WorkflowDragService,
|
|
374
|
+
WorkflowLinesManager,
|
|
375
|
+
WorkflowOperationBaseService,
|
|
376
|
+
WorkflowSelectService
|
|
377
|
+
} from "@flowgram.ai/free-layout-core";
|
|
378
|
+
import { HistoryService } from "@flowgram.ai/free-history-plugin";
|
|
379
|
+
import { FlowNodeTransformData as FlowNodeTransformData3, FlowNodeRenderData } from "@flowgram.ai/document";
|
|
380
|
+
import { PlaygroundConfigEntity, TransformData } from "@flowgram.ai/core";
|
|
381
|
+
var NodeIntoContainerService = class {
|
|
382
|
+
constructor() {
|
|
383
|
+
this.emitter = new Emitter();
|
|
384
|
+
this.toDispose = new DisposableCollection();
|
|
385
|
+
this.on = this.emitter.event;
|
|
386
|
+
}
|
|
387
|
+
init() {
|
|
388
|
+
this.initState();
|
|
389
|
+
this.toDispose.push(this.emitter);
|
|
390
|
+
}
|
|
391
|
+
ready() {
|
|
392
|
+
this.toDispose.push(this.listenDragToContainer());
|
|
393
|
+
}
|
|
394
|
+
dispose() {
|
|
395
|
+
this.initState();
|
|
396
|
+
this.toDispose.dispose();
|
|
397
|
+
}
|
|
398
|
+
/** 移除节点连线 */
|
|
399
|
+
async removeNodeLines(node) {
|
|
400
|
+
const lines = this.linesManager.getAllLines();
|
|
401
|
+
lines.forEach((line) => {
|
|
402
|
+
if (line.from.id !== node.id && line.to?.id !== node.id) {
|
|
403
|
+
return;
|
|
404
|
+
}
|
|
405
|
+
line.dispose();
|
|
406
|
+
});
|
|
407
|
+
await this.nextFrame();
|
|
408
|
+
}
|
|
409
|
+
/** 将节点移出容器 */
|
|
410
|
+
async moveOutContainer(params) {
|
|
411
|
+
const { node } = params;
|
|
412
|
+
const parentNode = node.parent;
|
|
413
|
+
const containerNode = parentNode?.parent;
|
|
414
|
+
const nodeJSON = await this.document.toNodeJSON(node);
|
|
415
|
+
if (!parentNode || !containerNode || !this.isContainer(parentNode) || !nodeJSON.meta?.position) {
|
|
416
|
+
return;
|
|
417
|
+
}
|
|
418
|
+
this.operationService.moveNode(node, {
|
|
419
|
+
parent: containerNode
|
|
420
|
+
});
|
|
421
|
+
const parentTransform = parentNode.getData(TransformData);
|
|
422
|
+
this.operationService.updateNodePosition(node, {
|
|
423
|
+
x: parentTransform.position.x + nodeJSON.meta.position.x,
|
|
424
|
+
y: parentTransform.position.y + nodeJSON.meta.position.y
|
|
425
|
+
});
|
|
426
|
+
parentTransform.fireChange();
|
|
427
|
+
await this.nextFrame();
|
|
428
|
+
parentTransform.fireChange();
|
|
429
|
+
this.emitter.fire({
|
|
430
|
+
type: "out" /* Out */,
|
|
431
|
+
node,
|
|
432
|
+
sourceContainer: parentNode,
|
|
433
|
+
targetContainer: containerNode
|
|
434
|
+
});
|
|
435
|
+
}
|
|
436
|
+
/** 能否将节点移出容器 */
|
|
437
|
+
canMoveOutContainer(node) {
|
|
438
|
+
const parentNode = node.parent;
|
|
439
|
+
const containerNode = parentNode?.parent;
|
|
440
|
+
if (!parentNode || !containerNode || !this.isContainer(parentNode)) {
|
|
441
|
+
return false;
|
|
442
|
+
}
|
|
443
|
+
return true;
|
|
444
|
+
}
|
|
445
|
+
/** 初始化状态 */
|
|
446
|
+
initState() {
|
|
447
|
+
this.state = {
|
|
448
|
+
isDraggingNode: false,
|
|
449
|
+
isSkipEvent: false,
|
|
450
|
+
transforms: void 0,
|
|
451
|
+
dragNode: void 0,
|
|
452
|
+
dropNode: void 0,
|
|
453
|
+
sourceParent: void 0
|
|
454
|
+
};
|
|
455
|
+
}
|
|
456
|
+
/** 监听节点拖拽 */
|
|
457
|
+
listenDragToContainer() {
|
|
458
|
+
const draggingNode = (e) => this.draggingNode(e);
|
|
459
|
+
const throttledDraggingNode = throttle(draggingNode, 200);
|
|
460
|
+
return this.dragService.onNodesDrag(async (event) => {
|
|
461
|
+
if (this.selectService.selectedNodes.length !== 1) {
|
|
462
|
+
return;
|
|
463
|
+
}
|
|
464
|
+
if (event.type === "onDragStart") {
|
|
465
|
+
if (this.state.isSkipEvent) {
|
|
466
|
+
this.state.isSkipEvent = false;
|
|
467
|
+
return;
|
|
468
|
+
}
|
|
469
|
+
this.historyService.startTransaction();
|
|
470
|
+
this.state.isDraggingNode = true;
|
|
471
|
+
this.state.transforms = this.getContainerTransforms();
|
|
472
|
+
this.state.dragNode = this.selectService.selectedNodes[0];
|
|
473
|
+
this.state.dropNode = void 0;
|
|
474
|
+
this.state.sourceParent = this.state.dragNode?.parent;
|
|
475
|
+
await this.dragOutContainer(event);
|
|
476
|
+
}
|
|
477
|
+
if (event.type === "onDragging") {
|
|
478
|
+
throttledDraggingNode(event);
|
|
479
|
+
}
|
|
480
|
+
if (event.type === "onDragEnd") {
|
|
481
|
+
if (this.state.isSkipEvent) {
|
|
482
|
+
return;
|
|
483
|
+
}
|
|
484
|
+
throttledDraggingNode.cancel();
|
|
485
|
+
draggingNode(event);
|
|
486
|
+
await this.dropNodeToContainer();
|
|
487
|
+
await this.clearInvalidLines();
|
|
488
|
+
this.setDropNode(void 0);
|
|
489
|
+
this.initState();
|
|
490
|
+
this.historyService.endTransaction();
|
|
491
|
+
}
|
|
492
|
+
});
|
|
493
|
+
}
|
|
494
|
+
/** 监听节点拖拽出容器 */
|
|
495
|
+
async dragOutContainer(event) {
|
|
496
|
+
const { dragNode } = this.state;
|
|
497
|
+
const activated = event.triggerEvent.metaKey || event.triggerEvent.ctrlKey;
|
|
498
|
+
if (!activated || // 必须按住指定按键
|
|
499
|
+
!dragNode || // 必须有一个节点
|
|
500
|
+
!this.canMoveOutContainer(dragNode)) {
|
|
501
|
+
return;
|
|
502
|
+
}
|
|
503
|
+
this.moveOutContainer({ node: dragNode });
|
|
504
|
+
this.state.isSkipEvent = true;
|
|
505
|
+
event.dragger.stop(event.dragEvent.clientX, event.dragEvent.clientY);
|
|
506
|
+
await this.nextFrame();
|
|
507
|
+
this.dragService.startDragSelectedNodes(event.triggerEvent);
|
|
508
|
+
}
|
|
509
|
+
/** 移除节点所有非法连线 */
|
|
510
|
+
async clearInvalidLines() {
|
|
511
|
+
const { dragNode, sourceParent } = this.state;
|
|
512
|
+
if (!dragNode) {
|
|
513
|
+
return;
|
|
514
|
+
}
|
|
515
|
+
if (dragNode.parent === sourceParent) {
|
|
516
|
+
return;
|
|
517
|
+
}
|
|
518
|
+
const lines = this.linesManager.getAllLines();
|
|
519
|
+
lines.forEach((line) => {
|
|
520
|
+
if (line.from.id !== dragNode.id && line.to?.id !== dragNode.id) {
|
|
521
|
+
return;
|
|
522
|
+
}
|
|
523
|
+
line.dispose();
|
|
524
|
+
});
|
|
525
|
+
await this.nextFrame();
|
|
526
|
+
}
|
|
527
|
+
/** 获取重叠位置 */
|
|
528
|
+
getCollisionTransform(params) {
|
|
529
|
+
const { targetRect, targetPoint, transforms, withPadding = false } = params;
|
|
530
|
+
const collisionTransform = transforms.find((transform) => {
|
|
531
|
+
const { bounds, entity } = transform;
|
|
532
|
+
const padding = withPadding ? this.document.layout.getPadding(entity) : { left: 0, right: 0 };
|
|
533
|
+
const transformRect = new Rectangle(
|
|
534
|
+
bounds.x + padding.left + padding.right,
|
|
535
|
+
bounds.y,
|
|
536
|
+
bounds.width,
|
|
537
|
+
bounds.height
|
|
538
|
+
);
|
|
539
|
+
if (targetRect) {
|
|
540
|
+
return this.isRectIntersects(targetRect, transformRect);
|
|
541
|
+
}
|
|
542
|
+
if (targetPoint) {
|
|
543
|
+
return this.isPointInRect(targetPoint, transformRect);
|
|
544
|
+
}
|
|
545
|
+
return false;
|
|
546
|
+
});
|
|
547
|
+
return collisionTransform;
|
|
548
|
+
}
|
|
549
|
+
/** 设置放置节点高亮 */
|
|
550
|
+
setDropNode(dropNode) {
|
|
551
|
+
if (this.state.dropNode === dropNode) {
|
|
552
|
+
return;
|
|
553
|
+
}
|
|
554
|
+
if (this.state.dropNode) {
|
|
555
|
+
const renderData2 = this.state.dropNode.getData(FlowNodeRenderData);
|
|
556
|
+
const renderDom2 = renderData2.node?.children?.[0];
|
|
557
|
+
if (renderDom2) {
|
|
558
|
+
renderDom2.style.outline = "";
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
this.state.dropNode = dropNode;
|
|
562
|
+
if (!dropNode) {
|
|
563
|
+
return;
|
|
564
|
+
}
|
|
565
|
+
const renderData = dropNode.getData(FlowNodeRenderData);
|
|
566
|
+
const renderDom = renderData.node?.children?.[0];
|
|
567
|
+
if (renderDom) {
|
|
568
|
+
renderDom.style.outline = "1px solid var(--coz-stroke-hglt,#4e40e5)";
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
/** 获取容器节点transforms */
|
|
572
|
+
getContainerTransforms() {
|
|
573
|
+
return this.document.getRenderDatas(FlowNodeTransformData3, false).filter((transform) => {
|
|
574
|
+
const { entity } = transform;
|
|
575
|
+
if (entity.originParent) {
|
|
576
|
+
return entity.getNodeMeta().selectable && entity.originParent.getNodeMeta().selectable;
|
|
577
|
+
}
|
|
578
|
+
return entity.getNodeMeta().selectable;
|
|
579
|
+
}).filter((transform) => this.isContainer(transform.entity));
|
|
580
|
+
}
|
|
581
|
+
/** 放置节点到容器 */
|
|
582
|
+
async dropNodeToContainer() {
|
|
583
|
+
const { dropNode, dragNode, isDraggingNode } = this.state;
|
|
584
|
+
if (!isDraggingNode || !dragNode || !dropNode) {
|
|
585
|
+
return;
|
|
586
|
+
}
|
|
587
|
+
return await this.moveIntoContainer({
|
|
588
|
+
node: dragNode,
|
|
589
|
+
containerNode: dropNode
|
|
590
|
+
});
|
|
591
|
+
}
|
|
592
|
+
/** 拖拽节点 */
|
|
593
|
+
draggingNode(nodeDragEvent) {
|
|
594
|
+
const { dragNode, isDraggingNode, transforms } = this.state;
|
|
595
|
+
if (!isDraggingNode || !dragNode || this.isContainer(dragNode) || !transforms?.length) {
|
|
596
|
+
return this.setDropNode(void 0);
|
|
597
|
+
}
|
|
598
|
+
const mousePos = this.playgroundConfig.getPosFromMouseEvent(nodeDragEvent.dragEvent);
|
|
599
|
+
const collisionTransform = this.getCollisionTransform({
|
|
600
|
+
targetPoint: mousePos,
|
|
601
|
+
transforms: this.state.transforms ?? []
|
|
602
|
+
});
|
|
603
|
+
const dropNode = collisionTransform?.entity;
|
|
604
|
+
if (!dropNode || dragNode.parent?.id === dropNode.id) {
|
|
605
|
+
return this.setDropNode(void 0);
|
|
606
|
+
}
|
|
607
|
+
const canDrop = this.dragService.canDropToNode({
|
|
608
|
+
dragNodeType: dragNode.flowNodeType,
|
|
609
|
+
dropNode
|
|
610
|
+
});
|
|
611
|
+
if (!canDrop.allowDrop) {
|
|
612
|
+
return this.setDropNode(void 0);
|
|
613
|
+
}
|
|
614
|
+
return this.setDropNode(canDrop.dropNode);
|
|
615
|
+
}
|
|
616
|
+
/** 将节点移入容器 */
|
|
617
|
+
async moveIntoContainer(params) {
|
|
618
|
+
const { node, containerNode } = params;
|
|
619
|
+
const parentNode = node.parent;
|
|
620
|
+
const nodeJSON = await this.document.toNodeJSON(node);
|
|
621
|
+
this.operationService.moveNode(node, {
|
|
622
|
+
parent: containerNode
|
|
623
|
+
});
|
|
624
|
+
this.operationService.updateNodePosition(
|
|
625
|
+
node,
|
|
626
|
+
this.dragService.adjustSubNodePosition(
|
|
627
|
+
nodeJSON.type,
|
|
628
|
+
containerNode,
|
|
629
|
+
nodeJSON.meta.position
|
|
630
|
+
)
|
|
631
|
+
);
|
|
632
|
+
await this.nextFrame();
|
|
633
|
+
this.emitter.fire({
|
|
634
|
+
type: "in" /* In */,
|
|
635
|
+
node,
|
|
636
|
+
sourceContainer: parentNode,
|
|
637
|
+
targetContainer: containerNode
|
|
638
|
+
});
|
|
639
|
+
}
|
|
640
|
+
isContainer(node) {
|
|
641
|
+
return node?.getNodeMeta().isContainer ?? false;
|
|
642
|
+
}
|
|
643
|
+
/** 判断点是否在矩形内 */
|
|
644
|
+
isPointInRect(point, rect) {
|
|
645
|
+
return point.x >= rect.left && point.x <= rect.right && point.y >= rect.top && point.y <= rect.bottom;
|
|
646
|
+
}
|
|
647
|
+
/** 判断两个矩形是否相交 */
|
|
648
|
+
isRectIntersects(rectA, rectB) {
|
|
649
|
+
const hasHorizontalOverlap = rectA.right > rectB.left && rectA.left < rectB.right;
|
|
650
|
+
const hasVerticalOverlap = rectA.bottom > rectB.top && rectA.top < rectB.bottom;
|
|
651
|
+
return hasHorizontalOverlap && hasVerticalOverlap;
|
|
652
|
+
}
|
|
653
|
+
async nextFrame() {
|
|
654
|
+
await new Promise((resolve) => requestAnimationFrame(resolve));
|
|
655
|
+
}
|
|
656
|
+
};
|
|
657
|
+
__decorateClass([
|
|
658
|
+
inject(WorkflowDragService)
|
|
659
|
+
], NodeIntoContainerService.prototype, "dragService", 2);
|
|
660
|
+
__decorateClass([
|
|
661
|
+
inject(WorkflowDocument)
|
|
662
|
+
], NodeIntoContainerService.prototype, "document", 2);
|
|
663
|
+
__decorateClass([
|
|
664
|
+
inject(PlaygroundConfigEntity)
|
|
665
|
+
], NodeIntoContainerService.prototype, "playgroundConfig", 2);
|
|
666
|
+
__decorateClass([
|
|
667
|
+
inject(WorkflowOperationBaseService)
|
|
668
|
+
], NodeIntoContainerService.prototype, "operationService", 2);
|
|
669
|
+
__decorateClass([
|
|
670
|
+
inject(WorkflowLinesManager)
|
|
671
|
+
], NodeIntoContainerService.prototype, "linesManager", 2);
|
|
672
|
+
__decorateClass([
|
|
673
|
+
inject(HistoryService)
|
|
674
|
+
], NodeIntoContainerService.prototype, "historyService", 2);
|
|
675
|
+
__decorateClass([
|
|
676
|
+
inject(WorkflowSelectService)
|
|
677
|
+
], NodeIntoContainerService.prototype, "selectService", 2);
|
|
678
|
+
NodeIntoContainerService = __decorateClass([
|
|
679
|
+
injectable()
|
|
680
|
+
], NodeIntoContainerService);
|
|
681
|
+
|
|
682
|
+
// src/plugin.tsx
|
|
683
|
+
import React8 from "react";
|
|
684
|
+
import { FlowRendererRegistry } from "@flowgram.ai/renderer";
|
|
685
|
+
import { definePluginCreator } from "@flowgram.ai/core";
|
|
686
|
+
var createContainerNodePlugin = definePluginCreator({
|
|
687
|
+
onBind: ({ bind }) => {
|
|
688
|
+
bind(NodeIntoContainerService).toSelf().inSingletonScope();
|
|
689
|
+
},
|
|
690
|
+
onInit(ctx, options) {
|
|
691
|
+
ctx.get(NodeIntoContainerService).init();
|
|
692
|
+
const registry = ctx.get(FlowRendererRegistry);
|
|
693
|
+
registry.registerReactComponent(ContainerNodeRenderKey, (props) => /* @__PURE__ */ React8.createElement(ContainerNodeRender, { ...props, content: options.renderContent }));
|
|
694
|
+
},
|
|
695
|
+
onReady(ctx, options) {
|
|
696
|
+
if (options.disableNodeIntoContainer !== true) {
|
|
697
|
+
ctx.get(NodeIntoContainerService).ready();
|
|
698
|
+
}
|
|
699
|
+
},
|
|
700
|
+
onDispose(ctx) {
|
|
701
|
+
ctx.get(NodeIntoContainerService).dispose();
|
|
702
|
+
}
|
|
703
|
+
});
|
|
704
|
+
export {
|
|
705
|
+
ContainerNodeBackground,
|
|
706
|
+
ContainerNodeBorder,
|
|
707
|
+
ContainerNodeContainer,
|
|
708
|
+
ContainerNodeForm,
|
|
709
|
+
ContainerNodeHeader,
|
|
710
|
+
ContainerNodePorts,
|
|
711
|
+
ContainerNodeRender,
|
|
712
|
+
ContainerNodeRenderKey,
|
|
713
|
+
NodeIntoContainerService,
|
|
714
|
+
NodeIntoContainerType,
|
|
715
|
+
createContainerNodePlugin
|
|
716
|
+
};
|
|
717
|
+
//# sourceMappingURL=index.js.map
|