@bian-womp/spark-workbench 0.2.64 → 0.2.65
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/lib/cjs/index.cjs +147 -1
- package/lib/cjs/index.cjs.map +1 -1
- package/lib/cjs/src/core/InMemoryWorkbench.d.ts +50 -1
- package/lib/cjs/src/core/InMemoryWorkbench.d.ts.map +1 -1
- package/lib/cjs/src/misc/context/ContextMenuHelpers.d.ts.map +1 -1
- package/lib/esm/index.js +147 -1
- package/lib/esm/index.js.map +1 -1
- package/lib/esm/src/core/InMemoryWorkbench.d.ts +50 -1
- package/lib/esm/src/core/InMemoryWorkbench.d.ts.map +1 -1
- package/lib/esm/src/misc/context/ContextMenuHelpers.d.ts.map +1 -1
- package/package.json +4 -4
|
@@ -1,7 +1,34 @@
|
|
|
1
|
-
import type { GraphDefinition, GraphNodeDefinition, GraphEdgeDefinition } from "@bian-womp/spark-protocol";
|
|
1
|
+
import type { GraphDefinition, GraphNodeDefinition, GraphEdgeDefinition, ResolvedHandles } from "@bian-womp/spark-protocol";
|
|
2
2
|
import { Registry } from "@bian-womp/spark-graph";
|
|
3
3
|
import { AbstractWorkbench } from "./AbstractWorkbench";
|
|
4
4
|
import type { ValidationResult, WorkbenchEventName, WorkbenchEventListener } from "./contracts";
|
|
5
|
+
import type { IGraphRunner } from "../runtime/IGraphRunner";
|
|
6
|
+
export type CopiedGraphData = {
|
|
7
|
+
nodes: Array<{
|
|
8
|
+
typeId: string;
|
|
9
|
+
params?: Record<string, unknown>;
|
|
10
|
+
resolvedHandles?: Partial<ResolvedHandles>;
|
|
11
|
+
position: {
|
|
12
|
+
x: number;
|
|
13
|
+
y: number;
|
|
14
|
+
};
|
|
15
|
+
inputs?: Record<string, unknown>;
|
|
16
|
+
originalNodeId: string;
|
|
17
|
+
}>;
|
|
18
|
+
edges: Array<{
|
|
19
|
+
sourceNodeId: string;
|
|
20
|
+
sourceHandle: string;
|
|
21
|
+
targetNodeId: string;
|
|
22
|
+
targetHandle: string;
|
|
23
|
+
typeId?: string;
|
|
24
|
+
}>;
|
|
25
|
+
bounds: {
|
|
26
|
+
minX: number;
|
|
27
|
+
minY: number;
|
|
28
|
+
maxX: number;
|
|
29
|
+
maxY: number;
|
|
30
|
+
};
|
|
31
|
+
};
|
|
5
32
|
export declare class InMemoryWorkbench extends AbstractWorkbench {
|
|
6
33
|
private def;
|
|
7
34
|
private positions;
|
|
@@ -104,5 +131,27 @@ export declare class InMemoryWorkbench extends AbstractWorkbench {
|
|
|
104
131
|
}): void;
|
|
105
132
|
on<K extends WorkbenchEventName>(event: K, handler: WorkbenchEventListener<K>): () => void;
|
|
106
133
|
private emit;
|
|
134
|
+
/**
|
|
135
|
+
* Copy selected nodes and their internal edges.
|
|
136
|
+
* Returns data in a format suitable for pasting.
|
|
137
|
+
* Positions are normalized relative to the selection bounds center.
|
|
138
|
+
* Uses the same logic as duplicate: copies inputs without bindings and supports copyOutputsFrom.
|
|
139
|
+
*/
|
|
140
|
+
copySelection(runner: IGraphRunner, getNodeSize?: (nodeId: string, typeId: string) => {
|
|
141
|
+
width: number;
|
|
142
|
+
height: number;
|
|
143
|
+
} | undefined): CopiedGraphData | null;
|
|
144
|
+
/**
|
|
145
|
+
* Paste copied graph data at the specified center position.
|
|
146
|
+
* Returns the mapping from original node IDs to new node IDs.
|
|
147
|
+
* Uses copyOutputsFrom to copy outputs from original nodes (like duplicate does).
|
|
148
|
+
*/
|
|
149
|
+
pasteCopiedData(data: CopiedGraphData, center: {
|
|
150
|
+
x: number;
|
|
151
|
+
y: number;
|
|
152
|
+
}): {
|
|
153
|
+
nodeIdMap: Map<string, string>;
|
|
154
|
+
edgeIds: string[];
|
|
155
|
+
};
|
|
107
156
|
}
|
|
108
157
|
//# sourceMappingURL=InMemoryWorkbench.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InMemoryWorkbench.d.ts","sourceRoot":"","sources":["../../../../src/core/InMemoryWorkbench.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,eAAe,EACf,mBAAmB,EACnB,mBAAmB,
|
|
1
|
+
{"version":3,"file":"InMemoryWorkbench.d.ts","sourceRoot":"","sources":["../../../../src/core/InMemoryWorkbench.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ContextMenuHelpers.d.ts","sourceRoot":"","sources":["../../../../../src/misc/context/ContextMenuHelpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAMvD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACtE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC/D,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAErE,wBAAgB,6BAA6B,CAC3C,MAAM,EAAE,MAAM,EACd,EAAE,EAAE,iBAAiB,EACrB,MAAM,EAAE,YAAY,EACpB,QAAQ,EAAE,QAAQ,EAClB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EACnD,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,EAClE,OAAO,EAAE,MAAM,IAAI,GAClB,uBAAuB,
|
|
1
|
+
{"version":3,"file":"ContextMenuHelpers.d.ts","sourceRoot":"","sources":["../../../../../src/misc/context/ContextMenuHelpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAMvD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACtE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC/D,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAErE,wBAAgB,6BAA6B,CAC3C,MAAM,EAAE,MAAM,EACd,EAAE,EAAE,iBAAiB,EACrB,MAAM,EAAE,YAAY,EACpB,QAAQ,EAAE,QAAQ,EAClB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EACnD,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,EAClE,OAAO,EAAE,MAAM,IAAI,GAClB,uBAAuB,CAsMzB;AAED,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,MAAM,EACd,EAAE,EAAE,iBAAiB,EACrB,QAAQ,EAAE,QAAQ,EAClB,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,GACjE,MAAM,EAAE,CAgCV"}
|
package/lib/esm/index.js
CHANGED
|
@@ -365,6 +365,142 @@ class InMemoryWorkbench extends AbstractWorkbench {
|
|
|
365
365
|
for (const h of Array.from(set))
|
|
366
366
|
h(payload);
|
|
367
367
|
}
|
|
368
|
+
/**
|
|
369
|
+
* Copy selected nodes and their internal edges.
|
|
370
|
+
* Returns data in a format suitable for pasting.
|
|
371
|
+
* Positions are normalized relative to the selection bounds center.
|
|
372
|
+
* Uses the same logic as duplicate: copies inputs without bindings and supports copyOutputsFrom.
|
|
373
|
+
*/
|
|
374
|
+
copySelection(runner, getNodeSize) {
|
|
375
|
+
const selection = this.getSelection();
|
|
376
|
+
if (selection.nodes.length === 0)
|
|
377
|
+
return null;
|
|
378
|
+
const def = this.export();
|
|
379
|
+
const positions = this.getPositions();
|
|
380
|
+
const selectedNodeSet = new Set(selection.nodes);
|
|
381
|
+
// Collect nodes to copy
|
|
382
|
+
const nodesToCopy = def.nodes.filter((n) => selectedNodeSet.has(n.nodeId));
|
|
383
|
+
if (nodesToCopy.length === 0)
|
|
384
|
+
return null;
|
|
385
|
+
// Calculate bounds
|
|
386
|
+
let minX = Infinity;
|
|
387
|
+
let minY = Infinity;
|
|
388
|
+
let maxX = -Infinity;
|
|
389
|
+
let maxY = -Infinity;
|
|
390
|
+
nodesToCopy.forEach((node) => {
|
|
391
|
+
const pos = positions[node.nodeId] || { x: 0, y: 0 };
|
|
392
|
+
const size = getNodeSize?.(node.nodeId, node.typeId) || {
|
|
393
|
+
width: 200,
|
|
394
|
+
height: 100,
|
|
395
|
+
};
|
|
396
|
+
minX = Math.min(minX, pos.x);
|
|
397
|
+
minY = Math.min(minY, pos.y);
|
|
398
|
+
maxX = Math.max(maxX, pos.x + size.width);
|
|
399
|
+
maxY = Math.max(maxY, pos.y + size.height);
|
|
400
|
+
});
|
|
401
|
+
const bounds = { minX, minY, maxX, maxY };
|
|
402
|
+
const centerX = (bounds.minX + bounds.maxX) / 2;
|
|
403
|
+
const centerY = (bounds.minY + bounds.maxY) / 2;
|
|
404
|
+
// Get inputs for each node
|
|
405
|
+
// Include values from inbound edges if those edges are selected
|
|
406
|
+
const allInputs = runner.getInputs(def);
|
|
407
|
+
const selectedEdgeSet = new Set(selection.edges);
|
|
408
|
+
const copiedNodes = nodesToCopy.map((node) => {
|
|
409
|
+
const pos = positions[node.nodeId] || { x: 0, y: 0 };
|
|
410
|
+
// Get all inbound edges for this node
|
|
411
|
+
const inboundEdges = def.edges.filter((e) => e.target.nodeId === node.nodeId);
|
|
412
|
+
// Build set of handles that have inbound edges
|
|
413
|
+
// But only exclude handles whose edges are NOT selected
|
|
414
|
+
const inboundHandlesToExclude = new Set(inboundEdges
|
|
415
|
+
.filter((e) => !selectedEdgeSet.has(e.id)) // Only exclude if edge is not selected
|
|
416
|
+
.map((e) => e.target.handle));
|
|
417
|
+
const allNodeInputs = allInputs[node.nodeId] || {};
|
|
418
|
+
// Include inputs that either:
|
|
419
|
+
// 1. Don't have inbound edges (literal values)
|
|
420
|
+
// 2. Have inbound edges that ARE selected (preserve the value from the edge)
|
|
421
|
+
const inputsToCopy = Object.fromEntries(Object.entries(allNodeInputs).filter(([handle]) => !inboundHandlesToExclude.has(handle)));
|
|
422
|
+
return {
|
|
423
|
+
typeId: node.typeId,
|
|
424
|
+
params: node.params,
|
|
425
|
+
resolvedHandles: node.resolvedHandles,
|
|
426
|
+
position: {
|
|
427
|
+
x: pos.x - centerX,
|
|
428
|
+
y: pos.y - centerY,
|
|
429
|
+
},
|
|
430
|
+
inputs: inputsToCopy,
|
|
431
|
+
originalNodeId: node.nodeId,
|
|
432
|
+
};
|
|
433
|
+
});
|
|
434
|
+
// Collect edges between copied nodes
|
|
435
|
+
const copiedEdges = def.edges
|
|
436
|
+
.filter((edge) => {
|
|
437
|
+
return (selectedNodeSet.has(edge.source.nodeId) &&
|
|
438
|
+
selectedNodeSet.has(edge.target.nodeId));
|
|
439
|
+
})
|
|
440
|
+
.map((edge) => ({
|
|
441
|
+
sourceNodeId: edge.source.nodeId,
|
|
442
|
+
sourceHandle: edge.source.handle,
|
|
443
|
+
targetNodeId: edge.target.nodeId,
|
|
444
|
+
targetHandle: edge.target.handle,
|
|
445
|
+
typeId: edge.typeId,
|
|
446
|
+
}));
|
|
447
|
+
return {
|
|
448
|
+
nodes: copiedNodes,
|
|
449
|
+
edges: copiedEdges,
|
|
450
|
+
bounds,
|
|
451
|
+
};
|
|
452
|
+
}
|
|
453
|
+
/**
|
|
454
|
+
* Paste copied graph data at the specified center position.
|
|
455
|
+
* Returns the mapping from original node IDs to new node IDs.
|
|
456
|
+
* Uses copyOutputsFrom to copy outputs from original nodes (like duplicate does).
|
|
457
|
+
*/
|
|
458
|
+
pasteCopiedData(data, center) {
|
|
459
|
+
const nodeIdMap = new Map();
|
|
460
|
+
const edgeIds = [];
|
|
461
|
+
// Add nodes
|
|
462
|
+
for (const nodeData of data.nodes) {
|
|
463
|
+
const newNodeId = this.addNode({
|
|
464
|
+
typeId: nodeData.typeId,
|
|
465
|
+
params: nodeData.params,
|
|
466
|
+
resolvedHandles: nodeData.resolvedHandles,
|
|
467
|
+
position: {
|
|
468
|
+
x: nodeData.position.x + center.x,
|
|
469
|
+
y: nodeData.position.y + center.y,
|
|
470
|
+
},
|
|
471
|
+
}, {
|
|
472
|
+
inputs: nodeData.inputs,
|
|
473
|
+
copyOutputsFrom: nodeData.originalNodeId,
|
|
474
|
+
dry: true,
|
|
475
|
+
});
|
|
476
|
+
nodeIdMap.set(nodeData.originalNodeId, newNodeId);
|
|
477
|
+
}
|
|
478
|
+
// Add edges
|
|
479
|
+
for (const edgeData of data.edges) {
|
|
480
|
+
const newSourceNodeId = nodeIdMap.get(edgeData.sourceNodeId);
|
|
481
|
+
const newTargetNodeId = nodeIdMap.get(edgeData.targetNodeId);
|
|
482
|
+
if (newSourceNodeId && newTargetNodeId) {
|
|
483
|
+
const edgeId = this.connect({
|
|
484
|
+
source: {
|
|
485
|
+
nodeId: newSourceNodeId,
|
|
486
|
+
handle: edgeData.sourceHandle,
|
|
487
|
+
},
|
|
488
|
+
target: {
|
|
489
|
+
nodeId: newTargetNodeId,
|
|
490
|
+
handle: edgeData.targetHandle,
|
|
491
|
+
},
|
|
492
|
+
typeId: edgeData.typeId,
|
|
493
|
+
}, { dry: true });
|
|
494
|
+
edgeIds.push(edgeId);
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
// Select the newly pasted nodes
|
|
498
|
+
this.setSelection({
|
|
499
|
+
nodes: Array.from(nodeIdMap.values()),
|
|
500
|
+
edges: edgeIds,
|
|
501
|
+
});
|
|
502
|
+
return { nodeIdMap, edgeIds };
|
|
503
|
+
}
|
|
368
504
|
}
|
|
369
505
|
|
|
370
506
|
class CLIWorkbench {
|
|
@@ -3646,7 +3782,7 @@ function createNodeContextMenuHandlers(nodeId, wb, runner, registry, outputsMap,
|
|
|
3646
3782
|
.map((e) => e.target.handle));
|
|
3647
3783
|
const allInputs = runner.getInputs(def)[nodeId] || {};
|
|
3648
3784
|
const inputsWithoutBindings = Object.fromEntries(Object.entries(allInputs).filter(([handle]) => !inboundHandles.has(handle)));
|
|
3649
|
-
wb.addNode({
|
|
3785
|
+
const newNodeId = wb.addNode({
|
|
3650
3786
|
typeId: n.typeId,
|
|
3651
3787
|
params: n.params,
|
|
3652
3788
|
position: { x: pos.x + 24, y: pos.y + 24 },
|
|
@@ -3656,6 +3792,11 @@ function createNodeContextMenuHandlers(nodeId, wb, runner, registry, outputsMap,
|
|
|
3656
3792
|
copyOutputsFrom: nodeId,
|
|
3657
3793
|
dry: true,
|
|
3658
3794
|
});
|
|
3795
|
+
// Select the newly duplicated node
|
|
3796
|
+
wb.setSelection({
|
|
3797
|
+
nodes: [newNodeId],
|
|
3798
|
+
edges: [],
|
|
3799
|
+
});
|
|
3659
3800
|
onClose();
|
|
3660
3801
|
},
|
|
3661
3802
|
onDuplicateWithEdges: async () => {
|
|
@@ -3687,6 +3828,11 @@ function createNodeContextMenuHandlers(nodeId, wb, runner, registry, outputsMap,
|
|
|
3687
3828
|
typeId: edge.typeId,
|
|
3688
3829
|
}, { dry: true });
|
|
3689
3830
|
}
|
|
3831
|
+
// Select the newly duplicated node and edges
|
|
3832
|
+
wb.setSelection({
|
|
3833
|
+
nodes: [newNodeId],
|
|
3834
|
+
edges: [],
|
|
3835
|
+
});
|
|
3690
3836
|
onClose();
|
|
3691
3837
|
},
|
|
3692
3838
|
onRunPull: async () => {
|