1
+ "use client" ;
2
+
3
+ import { forwardRef , useRef } from "react" ;
4
+ import { cn } from "@/lib/utils" ;
5
+ import { AnimatedBeam } from "@/components/ui/animated-beam" ;
6
+ import {
7
+ TableProperties ,
8
+ FileSpreadsheet ,
9
+ Database ,
10
+ LineChart ,
11
+ Download ,
12
+ Image ,
13
+ Table ,
14
+ Globe2 ,
15
+ Dna ,
16
+ Scale ,
17
+ Scissors
18
+ } from "lucide-react" ;
19
+
20
+ const Circle = forwardRef <
21
+ HTMLDivElement ,
22
+ { className ?: string ; children ?: React . ReactNode ; label ?: string }
23
+ > ( ( { className, children, label } , ref ) => {
24
+ return (
25
+ < div className = "flex flex-col items-center gap-2" >
26
+ < div
27
+ ref = { ref }
28
+ className = { cn (
29
+ "z-10 flex size-12 items-center justify-center rounded-full bg-white/80 dark:bg-black/80 backdrop-blur-xl p-3" ,
30
+ className ,
31
+ ) }
32
+ >
33
+ { children }
34
+ </ div >
35
+ { label && < span className = "text-sm text-muted-foreground" > { label } </ span > }
36
+ </ div >
37
+ ) ;
38
+ } ) ;
39
+
40
+ Circle . displayName = "Circle" ;
41
+
42
+ export function DataFlowDiagram ( ) {
43
+ const containerRef = useRef < HTMLDivElement > ( null ) ;
44
+
45
+ // Required Input refs
46
+ const syntenyRef = useRef < HTMLDivElement > ( null ) ;
47
+ const speciesRef = useRef < HTMLDivElement > ( null ) ;
48
+ const chromosomeRef = useRef < HTMLDivElement > ( null ) ;
49
+
50
+ // Optional Input refs
51
+ const annotationsRef = useRef < HTMLDivElement > ( null ) ;
52
+ const breakpointRef = useRef < HTMLDivElement > ( null ) ;
53
+ const ncbiRef = useRef < HTMLDivElement > ( null ) ;
54
+
55
+ // Processing ref
56
+ const processingRef = useRef < HTMLDivElement > ( null ) ;
57
+
58
+ // Output refs
59
+ const plotRef = useRef < HTMLDivElement > ( null ) ;
60
+ const exportRef = useRef < HTMLDivElement > ( null ) ;
61
+
62
+ return (
63
+ < div className = "relative flex h-[600px] w-full items-center justify-center overflow-hidden" ref = { containerRef } >
64
+ < div className = "flex w-full max-w-5xl flex-col gap-20" >
65
+ { /* Input Layer - Split into Required and Optional */ }
66
+ < div className = "grid grid-cols-2 gap-x-20" >
67
+ { /* Required Inputs */ }
68
+ < div className = "flex flex-col gap-6" >
69
+ < span className = "text-sm font-medium text-muted-foreground text-center" > Required Input</ span >
70
+ < div className = "grid grid-cols-3 gap-4" >
71
+ < Circle ref = { syntenyRef } label = "Synteny Data" >
72
+ < TableProperties className = "h-6 w-6" />
73
+ </ Circle >
74
+ < Circle ref = { speciesRef } label = "Species Data" >
75
+ < Database className = "h-6 w-6" />
76
+ </ Circle >
77
+ < Circle ref = { chromosomeRef } label = "Chromosome Size" >
78
+ < Scale className = "h-6 w-6" />
79
+ </ Circle >
80
+ </ div >
81
+ </ div >
82
+
83
+ { /* Optional Inputs */ }
84
+ < div className = "flex flex-col gap-6" >
85
+ < span className = "text-sm font-medium text-muted-foreground text-center" > Optional Input</ span >
86
+ < div className = "grid grid-cols-3 gap-4" >
87
+ < Circle ref = { annotationsRef } label = "Gene Annotations" >
88
+ < Dna className = "h-6 w-6" />
89
+ </ Circle >
90
+ < Circle ref = { breakpointRef } label = "Breakpoint Data" >
91
+ < Scissors className = "h-6 w-6" />
92
+ </ Circle >
93
+ < Circle ref = { ncbiRef } label = "NCBI Database" >
94
+ < Globe2 className = "h-6 w-6" />
95
+ </ Circle >
96
+ </ div >
97
+ </ div >
98
+ </ div >
99
+
100
+ { /* Processing */ }
101
+ < div className = "flex items-center justify-center" >
102
+ < Circle ref = { processingRef } className = "size-20" label = "CHITRA Engine" >
103
+ < LineChart className = "h-8 w-8" />
104
+ </ Circle >
105
+ </ div >
106
+
107
+ { /* Output */ }
108
+ < div className = "flex justify-center gap-20" >
109
+ < Circle ref = { plotRef } label = "Interactive Plot" >
110
+ < Image className = "h-6 w-6" />
111
+ </ Circle >
112
+ < Circle ref = { exportRef } label = "Export Synteny" >
113
+ < Table className = "h-6 w-6" />
114
+ </ Circle >
115
+ </ div >
116
+ </ div >
117
+
118
+ { /* Connect Required Inputs to Processing */ }
119
+ < AnimatedBeam containerRef = { containerRef } fromRef = { syntenyRef } toRef = { processingRef } />
120
+ < AnimatedBeam containerRef = { containerRef } fromRef = { speciesRef } toRef = { processingRef } />
121
+ < AnimatedBeam containerRef = { containerRef } fromRef = { chromosomeRef } toRef = { processingRef } />
122
+
123
+ { /* Connect Optional Inputs */ }
124
+ < AnimatedBeam containerRef = { containerRef } fromRef = { annotationsRef } toRef = { ncbiRef } />
125
+ < AnimatedBeam containerRef = { containerRef } fromRef = { breakpointRef } toRef = { ncbiRef } />
126
+ < AnimatedBeam containerRef = { containerRef } fromRef = { ncbiRef } toRef = { processingRef } />
127
+
128
+ { /* Connect Processing to Output */ }
129
+ < AnimatedBeam containerRef = { containerRef } fromRef = { processingRef } toRef = { plotRef } />
130
+ < AnimatedBeam containerRef = { containerRef } fromRef = { processingRef } toRef = { exportRef } />
131
+ </ div >
132
+ ) ;
133
+ }
0 commit comments