@@ -10,7 +10,7 @@ import {
1010 TotalVsMinorityOverlay ,
1111 FoldsVsMinorityOverlay
1212} from './components/ChartOverlays' ;
13- import { FlaskConical , ChevronDown , ChevronUp , MousePointerClick , Layers , Info , Github , Heart } from 'lucide-react' ;
13+ import { FlaskConical , ChevronDown , ChevronUp , MousePointerClick , Layers , Info , Github , Heart , Quote , Check , Copy } from 'lucide-react' ;
1414
1515// --- Static Configurations ---
1616
@@ -57,6 +57,86 @@ const MissionBrief = () => {
5757 ) ;
5858} ;
5959
60+ const CitationButton = ( ) => {
61+ const [ copiedBib , setCopiedBib ] = useState ( false ) ;
62+ const [ copiedAPA , setCopiedAPA ] = useState ( false ) ;
63+
64+ const handleCopy = ( text : string , type : 'bib' | 'apa' ) => {
65+ navigator . clipboard . writeText ( text ) ;
66+ if ( type === 'bib' ) {
67+ setCopiedBib ( true ) ;
68+ setTimeout ( ( ) => setCopiedBib ( false ) , 2000 ) ;
69+ } else {
70+ setCopiedAPA ( true ) ;
71+ setTimeout ( ( ) => setCopiedAPA ( false ) , 2000 ) ;
72+ }
73+ } ;
74+
75+ const bibtex = `@software{ResampleLab2025,
76+ author = {mr-september},
77+ title = {Resample Lab: Advanced Data Resampling Heuristics},
78+ year = {2025},
79+ publisher = {GitHub},
80+ journal = {GitHub repository},
81+ howpublished = {\\url{https://github.com/mr-september/Resample-Lab}}
82+ }` ;
83+
84+ const apa = `mr-september. (2025). Resample Lab: Advanced Data Resampling Heuristics [Computer software]. GitHub. https://github.com/mr-september/Resample-Lab` ;
85+
86+ return (
87+ < div className = "relative group" >
88+ < button
89+ className = "text-zinc-500 hover:text-indigo-400 transition-colors"
90+ aria-label = "Cite this Lab"
91+ >
92+ < Quote className = "w-5 h-5" />
93+ </ button >
94+
95+ < div className = "absolute top-full right-0 mt-4 w-96 p-4 bg-[#09090b] border border-zinc-800 rounded-xl shadow-2xl opacity-0 invisible group-hover:opacity-100 group-hover:visible transition-all duration-200 transform origin-top translate-y-2 group-hover:translate-y-0 z-50" >
96+ < div className = "text-[10px] text-zinc-500 font-bold uppercase tracking-wider mb-3" >
97+ Cite Resample Lab
98+ </ div >
99+
100+ < div className = "space-y-4" >
101+ { /* BibTeX */ }
102+ < div className = "space-y-1.5" >
103+ < div className = "flex items-center justify-between" >
104+ < span className = "text-xs text-zinc-400" > BibTeX</ span >
105+ < button
106+ onClick = { ( ) => handleCopy ( bibtex , 'bib' ) }
107+ className = "flex items-center gap-1.5 text-[10px] text-zinc-500 hover:text-indigo-400 transition-colors"
108+ >
109+ { copiedBib ? < Check className = "w-3 h-3" /> : < Copy className = "w-3 h-3" /> }
110+ { copiedBib ? 'Copied!' : 'Copy' }
111+ </ button >
112+ </ div >
113+ < pre className = "text-[10px] leading-relaxed p-2 bg-zinc-900/50 rounded-lg border border-zinc-800 text-zinc-400 overflow-x-auto text-left" >
114+ { bibtex }
115+ </ pre >
116+ </ div >
117+
118+ { /* APA */ }
119+ < div className = "space-y-1.5" >
120+ < div className = "flex items-center justify-between" >
121+ < span className = "text-xs text-zinc-400" > APA</ span >
122+ < button
123+ onClick = { ( ) => handleCopy ( apa , 'apa' ) }
124+ className = "flex items-center gap-1.5 text-[10px] text-zinc-500 hover:text-indigo-400 transition-colors"
125+ >
126+ { copiedAPA ? < Check className = "w-3 h-3" /> : < Copy className = "w-3 h-3" /> }
127+ { copiedAPA ? 'Copied!' : 'Copy' }
128+ </ button >
129+ </ div >
130+ < div className = "text-[10px] leading-relaxed p-2 bg-zinc-900/50 rounded-lg border border-zinc-800 text-zinc-400 text-left" >
131+ { apa }
132+ </ div >
133+ </ div >
134+ </ div >
135+ </ div >
136+ </ div >
137+ ) ;
138+ } ;
139+
60140function App ( ) {
61141 const [ params , setParams ] = useState < DatasetParams > ( {
62142 features : 50 ,
@@ -154,6 +234,9 @@ function App() {
154234 ) ) }
155235 </ div >
156236
237+ { /* Citation */ }
238+ < CitationButton />
239+
157240 { /* GitHub Link */ }
158241 < a
159242 href = "https://github.com/mr-september/Resample-Lab"
0 commit comments