@@ -33,6 +33,9 @@ import { useDarkMode } from "usehooks-ts";
33
33
34
34
import { VisualNodeEditorProvider } from "../visual-node-editor/VisualNodeEditorContext" ;
35
35
import { AiCompletionContext , AiCompletionProvider } from "@flyde/ui" ;
36
+ import { VisualNodeDiffView } from "../visual-node-editor/VisualNodeDiffView" ;
37
+ import { Dialog , DialogContent } from "@flyde/ui" ;
38
+ import { Button } from "@flyde/ui" ;
36
39
37
40
export * from "./ports" ;
38
41
export * from "./DebuggerContext" ;
@@ -57,6 +60,8 @@ export type FlydeFlowEditorProps = {
57
60
58
61
initialPadding ?: [ number , number ] ;
59
62
darkMode ?: boolean ;
63
+
64
+ comparisonNode ?: VisualNode ;
60
65
} ;
61
66
62
67
const maxUndoStackSize = 50 ;
@@ -230,6 +235,13 @@ export const FlowEditor: React.FC<FlydeFlowEditorProps> = React.memo(
230
235
} ;
231
236
} , [ createAiCompletion ] ) ;
232
237
238
+ const [ isDiffViewOpen , setIsDiffViewOpen ] = React . useState ( false ) ;
239
+
240
+ // Add a button to toggle the diff view
241
+ const toggleDiffView = React . useCallback ( ( ) => {
242
+ setIsDiffViewOpen ( ( prev ) => ! prev ) ;
243
+ } , [ ] ) ;
244
+
233
245
const renderInner = ( ) => {
234
246
return (
235
247
< DarkModeProvider value = { props . darkMode ?? isDarkMode } >
@@ -262,6 +274,86 @@ export const FlowEditor: React.FC<FlydeFlowEditorProps> = React.memo(
262
274
initialPadding = { props . initialPadding }
263
275
instancesWithErrors = { instancesWithErrors }
264
276
/>
277
+ { /* <VisualNodeDiffView
278
+ node={editedNode}
279
+ currentInsId={ROOT_INS_ID}
280
+ className="w-full h-full"
281
+ /> */ }
282
+
283
+ < Button
284
+ variant = "outline"
285
+ className = "fixed top-4 right-4 z-50"
286
+ onClick = { toggleDiffView }
287
+ >
288
+ Toggle Diff View
289
+ </ Button >
290
+
291
+ < Dialog open = { isDiffViewOpen } onOpenChange = { setIsDiffViewOpen } >
292
+ < DialogContent className = "max-w-[90vw] max-h-[90vh] w-[1200px] h-[800px]" >
293
+ < VisualNodeDiffView
294
+ node = { editedNode }
295
+ comparisonNode = { {
296
+ ...editedNode ,
297
+ instances : [
298
+ // Keep all instances except the first one in their original positions
299
+ ...editedNode . instances . slice ( 1 ) ,
300
+ // Add a new instance based on an existing one (should show as "added")
301
+ ...( editedNode . instances . length > 0
302
+ ? [
303
+ {
304
+ ...editedNode . instances [ 0 ] ,
305
+ id : "cloned-instance" ,
306
+ pos : {
307
+ x : editedNode . instances [ 0 ] . pos . x + 200 ,
308
+ y : editedNode . instances [ 0 ] . pos . y ,
309
+ } ,
310
+ } ,
311
+ ]
312
+ : [ ] ) ,
313
+ ] ,
314
+ // Add test connections to show different states
315
+ connections : [
316
+ // Keep only some existing connections (others will show as removed)
317
+ ...editedNode . connections . filter ( ( _ , i ) => i > 0 ) , // Remove first connection to show as removed
318
+ // Add a new connection between existing instances (will show as added)
319
+ ...( editedNode . instances . length > 1
320
+ ? [
321
+ {
322
+ from : {
323
+ insId : editedNode . instances [ 1 ] . id ,
324
+ pinId :
325
+ Object . keys (
326
+ editedNode . instances [ 1 ] . inputConfig
327
+ ) [ 0 ] || "value" ,
328
+ } ,
329
+ to : {
330
+ insId : editedNode . instances [ 0 ] . id ,
331
+ pinId : "value" ,
332
+ } ,
333
+ } ,
334
+ // Add another connection to the cloned instance
335
+ {
336
+ from : {
337
+ insId : editedNode . instances [ 1 ] . id ,
338
+ pinId :
339
+ Object . keys (
340
+ editedNode . instances [ 1 ] . inputConfig
341
+ ) [ 0 ] || "value" ,
342
+ } ,
343
+ to : {
344
+ insId : "cloned-instance" ,
345
+ pinId : "value" ,
346
+ } ,
347
+ } ,
348
+ ]
349
+ : [ ] ) ,
350
+ ] ,
351
+ } }
352
+ currentInsId = { ROOT_INS_ID + "diff" }
353
+ className = "w-full h-full"
354
+ />
355
+ </ DialogContent >
356
+ </ Dialog >
265
357
</ React . Fragment >
266
358
</ VisualNodeEditorProvider >
267
359
</ AiCompletionProvider >
0 commit comments