feature: implement cut and paste functionality (closes #8)
- Add CutStore (Zustand) to store cut node IDs, node data, edges, and source graph ID - Update graphToDot() to render cut nodes with dashed grey style for visual indication - Add 'Cut' action to node context menu; 'Paste' action to empty-area context menu - Cut logic: captures selected nodes (or right-clicked node if none selected) plus all nodes reachable by outgoing edges from those nodes; clears selection afterwards - Paste logic: adds cut nodes/edges to target graph, removes them from source graph in GraphsStore; pasting on the same graph as the cut source cancels the cut - Graph re-renders automatically when cutNodeIds changes via useCutStore subscription - Clear cut store on file load for consistency - Add E2E tests covering: Cut menu visibility, Paste menu visibility, cut styling, linked-node inclusion, cross-subgraph paste, source-graph cleanup, same-graph cancel Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import type { GraphModel } from "./components/Graph";
|
||||
|
||||
export function graphToDot(g: GraphModel): string {
|
||||
export function graphToDot(g: GraphModel, cutNodeIds: Set<string> = new Set()): string {
|
||||
// Directed graph, use neato layout so we can use pos attributes
|
||||
const lines = [];
|
||||
lines.push('digraph G {');
|
||||
@@ -12,6 +12,9 @@ export function graphToDot(g: GraphModel): string {
|
||||
const attrs = [];
|
||||
attrs.push(`label=\"${n.label}\"`);
|
||||
attrs.push(`id=\"${n.id}\"`)
|
||||
if (cutNodeIds.has(n.id)) {
|
||||
attrs.push(`fillcolor="#d9d9d9"`, `style="filled,dashed"`);
|
||||
}
|
||||
lines.push(` \"${n.id}\" [${attrs.join(', ')}];`);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user