@genfeedai/workflow-ui 0.2.3 → 0.2.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/canvas.d.ts +22 -22
- package/dist/canvas.mjs +16 -16
- package/dist/{chunk-XPZAHIWY.mjs → chunk-2FUPL67V.mjs} +1592 -1044
- package/dist/{chunk-HWVTD2LC.mjs → chunk-53XDE62A.mjs} +818 -623
- package/dist/{chunk-PCIWWD37.mjs → chunk-7LV4UAUS.mjs} +19 -19
- package/dist/{chunk-7SKSRSS7.mjs → chunk-B4EAAKYF.mjs} +16 -16
- package/dist/{chunk-ZJD5WMR3.mjs → chunk-C6MQBJFC.mjs} +45 -13
- package/dist/{chunk-7H3WJJYS.mjs → chunk-ESVULCFY.mjs} +12 -6
- package/dist/{chunk-GWBGK3KL.mjs → chunk-FWJIAW2E.mjs} +82 -47
- package/dist/{chunk-R727OFBR.mjs → chunk-GPYIIWD5.mjs} +404 -350
- package/dist/{chunk-OQREHJXK.mjs → chunk-IYFWAJBB.mjs} +208 -203
- package/dist/{chunk-N5NJZTK4.mjs → chunk-MGLAKMDP.mjs} +23 -21
- package/dist/{chunk-LT3ZJJL6.mjs → chunk-OJWVEEMM.mjs} +497 -399
- package/dist/{chunk-ZD2BADZO.mjs → chunk-ORVDYXDP.mjs} +221 -175
- package/dist/{chunk-CV4M7CNU.mjs → chunk-QQVHGJ2G.mjs} +149 -142
- package/dist/{chunk-6PSJTBNV.mjs → chunk-U4QPE4CY.mjs} +387 -347
- package/dist/{chunk-EFXQT23N.mjs → chunk-VVQ4CH77.mjs} +5 -5
- package/dist/{chunk-VRN3UWE5.mjs → chunk-XRC3O5GK.mjs} +73 -73
- package/dist/{chunk-FT33LFII.mjs → chunk-YUIK4AHM.mjs} +1 -1
- package/dist/{chunk-FMJPFB6W.mjs → chunk-ZSITTZ4S.mjs} +630 -569
- package/dist/hooks.d.ts +37 -37
- package/dist/hooks.mjs +10 -10
- package/dist/index.d.ts +26 -11
- package/dist/index.mjs +105 -19
- package/dist/lib.d.ts +203 -203
- package/dist/lib.mjs +228 -198
- package/dist/nodes.d.ts +2 -2
- package/dist/nodes.mjs +12 -12
- package/dist/panels.d.ts +2 -3
- package/dist/panels.mjs +3 -3
- package/dist/provider.d.ts +2 -2
- package/dist/provider.mjs +2 -2
- package/dist/stores.d.ts +5 -5
- package/dist/stores.mjs +5 -5
- package/dist/toolbar.d.ts +42 -24
- package/dist/toolbar.mjs +4 -4
- package/dist/ui.d.ts +2 -2
- package/dist/ui.mjs +2 -2
- package/dist/{useCommentNavigation-BakbiiIc.d.ts → useRequiredInputs-ByoIS-fT.d.ts} +160 -160
- package/dist/{promptLibraryStore-Dl3Q3cP6.d.ts → workflowStore-Bsz0nd5c.d.ts} +368 -368
- package/dist/workflowStore-N2F7WIG3.mjs +2 -0
- package/package.json +77 -75
- package/src/styles/workflow-ui.css +56 -19
- package/dist/workflowStore-UAAKOOIK.mjs +0 -2
- package/dist/{types-IEKYuYhu.d.ts → types-CRXJnajq.d.ts} +1 -1
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
1
|
+
import { useWorkflowUIConfig } from './chunk-YUIK4AHM.mjs';
|
|
2
|
+
import { selectNodes, selectEdges, selectRemoveNode, selectDuplicateNode, selectAddNode, useContextMenuStore, selectToggleNodeLock, selectCreateGroup, selectWorkflowId, selectSetSelectedNodeIds, selectUpdateNodeData } from './chunk-7LV4UAUS.mjs';
|
|
3
|
+
import { useSettingsStore } from './chunk-OJWVEEMM.mjs';
|
|
4
|
+
import { useWorkflowStore } from './chunk-GPYIIWD5.mjs';
|
|
5
5
|
import { useEffect, useState, useCallback, useRef, useMemo } from 'react';
|
|
6
6
|
import { nanoid } from 'nanoid';
|
|
7
7
|
import { useReactFlow } from '@xyflow/react';
|
|
8
8
|
import Dagre from '@dagrejs/dagre';
|
|
9
9
|
import { getNodesByCategory, NODE_DEFINITIONS } from '@genfeedai/types';
|
|
10
|
-
import { ChevronRight, Group, Copy, Lock, LockOpen, AlignHorizontalJustifyCenter, AlignVerticalJustifyCenter, Trash2,
|
|
10
|
+
import { ChevronRight, Group, Copy, Lock, LockOpen, AlignHorizontalJustifyCenter, AlignVerticalJustifyCenter, Trash2, Wand2, Volume2, Video, Subtitles, Sparkles, Scissors, Pencil, Navigation, Mic, MessageSquare, Maximize2, Maximize, Layers, Image, Grid3X3, GitBranch, Film, FileVideo, FileText, Crop, CheckCircle, Brain, AudioLines, ArrowRightToLine, ArrowLeftFromLine, Monitor, Clipboard, LayoutGrid, Palette } from 'lucide-react';
|
|
11
11
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
12
12
|
|
|
13
13
|
function useCanvasKeyboardShortcuts({
|
|
@@ -45,10 +45,12 @@ function useCanvasKeyboardShortcuts({
|
|
|
45
45
|
if (e.key === "f" && !isMod && !e.shiftKey) {
|
|
46
46
|
e.preventDefault();
|
|
47
47
|
if (selectedNodeIds.length > 0) {
|
|
48
|
-
const selectedNodes = nodes.filter(
|
|
49
|
-
|
|
48
|
+
const selectedNodes = nodes.filter(
|
|
49
|
+
(n) => selectedNodeIds.includes(n.id)
|
|
50
|
+
);
|
|
51
|
+
fitView({ duration: 200, nodes: selectedNodes, padding: 0.3 });
|
|
50
52
|
} else {
|
|
51
|
-
fitView({ padding: 0.2
|
|
53
|
+
fitView({ duration: 200, padding: 0.2 });
|
|
52
54
|
}
|
|
53
55
|
}
|
|
54
56
|
if (e.key === "?" && e.shiftKey && !isMod) {
|
|
@@ -87,22 +89,34 @@ function useCanvasKeyboardShortcuts({
|
|
|
87
89
|
}
|
|
88
90
|
if (e.key === "I" && e.shiftKey && !isMod) {
|
|
89
91
|
e.preventDefault();
|
|
90
|
-
const position = {
|
|
92
|
+
const position = {
|
|
93
|
+
x: window.innerWidth / 2 - 150,
|
|
94
|
+
y: window.innerHeight / 2 - 150
|
|
95
|
+
};
|
|
91
96
|
addNode("imageGen", position);
|
|
92
97
|
}
|
|
93
98
|
if (e.key === "V" && e.shiftKey && !isMod) {
|
|
94
99
|
e.preventDefault();
|
|
95
|
-
const position = {
|
|
100
|
+
const position = {
|
|
101
|
+
x: window.innerWidth / 2 - 150,
|
|
102
|
+
y: window.innerHeight / 2 - 150
|
|
103
|
+
};
|
|
96
104
|
addNode("videoGen", position);
|
|
97
105
|
}
|
|
98
106
|
if (e.key === "P" && e.shiftKey && !isMod) {
|
|
99
107
|
e.preventDefault();
|
|
100
|
-
const position = {
|
|
108
|
+
const position = {
|
|
109
|
+
x: window.innerWidth / 2 - 150,
|
|
110
|
+
y: window.innerHeight / 2 - 150
|
|
111
|
+
};
|
|
101
112
|
addNode("prompt", position);
|
|
102
113
|
}
|
|
103
114
|
if ((e.key === "L" || e.key === "l") && e.shiftKey && !isMod) {
|
|
104
115
|
e.preventDefault();
|
|
105
|
-
const position = {
|
|
116
|
+
const position = {
|
|
117
|
+
x: window.innerWidth / 2 - 150,
|
|
118
|
+
y: window.innerHeight / 2 - 150
|
|
119
|
+
};
|
|
106
120
|
addNode("llm", position);
|
|
107
121
|
}
|
|
108
122
|
if (e.key === "z" && isMod && !e.shiftKey) {
|
|
@@ -142,18 +156,18 @@ function createPastePayload(clipboard, offsetX, offsetY) {
|
|
|
142
156
|
const minY = Math.min(...clipboardNodes.map((n) => n.position.y));
|
|
143
157
|
const newNodes = clipboardNodes.map((node) => ({
|
|
144
158
|
...node,
|
|
159
|
+
data: {
|
|
160
|
+
...node.data,
|
|
161
|
+
error: void 0,
|
|
162
|
+
jobId: null,
|
|
163
|
+
status: "idle"
|
|
164
|
+
},
|
|
145
165
|
id: idMap.get(node.id),
|
|
146
166
|
position: {
|
|
147
167
|
x: node.position.x - minX + offsetX,
|
|
148
168
|
y: node.position.y - minY + offsetY
|
|
149
169
|
},
|
|
150
|
-
selected: true
|
|
151
|
-
data: {
|
|
152
|
-
...node.data,
|
|
153
|
-
status: "idle",
|
|
154
|
-
jobId: null,
|
|
155
|
-
error: void 0
|
|
156
|
-
}
|
|
170
|
+
selected: true
|
|
157
171
|
}));
|
|
158
172
|
const newEdges = clipboardEdges.map((edge) => ({
|
|
159
173
|
...edge,
|
|
@@ -161,7 +175,7 @@ function createPastePayload(clipboard, offsetX, offsetY) {
|
|
|
161
175
|
source: idMap.get(edge.source),
|
|
162
176
|
target: idMap.get(edge.target)
|
|
163
177
|
}));
|
|
164
|
-
return {
|
|
178
|
+
return { edges: newEdges, nodes: newNodes };
|
|
165
179
|
}
|
|
166
180
|
function useNodeActions() {
|
|
167
181
|
const nodes = useWorkflowStore(selectNodes);
|
|
@@ -185,7 +199,7 @@ function useNodeActions() {
|
|
|
185
199
|
(nodeId) => {
|
|
186
200
|
const node = nodes.find((n) => n.id === nodeId);
|
|
187
201
|
if (node) {
|
|
188
|
-
setClipboard({
|
|
202
|
+
setClipboard({ edges: [], isCut: false, nodes: [node] });
|
|
189
203
|
}
|
|
190
204
|
},
|
|
191
205
|
[nodes]
|
|
@@ -194,9 +208,11 @@ function useNodeActions() {
|
|
|
194
208
|
(nodeIds) => {
|
|
195
209
|
const nodeSet = new Set(nodeIds);
|
|
196
210
|
const nodesToCopy = nodes.filter((n) => nodeSet.has(n.id));
|
|
197
|
-
const edgesToCopy = edges.filter(
|
|
211
|
+
const edgesToCopy = edges.filter(
|
|
212
|
+
(e) => nodeSet.has(e.source) && nodeSet.has(e.target)
|
|
213
|
+
);
|
|
198
214
|
if (nodesToCopy.length > 0) {
|
|
199
|
-
setClipboard({
|
|
215
|
+
setClipboard({ edges: edgesToCopy, isCut: false, nodes: nodesToCopy });
|
|
200
216
|
}
|
|
201
217
|
},
|
|
202
218
|
[nodes, edges]
|
|
@@ -205,7 +221,7 @@ function useNodeActions() {
|
|
|
205
221
|
(nodeId) => {
|
|
206
222
|
const node = nodes.find((n) => n.id === nodeId);
|
|
207
223
|
if (node) {
|
|
208
|
-
setClipboard({
|
|
224
|
+
setClipboard({ edges: [], isCut: true, nodes: [node] });
|
|
209
225
|
removeNode(nodeId);
|
|
210
226
|
}
|
|
211
227
|
},
|
|
@@ -215,9 +231,11 @@ function useNodeActions() {
|
|
|
215
231
|
(nodeIds) => {
|
|
216
232
|
const nodeSet = new Set(nodeIds);
|
|
217
233
|
const nodesToCut = nodes.filter((n) => nodeSet.has(n.id));
|
|
218
|
-
const edgesToCut = edges.filter(
|
|
234
|
+
const edgesToCut = edges.filter(
|
|
235
|
+
(e) => nodeSet.has(e.source) && nodeSet.has(e.target)
|
|
236
|
+
);
|
|
219
237
|
if (nodesToCut.length > 0) {
|
|
220
|
-
setClipboard({
|
|
238
|
+
setClipboard({ edges: edgesToCut, isCut: true, nodes: nodesToCut });
|
|
221
239
|
for (const nodeId of nodeIds) {
|
|
222
240
|
removeNode(nodeId);
|
|
223
241
|
}
|
|
@@ -254,8 +272,8 @@ function useNodeActions() {
|
|
|
254
272
|
setClipboard(null);
|
|
255
273
|
}
|
|
256
274
|
return {
|
|
257
|
-
|
|
258
|
-
|
|
275
|
+
edgeIds: payload.edges.map((e) => e.id),
|
|
276
|
+
nodeIds: payload.nodes.map((n) => n.id)
|
|
259
277
|
};
|
|
260
278
|
},
|
|
261
279
|
[clipboard]
|
|
@@ -273,16 +291,16 @@ function useNodeActions() {
|
|
|
273
291
|
);
|
|
274
292
|
return {
|
|
275
293
|
clipboard,
|
|
276
|
-
deleteNode,
|
|
277
|
-
duplicate,
|
|
278
|
-
copyNode,
|
|
279
294
|
copyMultipleNodes,
|
|
280
|
-
|
|
295
|
+
copyNode,
|
|
281
296
|
cutMultipleNodes,
|
|
297
|
+
cutNode,
|
|
282
298
|
deleteMultipleNodes,
|
|
299
|
+
deleteNode,
|
|
300
|
+
duplicate,
|
|
283
301
|
duplicateMultipleNodes,
|
|
284
|
-
|
|
285
|
-
|
|
302
|
+
getPasteData,
|
|
303
|
+
pasteNodes
|
|
286
304
|
};
|
|
287
305
|
}
|
|
288
306
|
var DEFAULT_NODE_WIDTH = 280;
|
|
@@ -290,10 +308,10 @@ var DEFAULT_NODE_HEIGHT = 200;
|
|
|
290
308
|
var MIN_GAP = 40;
|
|
291
309
|
function getNodeRect(node) {
|
|
292
310
|
return {
|
|
293
|
-
|
|
294
|
-
y: node.position.y,
|
|
311
|
+
height: node.measured?.height ?? DEFAULT_NODE_HEIGHT,
|
|
295
312
|
width: node.measured?.width ?? DEFAULT_NODE_WIDTH,
|
|
296
|
-
|
|
313
|
+
x: node.position.x,
|
|
314
|
+
y: node.position.y
|
|
297
315
|
};
|
|
298
316
|
}
|
|
299
317
|
function getInputHandleIndex(nodeType, handleId) {
|
|
@@ -334,11 +352,14 @@ function reorderByHandlePosition(nodes, edges) {
|
|
|
334
352
|
for (const edge of targetEdges) {
|
|
335
353
|
const sourceNode = nodeMap.get(edge.source);
|
|
336
354
|
if (!sourceNode) continue;
|
|
337
|
-
const handleIndex = getInputHandleIndex(
|
|
355
|
+
const handleIndex = getInputHandleIndex(
|
|
356
|
+
targetNode.type,
|
|
357
|
+
edge.targetHandle ?? ""
|
|
358
|
+
);
|
|
338
359
|
sourceInfos.push({
|
|
339
|
-
|
|
360
|
+
currentY: sourceNode.position.y,
|
|
340
361
|
handleIndex,
|
|
341
|
-
|
|
362
|
+
nodeId: edge.source
|
|
342
363
|
});
|
|
343
364
|
}
|
|
344
365
|
if (sourceInfos.length < 2) continue;
|
|
@@ -403,18 +424,18 @@ function getLayoutedNodes(nodes, edges, options = {}) {
|
|
|
403
424
|
const { direction = "LR", nodeSpacing = 50, rankSpacing = 120 } = options;
|
|
404
425
|
const graph = new Dagre.graphlib.Graph().setDefaultEdgeLabel(() => ({}));
|
|
405
426
|
graph.setGraph({
|
|
406
|
-
|
|
407
|
-
nodesep: nodeSpacing,
|
|
408
|
-
ranksep: rankSpacing,
|
|
427
|
+
acyclicer: "greedy",
|
|
409
428
|
marginx: 50,
|
|
410
429
|
marginy: 50,
|
|
430
|
+
nodesep: nodeSpacing,
|
|
431
|
+
rankdir: direction,
|
|
411
432
|
ranker: "network-simplex",
|
|
412
|
-
|
|
433
|
+
ranksep: rankSpacing
|
|
413
434
|
});
|
|
414
435
|
for (const node of nodes) {
|
|
415
436
|
const width = node.measured?.width ?? DEFAULT_NODE_WIDTH;
|
|
416
437
|
const height = node.measured?.height ?? DEFAULT_NODE_HEIGHT;
|
|
417
|
-
graph.setNode(node.id, {
|
|
438
|
+
graph.setNode(node.id, { height, width });
|
|
418
439
|
}
|
|
419
440
|
for (const edge of edges) {
|
|
420
441
|
graph.setEdge(edge.source, edge.target);
|
|
@@ -442,7 +463,10 @@ function usePaneActions() {
|
|
|
442
463
|
const reactFlow = useReactFlow();
|
|
443
464
|
const addNodeAtPosition = useCallback(
|
|
444
465
|
(type, screenX, screenY) => {
|
|
445
|
-
const position = reactFlow.screenToFlowPosition({
|
|
466
|
+
const position = reactFlow.screenToFlowPosition({
|
|
467
|
+
x: screenX,
|
|
468
|
+
y: screenY
|
|
469
|
+
});
|
|
446
470
|
addNode(type, position);
|
|
447
471
|
},
|
|
448
472
|
[addNode, reactFlow]
|
|
@@ -463,7 +487,9 @@ function usePaneActions() {
|
|
|
463
487
|
const edgeStyle = useSettingsStore.getState().edgeStyle;
|
|
464
488
|
const currentNodes = reactFlow.getNodes();
|
|
465
489
|
const currentEdges = reactFlow.getEdges();
|
|
466
|
-
const layoutedNodes = getLayoutedNodes(currentNodes, currentEdges, {
|
|
490
|
+
const layoutedNodes = getLayoutedNodes(currentNodes, currentEdges, {
|
|
491
|
+
direction
|
|
492
|
+
});
|
|
467
493
|
reactFlow.setNodes(layoutedNodes);
|
|
468
494
|
reactFlow.setEdges(
|
|
469
495
|
(eds) => eds.map((edge) => ({
|
|
@@ -479,18 +505,21 @@ function usePaneActions() {
|
|
|
479
505
|
);
|
|
480
506
|
return {
|
|
481
507
|
addNodeAtPosition,
|
|
482
|
-
|
|
508
|
+
autoLayout,
|
|
483
509
|
fitView,
|
|
484
|
-
|
|
510
|
+
selectAll
|
|
485
511
|
};
|
|
486
512
|
}
|
|
487
|
-
function getEdgeMenuItems({
|
|
513
|
+
function getEdgeMenuItems({
|
|
514
|
+
edgeId,
|
|
515
|
+
onDelete
|
|
516
|
+
}) {
|
|
488
517
|
return [
|
|
489
518
|
{
|
|
519
|
+
danger: true,
|
|
520
|
+
icon: /* @__PURE__ */ jsx(Trash2, { className: "w-4 h-4" }),
|
|
490
521
|
id: "delete",
|
|
491
522
|
label: "Delete Connection",
|
|
492
|
-
icon: /* @__PURE__ */ jsx(Trash2, { className: "w-4 h-4" }),
|
|
493
|
-
danger: true,
|
|
494
523
|
onClick: () => onDelete(edgeId)
|
|
495
524
|
}
|
|
496
525
|
];
|
|
@@ -730,28 +759,38 @@ function ContextMenu({ x, y, items, onClose }) {
|
|
|
730
759
|
);
|
|
731
760
|
}
|
|
732
761
|
var NODE_COLOR_VALUES = {
|
|
733
|
-
none: null,
|
|
734
|
-
purple: "#a855f7",
|
|
735
762
|
blue: "#3b82f6",
|
|
763
|
+
gray: "#6b7280",
|
|
736
764
|
green: "#22c55e",
|
|
737
|
-
|
|
765
|
+
none: null,
|
|
738
766
|
orange: "#f97316",
|
|
739
|
-
red: "#ef4444",
|
|
740
767
|
pink: "#ec4899",
|
|
741
|
-
|
|
768
|
+
purple: "#a855f7",
|
|
769
|
+
red: "#ef4444",
|
|
770
|
+
yellow: "#eab308"
|
|
742
771
|
};
|
|
743
772
|
var NODE_COLOR_LABELS = {
|
|
744
|
-
none: "Default",
|
|
745
|
-
purple: "Purple",
|
|
746
773
|
blue: "Blue",
|
|
774
|
+
gray: "Gray",
|
|
747
775
|
green: "Green",
|
|
748
|
-
|
|
776
|
+
none: "Default",
|
|
749
777
|
orange: "Orange",
|
|
750
|
-
red: "Red",
|
|
751
778
|
pink: "Pink",
|
|
752
|
-
|
|
779
|
+
purple: "Purple",
|
|
780
|
+
red: "Red",
|
|
781
|
+
yellow: "Yellow"
|
|
753
782
|
};
|
|
754
|
-
var NODE_COLORS = [
|
|
783
|
+
var NODE_COLORS = [
|
|
784
|
+
"none",
|
|
785
|
+
"purple",
|
|
786
|
+
"blue",
|
|
787
|
+
"green",
|
|
788
|
+
"yellow",
|
|
789
|
+
"orange",
|
|
790
|
+
"red",
|
|
791
|
+
"pink",
|
|
792
|
+
"gray"
|
|
793
|
+
];
|
|
755
794
|
function getNodeMenuItems({
|
|
756
795
|
nodeId,
|
|
757
796
|
isLocked,
|
|
@@ -768,18 +807,18 @@ function getNodeMenuItems({
|
|
|
768
807
|
}) {
|
|
769
808
|
const items = [
|
|
770
809
|
{
|
|
810
|
+
icon: /* @__PURE__ */ jsx(Copy, { className: "w-4 h-4" }),
|
|
771
811
|
id: "duplicate",
|
|
772
812
|
label: "Duplicate",
|
|
773
|
-
|
|
774
|
-
shortcut: "\u2318D"
|
|
775
|
-
onClick: () => onDuplicate(nodeId)
|
|
813
|
+
onClick: () => onDuplicate(nodeId),
|
|
814
|
+
shortcut: "\u2318D"
|
|
776
815
|
}
|
|
777
816
|
];
|
|
778
817
|
if (hasMediaOutput && onSetAsThumbnail) {
|
|
779
818
|
items.push({
|
|
819
|
+
icon: /* @__PURE__ */ jsx(Image, { className: "w-4 h-4" }),
|
|
780
820
|
id: "setThumbnail",
|
|
781
821
|
label: "Set as Thumbnail",
|
|
782
|
-
icon: /* @__PURE__ */ jsx(Image, { className: "w-4 h-4" }),
|
|
783
822
|
onClick: () => onSetAsThumbnail(nodeId)
|
|
784
823
|
});
|
|
785
824
|
}
|
|
@@ -788,8 +827,6 @@ function getNodeMenuItems({
|
|
|
788
827
|
const colorValue = NODE_COLOR_VALUES[color];
|
|
789
828
|
const isSelected = colorValue === currentColor || color === "none" && !currentColor;
|
|
790
829
|
return {
|
|
791
|
-
id: `color-${color}`,
|
|
792
|
-
label: `${isSelected ? "\u2713 " : ""}${NODE_COLOR_LABELS[color]}`,
|
|
793
830
|
icon: /* @__PURE__ */ jsx(
|
|
794
831
|
"div",
|
|
795
832
|
{
|
|
@@ -797,100 +834,102 @@ function getNodeMenuItems({
|
|
|
797
834
|
style: { backgroundColor: colorValue || "transparent" }
|
|
798
835
|
}
|
|
799
836
|
),
|
|
837
|
+
id: `color-${color}`,
|
|
838
|
+
label: `${isSelected ? "\u2713 " : ""}${NODE_COLOR_LABELS[color]}`,
|
|
800
839
|
onClick: () => onSetColor(nodeId, colorValue)
|
|
801
840
|
};
|
|
802
841
|
});
|
|
803
842
|
items.push({
|
|
843
|
+
icon: /* @__PURE__ */ jsx(Palette, { className: "w-4 h-4" }),
|
|
804
844
|
id: "setColor",
|
|
805
845
|
label: "Set Color",
|
|
806
|
-
icon: /* @__PURE__ */ jsx(Palette, { className: "w-4 h-4" }),
|
|
807
846
|
submenu: colorSubmenu
|
|
808
847
|
});
|
|
809
848
|
}
|
|
810
849
|
items.push(createSeparator("separator-1"));
|
|
811
850
|
items.push(
|
|
812
851
|
isLocked ? {
|
|
852
|
+
icon: /* @__PURE__ */ jsx(LockOpen, { className: "w-4 h-4" }),
|
|
813
853
|
id: "unlock",
|
|
814
854
|
label: "Unlock Node",
|
|
815
|
-
|
|
816
|
-
shortcut: "L"
|
|
817
|
-
onClick: () => onUnlock(nodeId)
|
|
855
|
+
onClick: () => onUnlock(nodeId),
|
|
856
|
+
shortcut: "L"
|
|
818
857
|
} : {
|
|
858
|
+
icon: /* @__PURE__ */ jsx(Lock, { className: "w-4 h-4" }),
|
|
819
859
|
id: "lock",
|
|
820
860
|
label: "Lock Node",
|
|
821
|
-
|
|
822
|
-
shortcut: "L"
|
|
823
|
-
onClick: () => onLock(nodeId)
|
|
861
|
+
onClick: () => onLock(nodeId),
|
|
862
|
+
shortcut: "L"
|
|
824
863
|
}
|
|
825
864
|
);
|
|
826
865
|
items.push(createSeparator("separator-2"));
|
|
827
866
|
items.push(
|
|
828
867
|
{
|
|
868
|
+
icon: /* @__PURE__ */ jsx(Scissors, { className: "w-4 h-4" }),
|
|
829
869
|
id: "cut",
|
|
830
870
|
label: "Cut",
|
|
831
|
-
|
|
832
|
-
shortcut: "\u2318X"
|
|
833
|
-
onClick: () => onCut(nodeId)
|
|
871
|
+
onClick: () => onCut(nodeId),
|
|
872
|
+
shortcut: "\u2318X"
|
|
834
873
|
},
|
|
835
874
|
{
|
|
875
|
+
icon: /* @__PURE__ */ jsx(Copy, { className: "w-4 h-4" }),
|
|
836
876
|
id: "copy",
|
|
837
877
|
label: "Copy",
|
|
838
|
-
|
|
839
|
-
shortcut: "\u2318C"
|
|
840
|
-
onClick: () => onCopy(nodeId)
|
|
878
|
+
onClick: () => onCopy(nodeId),
|
|
879
|
+
shortcut: "\u2318C"
|
|
841
880
|
}
|
|
842
881
|
);
|
|
843
882
|
items.push(createSeparator("separator-3"));
|
|
844
883
|
items.push({
|
|
884
|
+
danger: true,
|
|
885
|
+
icon: /* @__PURE__ */ jsx(Trash2, { className: "w-4 h-4" }),
|
|
845
886
|
id: "delete",
|
|
846
887
|
label: "Delete",
|
|
847
|
-
|
|
848
|
-
shortcut: "\u232B"
|
|
849
|
-
danger: true,
|
|
850
|
-
onClick: () => onDelete(nodeId)
|
|
888
|
+
onClick: () => onDelete(nodeId),
|
|
889
|
+
shortcut: "\u232B"
|
|
851
890
|
});
|
|
852
891
|
return items;
|
|
853
892
|
}
|
|
854
893
|
var NODE_ICONS = {
|
|
855
|
-
|
|
856
|
-
|
|
894
|
+
ArrowLeftFromLine,
|
|
895
|
+
ArrowRightToLine,
|
|
896
|
+
AudioLines,
|
|
897
|
+
Brain,
|
|
898
|
+
CheckCircle,
|
|
899
|
+
Crop,
|
|
857
900
|
FileText,
|
|
858
|
-
Volume2,
|
|
859
901
|
FileVideo,
|
|
860
|
-
Sparkles,
|
|
861
|
-
Video,
|
|
862
|
-
Brain,
|
|
863
|
-
Mic,
|
|
864
|
-
AudioLines,
|
|
865
|
-
Navigation,
|
|
866
|
-
Maximize2,
|
|
867
|
-
Wand2,
|
|
868
|
-
Layers,
|
|
869
|
-
Scissors: Scissors,
|
|
870
902
|
Film,
|
|
871
|
-
|
|
872
|
-
Maximize,
|
|
903
|
+
GitBranch,
|
|
873
904
|
Grid3X3,
|
|
905
|
+
Image: Image,
|
|
906
|
+
Layers,
|
|
907
|
+
Maximize,
|
|
908
|
+
Maximize2,
|
|
909
|
+
MessageSquare,
|
|
910
|
+
Mic,
|
|
911
|
+
Navigation,
|
|
874
912
|
Pencil,
|
|
913
|
+
Scissors: Scissors,
|
|
914
|
+
Sparkles,
|
|
875
915
|
Subtitles,
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
GitBranch
|
|
916
|
+
Video,
|
|
917
|
+
Volume2,
|
|
918
|
+
Wand2
|
|
880
919
|
};
|
|
881
920
|
var CATEGORY_LABELS = {
|
|
882
|
-
input: "Input",
|
|
883
921
|
ai: "AI Generation",
|
|
884
|
-
|
|
922
|
+
composition: "Composition",
|
|
923
|
+
input: "Input",
|
|
885
924
|
output: "Output",
|
|
886
|
-
|
|
925
|
+
processing: "Processing"
|
|
887
926
|
};
|
|
888
927
|
var CATEGORY_ICONS = {
|
|
889
|
-
input: Image,
|
|
890
928
|
ai: Sparkles,
|
|
891
|
-
|
|
929
|
+
composition: GitBranch,
|
|
930
|
+
input: Image,
|
|
892
931
|
output: Monitor,
|
|
893
|
-
|
|
932
|
+
processing: Wand2
|
|
894
933
|
};
|
|
895
934
|
function getPaneMenuItems({
|
|
896
935
|
screenX,
|
|
@@ -908,15 +947,15 @@ function getPaneMenuItems({
|
|
|
908
947
|
const CategoryIcon = CATEGORY_ICONS[category];
|
|
909
948
|
const nodes = nodesByCategory[category];
|
|
910
949
|
return {
|
|
950
|
+
icon: /* @__PURE__ */ jsx(CategoryIcon, { className: "w-4 h-4" }),
|
|
911
951
|
id: `add-${category}`,
|
|
912
952
|
label: CATEGORY_LABELS[category],
|
|
913
|
-
icon: /* @__PURE__ */ jsx(CategoryIcon, { className: "w-4 h-4" }),
|
|
914
953
|
submenu: nodes.map((node) => {
|
|
915
954
|
const NodeIcon = NODE_ICONS[node.icon] ?? Sparkles;
|
|
916
955
|
return {
|
|
956
|
+
icon: /* @__PURE__ */ jsx(NodeIcon, { className: "w-4 h-4" }),
|
|
917
957
|
id: `add-${node.type}`,
|
|
918
958
|
label: node.label,
|
|
919
|
-
icon: /* @__PURE__ */ jsx(NodeIcon, { className: "w-4 h-4" }),
|
|
920
959
|
onClick: () => onAddNode(node.type, screenX, screenY)
|
|
921
960
|
};
|
|
922
961
|
})
|
|
@@ -926,33 +965,33 @@ function getPaneMenuItems({
|
|
|
926
965
|
...addNodeItems,
|
|
927
966
|
createSeparator("separator-1"),
|
|
928
967
|
{
|
|
968
|
+
disabled: !hasClipboard,
|
|
969
|
+
icon: /* @__PURE__ */ jsx(Clipboard, { className: "w-4 h-4" }),
|
|
929
970
|
id: "paste",
|
|
930
971
|
label: "Paste",
|
|
931
|
-
|
|
932
|
-
shortcut: "\u2318V"
|
|
933
|
-
disabled: !hasClipboard,
|
|
934
|
-
onClick: onPaste
|
|
972
|
+
onClick: onPaste,
|
|
973
|
+
shortcut: "\u2318V"
|
|
935
974
|
},
|
|
936
975
|
createSeparator("separator-2"),
|
|
937
976
|
{
|
|
938
977
|
id: "select-all",
|
|
939
978
|
label: "Select All",
|
|
940
|
-
|
|
941
|
-
|
|
979
|
+
onClick: onSelectAll,
|
|
980
|
+
shortcut: "\u2318A"
|
|
942
981
|
},
|
|
943
982
|
{
|
|
983
|
+
icon: /* @__PURE__ */ jsx(Maximize, { className: "w-4 h-4" }),
|
|
944
984
|
id: "fit-view",
|
|
945
985
|
label: "Fit View",
|
|
946
|
-
|
|
947
|
-
shortcut: "F"
|
|
948
|
-
onClick: onFitView
|
|
986
|
+
onClick: onFitView,
|
|
987
|
+
shortcut: "F"
|
|
949
988
|
},
|
|
950
989
|
{
|
|
990
|
+
icon: /* @__PURE__ */ jsx(LayoutGrid, { className: "w-4 h-4" }),
|
|
951
991
|
id: "auto-layout",
|
|
952
992
|
label: "Auto-layout Nodes",
|
|
953
|
-
|
|
954
|
-
shortcut: "L"
|
|
955
|
-
onClick: onAutoLayout
|
|
993
|
+
onClick: onAutoLayout,
|
|
994
|
+
shortcut: "L"
|
|
956
995
|
}
|
|
957
996
|
];
|
|
958
997
|
}
|
|
@@ -969,54 +1008,54 @@ function getSelectionMenuItems({
|
|
|
969
1008
|
const count = nodeIds.length;
|
|
970
1009
|
return [
|
|
971
1010
|
{
|
|
1011
|
+
icon: /* @__PURE__ */ jsx(Group, { className: "w-4 h-4" }),
|
|
972
1012
|
id: "group",
|
|
973
1013
|
label: "Create Group",
|
|
974
|
-
|
|
975
|
-
shortcut: "\u2318G"
|
|
976
|
-
onClick: () => onGroup(nodeIds)
|
|
1014
|
+
onClick: () => onGroup(nodeIds),
|
|
1015
|
+
shortcut: "\u2318G"
|
|
977
1016
|
},
|
|
978
1017
|
{
|
|
1018
|
+
icon: /* @__PURE__ */ jsx(Copy, { className: "w-4 h-4" }),
|
|
979
1019
|
id: "duplicate-all",
|
|
980
1020
|
label: `Duplicate ${count} Nodes`,
|
|
981
|
-
|
|
982
|
-
shortcut: "\u2318D"
|
|
983
|
-
onClick: () => onDuplicateAll(nodeIds)
|
|
1021
|
+
onClick: () => onDuplicateAll(nodeIds),
|
|
1022
|
+
shortcut: "\u2318D"
|
|
984
1023
|
},
|
|
985
1024
|
createSeparator("separator-1"),
|
|
986
1025
|
{
|
|
1026
|
+
icon: /* @__PURE__ */ jsx(Lock, { className: "w-4 h-4" }),
|
|
987
1027
|
id: "lock-all",
|
|
988
1028
|
label: "Lock All",
|
|
989
|
-
|
|
990
|
-
shortcut: "L"
|
|
991
|
-
onClick: () => onLockAll(nodeIds)
|
|
1029
|
+
onClick: () => onLockAll(nodeIds),
|
|
1030
|
+
shortcut: "L"
|
|
992
1031
|
},
|
|
993
1032
|
{
|
|
1033
|
+
icon: /* @__PURE__ */ jsx(LockOpen, { className: "w-4 h-4" }),
|
|
994
1034
|
id: "unlock-all",
|
|
995
1035
|
label: "Unlock All",
|
|
996
|
-
icon: /* @__PURE__ */ jsx(LockOpen, { className: "w-4 h-4" }),
|
|
997
1036
|
onClick: () => onUnlockAll(nodeIds)
|
|
998
1037
|
},
|
|
999
1038
|
createSeparator("separator-2"),
|
|
1000
1039
|
{
|
|
1040
|
+
icon: /* @__PURE__ */ jsx(AlignHorizontalJustifyCenter, { className: "w-4 h-4" }),
|
|
1001
1041
|
id: "align-horizontal",
|
|
1002
1042
|
label: "Align Horizontally",
|
|
1003
|
-
icon: /* @__PURE__ */ jsx(AlignHorizontalJustifyCenter, { className: "w-4 h-4" }),
|
|
1004
1043
|
onClick: () => onAlignHorizontal(nodeIds)
|
|
1005
1044
|
},
|
|
1006
1045
|
{
|
|
1046
|
+
icon: /* @__PURE__ */ jsx(AlignVerticalJustifyCenter, { className: "w-4 h-4" }),
|
|
1007
1047
|
id: "align-vertical",
|
|
1008
1048
|
label: "Align Vertically",
|
|
1009
|
-
icon: /* @__PURE__ */ jsx(AlignVerticalJustifyCenter, { className: "w-4 h-4" }),
|
|
1010
1049
|
onClick: () => onAlignVertical(nodeIds)
|
|
1011
1050
|
},
|
|
1012
1051
|
createSeparator("separator-3"),
|
|
1013
1052
|
{
|
|
1053
|
+
danger: true,
|
|
1054
|
+
icon: /* @__PURE__ */ jsx(Trash2, { className: "w-4 h-4" }),
|
|
1014
1055
|
id: "delete-all",
|
|
1015
1056
|
label: `Delete ${count} Nodes`,
|
|
1016
|
-
|
|
1017
|
-
shortcut: "\u232B"
|
|
1018
|
-
danger: true,
|
|
1019
|
-
onClick: () => onDeleteAll(nodeIds)
|
|
1057
|
+
onClick: () => onDeleteAll(nodeIds),
|
|
1058
|
+
shortcut: "\u232B"
|
|
1020
1059
|
}
|
|
1021
1060
|
];
|
|
1022
1061
|
}
|
|
@@ -1057,30 +1096,30 @@ function useContextMenu() {
|
|
|
1057
1096
|
const { addNodeAtPosition, selectAll, fitView, autoLayout } = usePaneActions();
|
|
1058
1097
|
const reactFlow = useReactFlow();
|
|
1059
1098
|
const stableHandlersRef = useRef({
|
|
1060
|
-
|
|
1099
|
+
addNodeAtPosition,
|
|
1100
|
+
autoLayout,
|
|
1061
1101
|
copyNode,
|
|
1062
1102
|
cutNode,
|
|
1063
|
-
deleteNode,
|
|
1064
1103
|
deleteMultipleNodes,
|
|
1104
|
+
deleteNode,
|
|
1105
|
+
duplicate,
|
|
1065
1106
|
duplicateMultipleNodes,
|
|
1066
|
-
removeEdge,
|
|
1067
|
-
addNodeAtPosition,
|
|
1068
|
-
selectAll,
|
|
1069
1107
|
fitView,
|
|
1070
|
-
|
|
1108
|
+
removeEdge,
|
|
1109
|
+
selectAll
|
|
1071
1110
|
});
|
|
1072
1111
|
stableHandlersRef.current = {
|
|
1073
|
-
|
|
1112
|
+
addNodeAtPosition,
|
|
1113
|
+
autoLayout,
|
|
1074
1114
|
copyNode,
|
|
1075
1115
|
cutNode,
|
|
1076
|
-
deleteNode,
|
|
1077
1116
|
deleteMultipleNodes,
|
|
1117
|
+
deleteNode,
|
|
1118
|
+
duplicate,
|
|
1078
1119
|
duplicateMultipleNodes,
|
|
1079
|
-
removeEdge,
|
|
1080
|
-
addNodeAtPosition,
|
|
1081
|
-
selectAll,
|
|
1082
1120
|
fitView,
|
|
1083
|
-
|
|
1121
|
+
removeEdge,
|
|
1122
|
+
selectAll
|
|
1084
1123
|
};
|
|
1085
1124
|
const lockNode = useCallback(
|
|
1086
1125
|
(nodeId) => {
|
|
@@ -1168,7 +1207,14 @@ function useContextMenu() {
|
|
|
1168
1207
|
if (!pasteData) return;
|
|
1169
1208
|
addNodesAndEdges(pasteData.nodes, pasteData.edges);
|
|
1170
1209
|
setSelectedNodeIds(pasteData.nodes.map((n) => n.id));
|
|
1171
|
-
}, [
|
|
1210
|
+
}, [
|
|
1211
|
+
clipboard,
|
|
1212
|
+
position,
|
|
1213
|
+
reactFlow,
|
|
1214
|
+
getPasteData,
|
|
1215
|
+
addNodesAndEdges,
|
|
1216
|
+
setSelectedNodeIds
|
|
1217
|
+
]);
|
|
1172
1218
|
const setNodeColor = useCallback(
|
|
1173
1219
|
(nodeId, color) => {
|
|
1174
1220
|
updateNodeData(nodeId, { color: color || void 0 });
|
|
@@ -1210,18 +1256,18 @@ function useContextMenu() {
|
|
|
1210
1256
|
const nodeHasMediaOutput = hasMediaOutput(targetId);
|
|
1211
1257
|
const currentColor = node?.data?.color;
|
|
1212
1258
|
return getNodeMenuItems({
|
|
1213
|
-
nodeId: targetId,
|
|
1214
|
-
isLocked,
|
|
1215
|
-
hasMediaOutput: nodeHasMediaOutput,
|
|
1216
1259
|
currentColor,
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
onCut: handlers.cutNode,
|
|
1260
|
+
hasMediaOutput: nodeHasMediaOutput,
|
|
1261
|
+
isLocked,
|
|
1262
|
+
nodeId: targetId,
|
|
1221
1263
|
onCopy: handlers.copyNode,
|
|
1264
|
+
onCut: handlers.cutNode,
|
|
1222
1265
|
onDelete: handlers.deleteNode,
|
|
1266
|
+
onDuplicate: handlers.duplicate,
|
|
1267
|
+
onLock: lockNode,
|
|
1223
1268
|
onSetAsThumbnail: workflowId && workflowsApi ? setAsThumbnail : void 0,
|
|
1224
|
-
onSetColor: setNodeColor
|
|
1269
|
+
onSetColor: setNodeColor,
|
|
1270
|
+
onUnlock: unlockNode
|
|
1225
1271
|
});
|
|
1226
1272
|
}
|
|
1227
1273
|
case "edge":
|
|
@@ -1232,26 +1278,26 @@ function useContextMenu() {
|
|
|
1232
1278
|
});
|
|
1233
1279
|
case "pane":
|
|
1234
1280
|
return getPaneMenuItems({
|
|
1235
|
-
screenX: position.x,
|
|
1236
|
-
screenY: position.y,
|
|
1237
1281
|
hasClipboard: !!clipboard,
|
|
1238
1282
|
onAddNode: handlers.addNodeAtPosition,
|
|
1283
|
+
onAutoLayout: () => handlers.autoLayout("LR"),
|
|
1284
|
+
onFitView: handlers.fitView,
|
|
1239
1285
|
onPaste: pasteNodes,
|
|
1240
1286
|
onSelectAll: handlers.selectAll,
|
|
1241
|
-
|
|
1242
|
-
|
|
1287
|
+
screenX: position.x,
|
|
1288
|
+
screenY: position.y
|
|
1243
1289
|
});
|
|
1244
1290
|
case "selection":
|
|
1245
1291
|
if (!targetIds || targetIds.length === 0) return [];
|
|
1246
1292
|
return getSelectionMenuItems({
|
|
1247
1293
|
nodeIds: targetIds,
|
|
1248
|
-
onGroup: groupNodes,
|
|
1249
|
-
onDuplicateAll: handlers.duplicateMultipleNodes,
|
|
1250
|
-
onLockAll: lockAllNodes,
|
|
1251
|
-
onUnlockAll: unlockAllNodes,
|
|
1252
1294
|
onAlignHorizontal: alignNodesHorizontally,
|
|
1253
1295
|
onAlignVertical: alignNodesVertically,
|
|
1254
|
-
onDeleteAll: handlers.deleteMultipleNodes
|
|
1296
|
+
onDeleteAll: handlers.deleteMultipleNodes,
|
|
1297
|
+
onDuplicateAll: handlers.duplicateMultipleNodes,
|
|
1298
|
+
onGroup: groupNodes,
|
|
1299
|
+
onLockAll: lockAllNodes,
|
|
1300
|
+
onUnlockAll: unlockAllNodes
|
|
1255
1301
|
});
|
|
1256
1302
|
default:
|
|
1257
1303
|
return [];
|
|
@@ -1279,15 +1325,15 @@ function useContextMenu() {
|
|
|
1279
1325
|
]);
|
|
1280
1326
|
const menuItems = useMemo(() => getMenuItems(), [getMenuItems]);
|
|
1281
1327
|
return {
|
|
1328
|
+
close,
|
|
1282
1329
|
isOpen,
|
|
1283
|
-
position,
|
|
1284
|
-
menuType,
|
|
1285
1330
|
menuItems,
|
|
1286
|
-
|
|
1331
|
+
menuType,
|
|
1287
1332
|
openEdgeMenu,
|
|
1333
|
+
openNodeMenu,
|
|
1288
1334
|
openPaneMenu,
|
|
1289
1335
|
openSelectionMenu,
|
|
1290
|
-
|
|
1336
|
+
position
|
|
1291
1337
|
};
|
|
1292
1338
|
}
|
|
1293
1339
|
|