11import { useAnimation , useVariable } from "../src/lib/animation"
2- import { DrawText } from "../src/lib/animation/effect/draw-text"
32import { BEZIER_SMOOTH } from "../src/lib/animation/functions"
43import { Clip } from "../src/lib/clip"
54import { seconds } from "../src/lib/frame"
65import { FillFrame } from "../src/lib/layout/fill-frame"
6+ import { Code } from "../src/lib/misc/code"
77import { Project , type ProjectSettings } from "../src/lib/project"
88import { TimeLine } from "../src/lib/timeline"
99
@@ -14,29 +14,195 @@ export const PROJECT_SETTINGS: ProjectSettings = {
1414 fps : 60 ,
1515}
1616
17- const HelloScene = ( ) => {
18- const progress = useVariable ( 0 )
19- const color = useVariable ( "#FFFFFF" )
17+ const CODE_STEPS = [
18+ {
19+ language : "ts" as const ,
20+ code : `type User = { id: string; first: string; last: string }
2021
21- useAnimation ( async ( context ) => {
22- await context . parallel ( [
23- context . move ( progress ) . to ( 1 , seconds ( 3 ) , BEZIER_SMOOTH ) ,
24- context . move ( color ) . to ( "#75a9bd" , seconds ( 3 ) , BEZIER_SMOOTH ) ,
22+ export const fetchUser = async (id: string) => {
23+ const res = await fetch(\`/api/users/\${id}\`)
24+ return res.json()
25+ }` ,
26+ } ,
27+ {
28+ language : "ts" as const ,
29+ code : `type User = { id: string; first: string; last: string }
30+
31+ export const fetchUser = async (id: string): Promise<User> => {
32+ const res = await fetch(\`/api/users/\${id}\`)
33+ if (!res.ok) {
34+ throw new Error("request failed")
35+ }
36+ return res.json()
37+ }` ,
38+ } ,
39+ {
40+ language : "ts" as const ,
41+ code : `type User = { id: string; first: string; last: string }
42+
43+ export const fetchUser = async (id: string): Promise<User> => {
44+ const res = await fetch(\`/api/users/\${id}\`)
45+ if (!res.ok) {
46+ throw new Error("request failed")
47+ }
48+ const user = await res.json() as User
49+ return user
50+ }` ,
51+ } ,
52+ {
53+ language : "ts" as const ,
54+ code : `type User = { id: string; first: string; last: string; fullName: string }
55+
56+ export const fetchUser = async (id: string): Promise<User> => {
57+ const res = await fetch(\`/api/users/\${id}\`)
58+ if (!res.ok) {
59+ throw new Error("request failed")
60+ }
61+ const user = await res.json() as Omit<User, "fullName">
62+ const fullName = \`\${user.first} \${user.last}\`
63+ return { ...user, fullName }
64+ }` ,
65+ } ,
66+ ]
67+
68+ const CodeScene = ( ) => {
69+ const codeStep = useVariable ( 0 )
70+ const focusStep = useVariable ( 0 )
71+ const panelOpacity = useVariable ( 0 )
72+ const panelOffset = useVariable ( 50 )
73+
74+ useAnimation ( async ( ctx ) => {
75+ await ctx . parallel ( [
76+ ctx . move ( panelOpacity ) . to ( 1 , seconds ( 0.7 ) , BEZIER_SMOOTH ) ,
77+ ctx . move ( panelOffset ) . to ( 0 , seconds ( 0.7 ) , BEZIER_SMOOTH ) ,
78+ ] )
79+
80+ await ctx . sleep ( seconds ( 0.2 ) )
81+
82+ await ctx . parallel ( [
83+ ctx . move ( codeStep ) . to ( 1 , seconds ( 1.7 ) , BEZIER_SMOOTH ) ,
84+ ctx . move ( focusStep ) . to ( 1 , seconds ( 1.7 ) , BEZIER_SMOOTH ) ,
85+ ] )
86+
87+ await ctx . sleep ( seconds ( 0.3 ) )
88+
89+ await ctx . parallel ( [
90+ ctx . move ( codeStep ) . to ( 2 , seconds ( 1.8 ) , BEZIER_SMOOTH ) ,
91+ ctx . move ( focusStep ) . to ( 2 , seconds ( 1.8 ) , BEZIER_SMOOTH ) ,
92+ ] )
93+
94+ await ctx . sleep ( seconds ( 0.3 ) )
95+
96+ await ctx . parallel ( [
97+ ctx . move ( codeStep ) . to ( 3 , seconds ( 2.0 ) , BEZIER_SMOOTH ) ,
98+ ctx . move ( focusStep ) . to ( 3 , seconds ( 2.0 ) , BEZIER_SMOOTH ) ,
99+ ] )
100+
101+ await ctx . sleep ( seconds ( 0.6 ) )
102+
103+ await ctx . parallel ( [
104+ ctx . move ( panelOpacity ) . to ( 0 , seconds ( 0.8 ) , BEZIER_SMOOTH ) ,
105+ ctx . move ( panelOffset ) . to ( - 30 , seconds ( 0.8 ) , BEZIER_SMOOTH ) ,
25106 ] )
26- await context . sleep ( seconds ( 1 ) )
27- await context . move ( progress ) . to ( 0 , seconds ( 3 ) , BEZIER_SMOOTH )
28107 } , [ ] )
29108
30109 return (
31- < FillFrame style = { { alignItems : "center" , justifyContent : "center" } } >
32- < DrawText
33- text = "Hello, world!"
34- fontUrl = "assets/NotoSerifCJKJP-Medium.ttf"
35- strokeWidth = { 2 }
36- progress = { progress }
37- strokeColor = { color . use ( ) }
38- fillColor = { color . use ( ) }
39- />
110+ < FillFrame
111+ style = { {
112+ alignItems : "center" ,
113+ justifyContent : "center" ,
114+ background :
115+ "radial-gradient(circle at 20% 20%, rgba(56,189,248,0.12), transparent 45%), radial-gradient(circle at 80% 80%, rgba(14,165,233,0.08), transparent 40%), #020617" ,
116+ } }
117+ >
118+ < div
119+ style = { {
120+ width : 1480 ,
121+ maxWidth : "92%" ,
122+ padding : 22 ,
123+ borderRadius : 18 ,
124+ background : "linear-gradient(180deg, rgba(15,23,42,0.94), rgba(2,6,23,0.94))" ,
125+ border : "1px solid rgba(56,189,248,0.28)" ,
126+ boxShadow : "0 28px 70px rgba(2,6,23,0.65)" ,
127+ transform : `translateY(${ panelOffset . use ( ) } px)` ,
128+ opacity : panelOpacity . use ( ) ,
129+ } }
130+ >
131+ < div
132+ style = { {
133+ marginBottom : 14 ,
134+ color : "#bae6fd" ,
135+ fontSize : 22 ,
136+ fontWeight : 700 ,
137+ letterSpacing : "0.02em" ,
138+ fontFamily : "'Fira Sans', 'Noto Sans JP', sans-serif" ,
139+ } }
140+ >
141+ Code Step Demo
142+ </ div >
143+
144+ < Code
145+ steps = { CODE_STEPS }
146+ step = { codeStep }
147+ fontSize = { 30 }
148+ lineHeight = { 1.55 }
149+ padding = { 18 }
150+ theme = { {
151+ base : "#dbeafe" ,
152+ keyword : "#7dd3fc" ,
153+ type : "#fca5a5" ,
154+ string : "#86efac" ,
155+ number : "#fbbf24" ,
156+ comment : "#94a3b8" ,
157+ builtin : "#c4b5fd" ,
158+ punctuation : "#cbd5e1" ,
159+ } }
160+ highlightTracks = { [
161+ {
162+ id : "main-focus" ,
163+ step : focusStep ,
164+ steps : [
165+ {
166+ codeStep : 0 ,
167+ match : "await fetch(`/api/users/${id}`)" ,
168+ padding : { x : 14 , y : 5 } ,
169+ radius : 12 ,
170+ strokeWidth : 3 ,
171+ color : "#22d3ee" ,
172+ fillColor : "rgba(34,211,238,0.12)" ,
173+ } ,
174+ {
175+ codeStep : 1 ,
176+ match : "if (!res.ok) {\n throw new Error(\"request failed\")\n }" ,
177+ padding : { x : 14 , y : 5 } ,
178+ radius : 12 ,
179+ strokeWidth : 3 ,
180+ color : "#f59e0b" ,
181+ fillColor : "rgba(245,158,11,0.12)" ,
182+ } ,
183+ {
184+ codeStep : 2 ,
185+ match : "const user = await res.json() as User" ,
186+ padding : { x : 14 , y : 5 } ,
187+ radius : 12 ,
188+ strokeWidth : 3 ,
189+ color : "#a78bfa" ,
190+ fillColor : "rgba(167,139,250,0.14)" ,
191+ } ,
192+ {
193+ codeStep : 3 ,
194+ match : "return { ...user, fullName }" ,
195+ padding : { x : 14 , y : 5 } ,
196+ radius : 12 ,
197+ strokeWidth : 3 ,
198+ color : "#34d399" ,
199+ fillColor : "rgba(52,211,153,0.14)" ,
200+ } ,
201+ ] ,
202+ } ,
203+ ] }
204+ />
205+ </ div >
40206 </ FillFrame >
41207 )
42208}
@@ -45,8 +211,8 @@ export const PROJECT = () => {
45211 return (
46212 < Project >
47213 < TimeLine >
48- < Clip label = "Hello " >
49- < HelloScene />
214+ < Clip label = "Code Demo " >
215+ < CodeScene />
50216 </ Clip >
51217 </ TimeLine >
52218 </ Project >
0 commit comments