1+ import React , { useState , useEffect } from 'react' ;
2+
3+ const AnimatedCodeEditor : React . FC = ( ) => {
4+ const [ currentLine , setCurrentLine ] = useState ( 0 ) ;
5+ const [ typedCode , setTypedCode ] = useState < string [ ] > ( [ ] ) ;
6+ const [ showSuccess , setShowSuccess ] = useState ( false ) ;
7+ const [ isTyping , setIsTyping ] = useState ( false ) ;
8+
9+ const codeLines = [
10+ { text : "name: PRiority Auto-Fund" , indent : 0 , highlight : false } ,
11+ { text : "" , indent : 0 , highlight : false } ,
12+ { text : "on:" , indent : 0 , highlight : false } ,
13+ { text : " issues:" , indent : 0 , highlight : false } ,
14+ { text : " types: [opened, labeled]" , indent : 1 , highlight : true } ,
15+ { text : "" , indent : 0 , highlight : false } ,
16+ { text : "jobs:" , indent : 0 , highlight : false } ,
17+ { text : " auto-estimate:" , indent : 0 , highlight : false } ,
18+ { text : " runs-on: ubuntu-latest" , indent : 1 , highlight : false } ,
19+ { text : " steps:" , indent : 1 , highlight : false } ,
20+ { text : " - uses: priority/estimate@v1" , indent : 2 , highlight : true } ,
21+ { text : " with:" , indent : 2 , highlight : false } ,
22+ { text : " ai-model: claude-3-opus" , indent : 3 , highlight : true } ,
23+ { text : " threshold: $100" , indent : 3 , highlight : false } ,
24+ { text : " auto-fund: true" , indent : 3 , highlight : true } ,
25+ { text : " - name: ✨ Magic happens" , indent : 2 , highlight : true } ,
26+ ] ;
27+
28+ useEffect ( ( ) => {
29+ const startTyping = async ( ) => {
30+ setIsTyping ( true ) ;
31+ setTypedCode ( [ ] ) ;
32+ setCurrentLine ( 0 ) ;
33+ setShowSuccess ( false ) ;
34+
35+ for ( let i = 0 ; i < codeLines . length ; i ++ ) {
36+ await typeLineByLine ( i ) ;
37+ }
38+
39+ await new Promise ( resolve => setTimeout ( resolve , 500 ) ) ;
40+ setShowSuccess ( true ) ;
41+ await new Promise ( resolve => setTimeout ( resolve , 3000 ) ) ;
42+ setIsTyping ( false ) ;
43+ } ;
44+
45+ const interval = setInterval ( ( ) => {
46+ if ( ! isTyping ) {
47+ startTyping ( ) ;
48+ }
49+ } , 8000 ) ;
50+
51+ // Start immediately
52+ if ( ! isTyping ) {
53+ startTyping ( ) ;
54+ }
55+
56+ return ( ) => clearInterval ( interval ) ;
57+ } , [ isTyping ] ) ;
58+
59+ const typeLineByLine = async ( lineIndex : number ) => {
60+ const line = codeLines [ lineIndex ] ;
61+ let currentText = '' ;
62+
63+ for ( let i = 0 ; i <= line . text . length ; i ++ ) {
64+ currentText = line . text . slice ( 0 , i ) ;
65+ setTypedCode ( prev => {
66+ const newLines = [ ...prev ] ;
67+ newLines [ lineIndex ] = currentText ;
68+ return newLines ;
69+ } ) ;
70+ setCurrentLine ( lineIndex ) ;
71+ await new Promise ( resolve => setTimeout ( resolve , 30 ) ) ;
72+ }
73+ } ;
74+
75+ return (
76+ < div className = "relative" >
77+ < div className = "glass-card overflow-hidden" >
78+ { /* Editor Header */ }
79+ < div className = "flex items-center justify-between px-4 py-3 border-b border-gray-700 bg-gray-900/50" >
80+ < div className = "flex items-center gap-2" >
81+ < div className = "w-3 h-3 rounded-full bg-red-500" > </ div >
82+ < div className = "w-3 h-3 rounded-full bg-yellow-500" > </ div >
83+ < div className = "w-3 h-3 rounded-full bg-green-500" > </ div >
84+ </ div >
85+ < span className = "text-xs text-gray-400 font-mono" > .github/workflows/priority.yml</ span >
86+ < div className = "flex items-center gap-2" >
87+ { showSuccess && (
88+ < span className = "text-xs text-green-400 font-mono animate-fade-in flex items-center gap-1" >
89+ < svg className = "w-4 h-4" fill = "currentColor" viewBox = "0 0 20 20" >
90+ < path fillRule = "evenodd" d = "M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clipRule = "evenodd" />
91+ </ svg >
92+ Deployed
93+ </ span >
94+ ) }
95+ </ div >
96+ </ div >
97+
98+ { /* Code Editor */ }
99+ < div className = "p-6 bg-gray-950/50 font-mono text-sm" >
100+ < div className = "space-y-1" >
101+ { codeLines . map ( ( line , index ) => (
102+ < div
103+ key = { index }
104+ className = { `flex items-center transition-all duration-300 ${
105+ index === currentLine && isTyping ? 'bg-blue-500/10' : ''
106+ } `}
107+ >
108+ < span className = "text-gray-600 mr-4 select-none" style = { { width : '30px' } } >
109+ { String ( index + 1 ) . padStart ( 2 , '0' ) }
110+ </ span >
111+ < span
112+ className = { `${
113+ line . highlight ? 'text-blue-400' : 'text-gray-300'
114+ } ${ index <= currentLine ? 'opacity-100' : 'opacity-0' } `}
115+ style = { { paddingLeft : `${ line . indent * 20 } px` } }
116+ >
117+ { typedCode [ index ] || '' }
118+ { index === currentLine && isTyping && (
119+ < span className = "inline-block w-2 h-4 bg-blue-500 animate-blink ml-1" > </ span >
120+ ) }
121+ </ span >
122+ </ div >
123+ ) ) }
124+ </ div >
125+ </ div >
126+
127+ { /* Success Overlay */ }
128+ { showSuccess && (
129+ < div className = "absolute inset-0 flex items-center justify-center bg-black/50 backdrop-blur-sm animate-fade-in" >
130+ < div className = "text-center" >
131+ < div className = "text-6xl mb-4 animate-bounce" > 🚀</ div >
132+ < div className = "text-2xl font-bold text-white mb-2" > Deployed!</ div >
133+ < div className = "text-gray-400" > Your repo is now PRiority-enabled</ div >
134+ </ div >
135+ </ div >
136+ ) }
137+ </ div >
138+
139+ { /* Feature Badges */ }
140+ < div className = "mt-6 flex flex-wrap gap-3 justify-center" >
141+ { [ '🤖 AI-Powered' , '⚡ Instant Setup' , '🎯 Zero Config' , '💰 Auto-Fund' ] . map ( ( badge , index ) => (
142+ < div
143+ key = { badge }
144+ className = "px-4 py-2 bg-gradient-to-r from-blue-500/20 to-purple-500/20 border border-blue-500/30 rounded-full text-sm font-medium animate-fade-in"
145+ style = { { animationDelay : `${ index * 100 } ms` } }
146+ >
147+ { badge }
148+ </ div >
149+ ) ) }
150+ </ div >
151+ </ div >
152+ ) ;
153+ } ;
154+
155+ export default AnimatedCodeEditor ;
0 commit comments