11import { useEffect , useState , useMemo , useRef } from 'react' ;
22
33type TerminalExample = {
4+ name : string ;
45 lines : string [ ] ;
56 delay : number ; // Delay before starting next example
67} ;
@@ -11,6 +12,7 @@ interface AnimatedTerminalProps {
1112
1213const getExamples = ( version : string = '9.8.0' ) : TerminalExample [ ] => [
1314 {
15+ name : 'NumPy Basics' ,
1416 lines : [
1517 '$ ipython' ,
1618 `IPython ${ version } -- An enhanced Interactive Python` ,
@@ -26,6 +28,7 @@ const getExamples = (version: string = '9.8.0'): TerminalExample[] => [
2628 delay : 4000 ,
2729 } ,
2830 {
31+ name : 'Performance & Plotting' ,
2932 lines : [
3033 '$ ipython' ,
3134 `IPython ${ version } -- An enhanced Interactive Python` ,
@@ -40,6 +43,7 @@ const getExamples = (version: string = '9.8.0'): TerminalExample[] => [
4043 delay : 4000 ,
4144 } ,
4245 {
46+ name : 'Functions' ,
4347 lines : [
4448 '$ ipython' ,
4549 `IPython ${ version } -- An enhanced Interactive Python` ,
@@ -97,6 +101,15 @@ export default function AnimatedTerminal({ version }: AnimatedTerminalProps) {
97101 } ;
98102 } , [ ] ) ;
99103
104+ // Function to switch to a specific example
105+ const switchToExample = ( index : number ) => {
106+ if ( index >= 0 && index < examples . length ) {
107+ setCurrentExample ( index ) ;
108+ setCurrentLineIndex ( 0 ) ;
109+ setDisplayedLines ( [ ] ) ;
110+ }
111+ } ;
112+
100113 useEffect ( ( ) => {
101114 // Pause animation when page is not visible
102115 if ( ! isVisible ) {
@@ -175,30 +188,49 @@ export default function AnimatedTerminal({ version }: AnimatedTerminalProps) {
175188 const minHeight = `${ maxLines * lineHeight + padding + controlsHeight } rem` ;
176189
177190 return (
178- < div className = "bg-gray-50 dark:bg-gray-900 rounded-lg overflow-hidden font-mono text-sm" style = { { minHeight } } >
179- { /* macOS Window Controls */ }
180- < div className = "bg-gray-200 dark:bg-gray-800 border-b border-gray-300 dark:border-gray-700 px-4 py-2 flex items-center gap-2" >
181- < div className = "w-3 h-3 rounded-full bg-red-500" > </ div >
182- < div className = "w-3 h-3 rounded-full bg-yellow-500" > </ div >
183- < div className = "w-3 h-3 rounded-full bg-green-500" > </ div >
191+ < div >
192+ < div className = "bg-gray-50 dark:bg-gray-900 rounded-lg overflow-hidden font-mono text-sm" style = { { minHeight } } >
193+ { /* macOS Window Controls */ }
194+ < div className = "bg-gray-200 dark:bg-gray-800 border-b border-gray-300 dark:border-gray-700 px-4 py-2 flex items-center gap-2" >
195+ < div className = "w-3 h-3 rounded-full bg-red-500" > </ div >
196+ < div className = "w-3 h-3 rounded-full bg-yellow-500" > </ div >
197+ < div className = "w-3 h-3 rounded-full bg-green-500" > </ div >
198+ </ div >
199+
200+ { /* Terminal Content */ }
201+ < div className = "p-6 whitespace-pre" >
202+ { displayedLines . map ( ( line , index ) => {
203+ const { prefix, content, prefixColor } = getLinePrefix ( line ) ;
204+ const lineColor = getLineColor ( line ) ;
205+
206+ return (
207+ < div key = { index } className = { `${ lineColor } whitespace-pre` } >
208+ { prefix && < span className = { prefixColor } > { prefix } </ span > }
209+ { content }
210+ </ div >
211+ ) ;
212+ } ) }
213+ { displayedLines . length === 0 && (
214+ < div className = "text-theme-secondary whitespace-pre" > $ ipython</ div >
215+ ) }
216+ </ div >
184217 </ div >
185218
186- { /* Terminal Content */ }
187- < div className = "p-6" >
188- { displayedLines . map ( ( line , index ) => {
189- const { prefix, content, prefixColor } = getLinePrefix ( line ) ;
190- const lineColor = getLineColor ( line ) ;
191-
192- return (
193- < div key = { index } className = { lineColor } >
194- { prefix && < span className = { prefixColor } > { prefix } </ span > }
195- { content }
196- </ div >
197- ) ;
198- } ) }
199- { displayedLines . length === 0 && (
200- < div className = "text-theme-secondary" > $ ipython</ div >
201- ) }
219+ { /* Indicator Dots */ }
220+ < div className = "flex justify-center items-center gap-2 mt-4" >
221+ { examples . map ( ( example , index ) => (
222+ < button
223+ key = { index }
224+ onClick = { ( ) => switchToExample ( index ) }
225+ className = { `transition-all duration-200 focus:outline-none focus:ring-2 focus:ring-theme-primary focus:ring-offset-2 rounded-full ${
226+ index === currentExample
227+ ? 'w-3 h-3 bg-theme-accent border-2 border-theme-primary scale-125'
228+ : 'w-2 h-2 bg-gray-400 dark:bg-gray-600 hover:bg-gray-500 dark:hover:bg-gray-500'
229+ } `}
230+ aria-label = { `Go to ${ example . name } ` }
231+ title = { example . name }
232+ />
233+ ) ) }
202234 </ div >
203235 </ div >
204236 ) ;
0 commit comments