@editframe/create 0.44.0 → 0.45.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +16 -28
- package/dist/index.js.map +1 -1
- package/dist/skills/editframe-brand-video-generator/README.md +155 -0
- package/dist/skills/editframe-brand-video-generator/SKILL.md +207 -0
- package/dist/skills/editframe-brand-video-generator/references/brand-examples.md +178 -0
- package/dist/skills/editframe-brand-video-generator/references/color-psychology.md +227 -0
- package/dist/skills/editframe-brand-video-generator/references/composition-patterns.md +383 -0
- package/dist/skills/editframe-brand-video-generator/references/editing.md +66 -0
- package/dist/skills/editframe-brand-video-generator/references/emotional-arcs.md +496 -0
- package/dist/skills/editframe-brand-video-generator/references/genre-selection.md +135 -0
- package/dist/skills/editframe-brand-video-generator/references/transition-styles.md +611 -0
- package/dist/skills/editframe-brand-video-generator/references/typography-personalities.md +326 -0
- package/dist/skills/editframe-brand-video-generator/references/video-archetypes.md +86 -0
- package/dist/skills/editframe-brand-video-generator/references/video-fundamentals.md +169 -0
- package/dist/skills/editframe-brand-video-generator/references/visual-metaphors.md +50 -0
- package/dist/skills/editframe-composition/SKILL.md +169 -0
- package/dist/skills/editframe-composition/references/audio.md +483 -0
- package/dist/skills/editframe-composition/references/captions.md +844 -0
- package/dist/skills/editframe-composition/references/composition-model.md +73 -0
- package/dist/skills/editframe-composition/references/configuration.md +403 -0
- package/dist/skills/editframe-composition/references/css-parts.md +105 -0
- package/dist/skills/editframe-composition/references/css-variables.md +640 -0
- package/dist/skills/editframe-composition/references/entry-points.md +810 -0
- package/dist/skills/editframe-composition/references/events.md +499 -0
- package/dist/skills/editframe-composition/references/getting-started.md +259 -0
- package/dist/skills/editframe-composition/references/hooks.md +234 -0
- package/dist/skills/editframe-composition/references/image.md +241 -0
- package/dist/skills/editframe-composition/references/r3f.md +580 -0
- package/dist/skills/editframe-composition/references/render-api.md +484 -0
- package/dist/skills/editframe-composition/references/render-strategies.md +119 -0
- package/dist/skills/editframe-composition/references/render-to-video.md +1101 -0
- package/dist/skills/editframe-composition/references/scripting.md +606 -0
- package/dist/skills/editframe-composition/references/sequencing.md +116 -0
- package/dist/skills/editframe-composition/references/server-rendering.md +753 -0
- package/dist/skills/editframe-composition/references/surface.md +329 -0
- package/dist/skills/editframe-composition/references/text.md +627 -0
- package/dist/skills/editframe-composition/references/time-model.md +99 -0
- package/dist/skills/editframe-composition/references/timegroup-modes.md +102 -0
- package/dist/skills/editframe-composition/references/timegroup.md +457 -0
- package/dist/skills/editframe-composition/references/timeline-root.md +398 -0
- package/dist/skills/editframe-composition/references/transcription.md +47 -0
- package/dist/skills/editframe-composition/references/transitions.md +608 -0
- package/dist/skills/editframe-composition/references/use-media-info.md +357 -0
- package/dist/skills/editframe-composition/references/video.md +506 -0
- package/dist/skills/editframe-composition/references/waveform.md +327 -0
- package/dist/skills/editframe-editor-gui/SKILL.md +152 -0
- package/dist/skills/editframe-editor-gui/references/active-root-temporal.md +657 -0
- package/dist/skills/editframe-editor-gui/references/canvas.md +947 -0
- package/dist/skills/editframe-editor-gui/references/controls.md +366 -0
- package/dist/skills/editframe-editor-gui/references/dial.md +756 -0
- package/dist/skills/editframe-editor-gui/references/editor-toolkit.md +587 -0
- package/dist/skills/editframe-editor-gui/references/filmstrip.md +460 -0
- package/dist/skills/editframe-editor-gui/references/fit-scale.md +772 -0
- package/dist/skills/editframe-editor-gui/references/focus-overlay.md +561 -0
- package/dist/skills/editframe-editor-gui/references/hierarchy.md +544 -0
- package/dist/skills/editframe-editor-gui/references/overlay-item.md +634 -0
- package/dist/skills/editframe-editor-gui/references/overlay-layer.md +429 -0
- package/dist/skills/editframe-editor-gui/references/pan-zoom.md +568 -0
- package/dist/skills/editframe-editor-gui/references/pause.md +397 -0
- package/dist/skills/editframe-editor-gui/references/play.md +370 -0
- package/dist/skills/editframe-editor-gui/references/preview.md +391 -0
- package/dist/skills/editframe-editor-gui/references/resizable-box.md +749 -0
- package/dist/skills/editframe-editor-gui/references/scrubber.md +588 -0
- package/dist/skills/editframe-editor-gui/references/thumbnail-strip.md +566 -0
- package/dist/skills/editframe-editor-gui/references/time-display.md +492 -0
- package/dist/skills/editframe-editor-gui/references/timeline-ruler.md +489 -0
- package/dist/skills/editframe-editor-gui/references/timeline.md +604 -0
- package/dist/skills/editframe-editor-gui/references/toggle-loop.md +618 -0
- package/dist/skills/editframe-editor-gui/references/toggle-play.md +526 -0
- package/dist/skills/editframe-editor-gui/references/transform-handles.md +924 -0
- package/dist/skills/editframe-editor-gui/references/trim-handles.md +725 -0
- package/dist/skills/editframe-editor-gui/references/workbench.md +453 -0
- package/dist/skills/editframe-motion-design/SKILL.md +101 -0
- package/dist/skills/editframe-motion-design/references/0-editframe.md +299 -0
- package/dist/skills/editframe-motion-design/references/1-intent.md +201 -0
- package/dist/skills/editframe-motion-design/references/2-physics-model.md +405 -0
- package/dist/skills/editframe-motion-design/references/3-attention.md +350 -0
- package/dist/skills/editframe-motion-design/references/4-process.md +418 -0
- package/dist/skills/editframe-vite-plugin/SKILL.md +75 -0
- package/dist/skills/editframe-vite-plugin/references/file-api.md +111 -0
- package/dist/skills/editframe-vite-plugin/references/getting-started.md +96 -0
- package/dist/skills/editframe-vite-plugin/references/jit-transcoding.md +91 -0
- package/dist/skills/editframe-vite-plugin/references/local-assets.md +75 -0
- package/dist/skills/editframe-vite-plugin/references/visual-testing.md +136 -0
- package/dist/skills/editframe-webhooks/SKILL.md +126 -0
- package/dist/skills/editframe-webhooks/references/events.md +382 -0
- package/dist/skills/editframe-webhooks/references/getting-started.md +232 -0
- package/dist/skills/editframe-webhooks/references/security.md +418 -0
- package/dist/skills/editframe-webhooks/references/testing.md +409 -0
- package/dist/skills/editframe-webhooks/references/troubleshooting.md +457 -0
- package/dist/templates/html/AGENTS.md +13 -0
- package/dist/templates/react/AGENTS.md +13 -0
- package/dist/utils.js +15 -16
- package/dist/utils.js.map +1 -1
- package/package.json +1 -1
- package/tsdown.config.ts +4 -0
- package/dist/detectAgent.js +0 -89
- package/dist/detectAgent.js.map +0 -1
|
@@ -0,0 +1,640 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: CSS Variables
|
|
3
|
+
description: Dynamic CSS custom properties updated each frame with current time, duration, and progress values for time-driven animations.
|
|
4
|
+
type: reference
|
|
5
|
+
nav:
|
|
6
|
+
parent: "Layout & Timing"
|
|
7
|
+
priority: 30
|
|
8
|
+
related: ["video~effects"]
|
|
9
|
+
react:
|
|
10
|
+
generate: true
|
|
11
|
+
componentName: "CSS Variables"
|
|
12
|
+
importPath: "@editframe/react"
|
|
13
|
+
nav:
|
|
14
|
+
parent: "Advanced"
|
|
15
|
+
priority: 51
|
|
16
|
+
related: ["transitions", "timegroup"]
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
# CSS Variables
|
|
20
|
+
|
|
21
|
+
Dynamic CSS variables for time-based animations.
|
|
22
|
+
|
|
23
|
+
## Available Variables
|
|
24
|
+
|
|
25
|
+
All temporal elements expose these CSS variables:
|
|
26
|
+
|
|
27
|
+
- `--ef-duration` - Total duration (e.g., `"10s"`)
|
|
28
|
+
- `--ef-progress` - Current progress as number (0-1)
|
|
29
|
+
- `--ef-transition-duration` - Overlap duration for transitions
|
|
30
|
+
- `--ef-transition-out-start` - Delay for fade-out animations
|
|
31
|
+
|
|
32
|
+
## --ef-duration
|
|
33
|
+
|
|
34
|
+
Element's total duration as a CSS time value.
|
|
35
|
+
|
|
36
|
+
<!-- html-only -->
|
|
37
|
+
```html
|
|
38
|
+
<ef-video src="video.mp4" class="size-full"></ef-video>
|
|
39
|
+
|
|
40
|
+
<style>
|
|
41
|
+
ef-video {
|
|
42
|
+
/* Fade out during last 2 seconds */
|
|
43
|
+
animation: 2s fade-out calc(var(--ef-duration) - 2s);
|
|
44
|
+
}
|
|
45
|
+
</style>
|
|
46
|
+
```
|
|
47
|
+
<!-- /html-only -->
|
|
48
|
+
<!-- react-only -->
|
|
49
|
+
```tsx
|
|
50
|
+
import { Video } from "@editframe/react";
|
|
51
|
+
|
|
52
|
+
<Video
|
|
53
|
+
src="/assets/video.mp4"
|
|
54
|
+
className="size-full"
|
|
55
|
+
style={{
|
|
56
|
+
animation: "2s fade-out calc(var(--ef-duration) - 2s)"
|
|
57
|
+
}}
|
|
58
|
+
/>
|
|
59
|
+
```
|
|
60
|
+
<!-- /react-only -->
|
|
61
|
+
|
|
62
|
+
**Use cases:**
|
|
63
|
+
- Time animations relative to end of clip
|
|
64
|
+
- Calculate delays dynamically
|
|
65
|
+
- Avoid hardcoding durations
|
|
66
|
+
|
|
67
|
+
## --ef-progress
|
|
68
|
+
|
|
69
|
+
Current progress as a number from 0 to 1 (not a percentage).
|
|
70
|
+
|
|
71
|
+
**Important:** `--ef-progress` is stored as a number (0-1), not a CSS percentage. Multiply by 100% in calculations.
|
|
72
|
+
|
|
73
|
+
<!-- html-only -->
|
|
74
|
+
```html
|
|
75
|
+
<ef-timegroup mode="fixed" duration="5s">
|
|
76
|
+
<div class="progress-bar"></div>
|
|
77
|
+
</ef-timegroup>
|
|
78
|
+
|
|
79
|
+
<style>
|
|
80
|
+
.progress-bar {
|
|
81
|
+
/* Width grows from 0% to 100% */
|
|
82
|
+
width: calc(var(--ef-progress) * 100%);
|
|
83
|
+
height: 4px;
|
|
84
|
+
background: blue;
|
|
85
|
+
}
|
|
86
|
+
</style>
|
|
87
|
+
```
|
|
88
|
+
<!-- /html-only -->
|
|
89
|
+
<!-- react-only -->
|
|
90
|
+
```tsx
|
|
91
|
+
import { Timegroup } from "@editframe/react";
|
|
92
|
+
|
|
93
|
+
<Timegroup mode="fixed" duration="5s">
|
|
94
|
+
<div
|
|
95
|
+
className="progress-bar h-1 bg-blue-500"
|
|
96
|
+
style={{
|
|
97
|
+
width: "calc(var(--ef-progress) * 100%)"
|
|
98
|
+
}}
|
|
99
|
+
/>
|
|
100
|
+
</Timegroup>
|
|
101
|
+
```
|
|
102
|
+
<!-- /react-only -->
|
|
103
|
+
|
|
104
|
+
**Use cases:**
|
|
105
|
+
- Progress bars
|
|
106
|
+
- Scale animations
|
|
107
|
+
- Opacity fades
|
|
108
|
+
- Position interpolation
|
|
109
|
+
|
|
110
|
+
### Why Not a Percentage?
|
|
111
|
+
|
|
112
|
+
CSS percentages resolve to pixel values based on element dimensions. Using a number (0-1) allows it to work correctly in all calculations:
|
|
113
|
+
|
|
114
|
+
<!-- html-only -->
|
|
115
|
+
```css
|
|
116
|
+
/* Good: Number multiplied by 100% */
|
|
117
|
+
width: calc(var(--ef-progress) * 100%);
|
|
118
|
+
|
|
119
|
+
/* Bad: Would be interpreted as pixels */
|
|
120
|
+
width: var(--ef-progress);
|
|
121
|
+
```
|
|
122
|
+
<!-- /html-only -->
|
|
123
|
+
<!-- react-only -->
|
|
124
|
+
```tsx
|
|
125
|
+
{/* Good: Number multiplied by 100% */}
|
|
126
|
+
<div style={{ width: "calc(var(--ef-progress) * 100%)" }} />
|
|
127
|
+
|
|
128
|
+
{/* Bad: Would be interpreted as pixels */}
|
|
129
|
+
<div style={{ width: "var(--ef-progress)" }} />
|
|
130
|
+
```
|
|
131
|
+
<!-- /react-only -->
|
|
132
|
+
|
|
133
|
+
## --ef-transition-duration
|
|
134
|
+
|
|
135
|
+
Duration of overlap for transitions (only set when overlap exists).
|
|
136
|
+
|
|
137
|
+
<!-- html-only -->
|
|
138
|
+
```html
|
|
139
|
+
<ef-timegroup mode="sequence" overlap="1s">
|
|
140
|
+
<ef-timegroup mode="contain">
|
|
141
|
+
<ef-video
|
|
142
|
+
src="clip1.mp4"
|
|
143
|
+
style="animation: fade-out var(--ef-transition-duration) var(--ef-transition-out-start)"
|
|
144
|
+
></ef-video>
|
|
145
|
+
</ef-timegroup>
|
|
146
|
+
</ef-timegroup>
|
|
147
|
+
```
|
|
148
|
+
<!-- /html-only -->
|
|
149
|
+
<!-- react-only -->
|
|
150
|
+
```tsx
|
|
151
|
+
<Timegroup mode="sequence" overlap="1s">
|
|
152
|
+
<Timegroup mode="contain">
|
|
153
|
+
<Video
|
|
154
|
+
src="/assets/clip1.mp4"
|
|
155
|
+
style={{
|
|
156
|
+
animation: "fade-out var(--ef-transition-duration) var(--ef-transition-out-start)"
|
|
157
|
+
}}
|
|
158
|
+
/>
|
|
159
|
+
</Timegroup>
|
|
160
|
+
</Timegroup>
|
|
161
|
+
```
|
|
162
|
+
<!-- /react-only -->
|
|
163
|
+
|
|
164
|
+
**Use cases:**
|
|
165
|
+
- Match animation duration to overlap
|
|
166
|
+
- Dynamic transition timing
|
|
167
|
+
- Consistent fade durations
|
|
168
|
+
|
|
169
|
+
## --ef-transition-out-start
|
|
170
|
+
|
|
171
|
+
Delay for when fade-out should start (calculated as duration - overlap).
|
|
172
|
+
|
|
173
|
+
<!-- html-only -->
|
|
174
|
+
```html
|
|
175
|
+
<ef-video
|
|
176
|
+
src="video.mp4"
|
|
177
|
+
style="animation: 1s fade-out var(--ef-transition-out-start)"
|
|
178
|
+
></ef-video>
|
|
179
|
+
```
|
|
180
|
+
<!-- /html-only -->
|
|
181
|
+
<!-- react-only -->
|
|
182
|
+
```tsx
|
|
183
|
+
<Video
|
|
184
|
+
src="/assets/video.mp4"
|
|
185
|
+
style={{
|
|
186
|
+
animation: "1s fade-out var(--ef-transition-out-start)"
|
|
187
|
+
}}
|
|
188
|
+
/>
|
|
189
|
+
```
|
|
190
|
+
<!-- /react-only -->
|
|
191
|
+
|
|
192
|
+
**Use cases:**
|
|
193
|
+
- Fade out near end of clip
|
|
194
|
+
- Exit animations
|
|
195
|
+
- Transition timing
|
|
196
|
+
|
|
197
|
+
## Examples
|
|
198
|
+
|
|
199
|
+
### Progress Bar
|
|
200
|
+
|
|
201
|
+
<!-- html-only -->
|
|
202
|
+
```html
|
|
203
|
+
<ef-timegroup mode="fixed" duration="10s" class="relative">
|
|
204
|
+
<div class="progress-container">
|
|
205
|
+
<div class="progress-fill"></div>
|
|
206
|
+
</div>
|
|
207
|
+
</ef-timegroup>
|
|
208
|
+
|
|
209
|
+
<style>
|
|
210
|
+
.progress-container {
|
|
211
|
+
width: 100%;
|
|
212
|
+
height: 8px;
|
|
213
|
+
background: rgba(255, 255, 255, 0.2);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
.progress-fill {
|
|
217
|
+
width: calc(var(--ef-progress) * 100%);
|
|
218
|
+
height: 100%;
|
|
219
|
+
background: #3b82f6;
|
|
220
|
+
transition: width 0.1s linear;
|
|
221
|
+
}
|
|
222
|
+
</style>
|
|
223
|
+
```
|
|
224
|
+
<!-- /html-only -->
|
|
225
|
+
<!-- react-only -->
|
|
226
|
+
```tsx
|
|
227
|
+
import { Timegroup } from "@editframe/react";
|
|
228
|
+
|
|
229
|
+
const ProgressBar = () => {
|
|
230
|
+
return (
|
|
231
|
+
<Timegroup mode="fixed" duration="10s" className="relative">
|
|
232
|
+
<div className="w-full h-2 bg-gray-200">
|
|
233
|
+
<div
|
|
234
|
+
className="h-full bg-blue-500 transition-all duration-100"
|
|
235
|
+
style={{
|
|
236
|
+
width: "calc(var(--ef-progress) * 100%)"
|
|
237
|
+
}}
|
|
238
|
+
/>
|
|
239
|
+
</div>
|
|
240
|
+
</Timegroup>
|
|
241
|
+
);
|
|
242
|
+
};
|
|
243
|
+
```
|
|
244
|
+
<!-- /react-only -->
|
|
245
|
+
|
|
246
|
+
### Scale Animation
|
|
247
|
+
|
|
248
|
+
<!-- html-only -->
|
|
249
|
+
```html
|
|
250
|
+
<ef-timegroup mode="fixed" duration="3s">
|
|
251
|
+
<div class="scaling-text">Hello World</div>
|
|
252
|
+
</ef-timegroup>
|
|
253
|
+
|
|
254
|
+
<style>
|
|
255
|
+
.scaling-text {
|
|
256
|
+
transform: scale(var(--ef-progress));
|
|
257
|
+
opacity: var(--ef-progress);
|
|
258
|
+
}
|
|
259
|
+
</style>
|
|
260
|
+
```
|
|
261
|
+
<!-- /html-only -->
|
|
262
|
+
<!-- react-only -->
|
|
263
|
+
```tsx
|
|
264
|
+
const ScalingText = () => {
|
|
265
|
+
return (
|
|
266
|
+
<Timegroup mode="fixed" duration="3s">
|
|
267
|
+
<div
|
|
268
|
+
className="text-4xl font-bold"
|
|
269
|
+
style={{
|
|
270
|
+
transform: "scale(var(--ef-progress))",
|
|
271
|
+
opacity: "var(--ef-progress)"
|
|
272
|
+
}}
|
|
273
|
+
>
|
|
274
|
+
Hello World
|
|
275
|
+
</div>
|
|
276
|
+
</Timegroup>
|
|
277
|
+
);
|
|
278
|
+
};
|
|
279
|
+
```
|
|
280
|
+
<!-- /react-only -->
|
|
281
|
+
|
|
282
|
+
### Circular Progress
|
|
283
|
+
|
|
284
|
+
<!-- html-only -->
|
|
285
|
+
```html
|
|
286
|
+
<ef-timegroup mode="fixed" duration="5s">
|
|
287
|
+
<svg class="circular-progress" viewBox="0 0 100 100">
|
|
288
|
+
<circle class="progress-ring" cx="50" cy="50" r="40"></circle>
|
|
289
|
+
</svg>
|
|
290
|
+
</ef-timegroup>
|
|
291
|
+
|
|
292
|
+
<style>
|
|
293
|
+
.progress-ring {
|
|
294
|
+
fill: none;
|
|
295
|
+
stroke: #3b82f6;
|
|
296
|
+
stroke-width: 8;
|
|
297
|
+
stroke-dasharray: 251.2; /* 2 * PI * 40 */
|
|
298
|
+
stroke-dashoffset: calc(251.2 * (1 - var(--ef-progress)));
|
|
299
|
+
transform: rotate(-90deg);
|
|
300
|
+
transform-origin: center;
|
|
301
|
+
}
|
|
302
|
+
</style>
|
|
303
|
+
```
|
|
304
|
+
<!-- /html-only -->
|
|
305
|
+
<!-- react-only -->
|
|
306
|
+
```tsx
|
|
307
|
+
const CircularProgress = () => {
|
|
308
|
+
return (
|
|
309
|
+
<Timegroup mode="fixed" duration="5s">
|
|
310
|
+
<svg className="w-32 h-32" viewBox="0 0 100 100">
|
|
311
|
+
<circle
|
|
312
|
+
cx="50"
|
|
313
|
+
cy="50"
|
|
314
|
+
r="40"
|
|
315
|
+
fill="none"
|
|
316
|
+
stroke="#3b82f6"
|
|
317
|
+
strokeWidth="8"
|
|
318
|
+
style={{
|
|
319
|
+
strokeDasharray: "251.2",
|
|
320
|
+
strokeDashoffset: "calc(251.2 * (1 - var(--ef-progress)))",
|
|
321
|
+
transform: "rotate(-90deg)",
|
|
322
|
+
transformOrigin: "center"
|
|
323
|
+
}}
|
|
324
|
+
/>
|
|
325
|
+
</svg>
|
|
326
|
+
</Timegroup>
|
|
327
|
+
);
|
|
328
|
+
};
|
|
329
|
+
```
|
|
330
|
+
<!-- /react-only -->
|
|
331
|
+
|
|
332
|
+
### Dynamic Positioning
|
|
333
|
+
|
|
334
|
+
<!-- html-only -->
|
|
335
|
+
```html
|
|
336
|
+
<ef-timegroup mode="fixed" duration="4s" class="relative w-full h-full">
|
|
337
|
+
<div class="moving-box"></div>
|
|
338
|
+
</ef-timegroup>
|
|
339
|
+
|
|
340
|
+
<style>
|
|
341
|
+
.moving-box {
|
|
342
|
+
position: absolute;
|
|
343
|
+
width: 100px;
|
|
344
|
+
height: 100px;
|
|
345
|
+
background: red;
|
|
346
|
+
/* Move from left (0%) to right (100%) */
|
|
347
|
+
left: calc(var(--ef-progress) * (100% - 100px));
|
|
348
|
+
}
|
|
349
|
+
</style>
|
|
350
|
+
```
|
|
351
|
+
<!-- /html-only -->
|
|
352
|
+
<!-- react-only -->
|
|
353
|
+
```tsx
|
|
354
|
+
const MovingBox = () => {
|
|
355
|
+
return (
|
|
356
|
+
<Timegroup mode="fixed" duration="4s" className="relative w-full h-full">
|
|
357
|
+
<div
|
|
358
|
+
className="absolute w-24 h-24 bg-red-500"
|
|
359
|
+
style={{
|
|
360
|
+
left: "calc(var(--ef-progress) * (100% - 96px))"
|
|
361
|
+
}}
|
|
362
|
+
/>
|
|
363
|
+
</Timegroup>
|
|
364
|
+
);
|
|
365
|
+
};
|
|
366
|
+
```
|
|
367
|
+
<!-- /react-only -->
|
|
368
|
+
|
|
369
|
+
### Fade In and Out
|
|
370
|
+
|
|
371
|
+
<!-- html-only -->
|
|
372
|
+
```html
|
|
373
|
+
<ef-timegroup mode="fixed" duration="6s">
|
|
374
|
+
<div class="fading-element">Content</div>
|
|
375
|
+
</ef-timegroup>
|
|
376
|
+
|
|
377
|
+
<style>
|
|
378
|
+
.fading-element {
|
|
379
|
+
/* Fade in first half, fade out second half */
|
|
380
|
+
opacity: calc(1 - abs(var(--ef-progress) * 2 - 1));
|
|
381
|
+
}
|
|
382
|
+
</style>
|
|
383
|
+
```
|
|
384
|
+
<!-- /html-only -->
|
|
385
|
+
<!-- react-only -->
|
|
386
|
+
```tsx
|
|
387
|
+
const FadingElement = () => {
|
|
388
|
+
return (
|
|
389
|
+
<Timegroup mode="fixed" duration="6s">
|
|
390
|
+
<div
|
|
391
|
+
className="text-2xl"
|
|
392
|
+
style={{
|
|
393
|
+
opacity: "calc(1 - abs(var(--ef-progress) * 2 - 1))"
|
|
394
|
+
}}
|
|
395
|
+
>
|
|
396
|
+
Content
|
|
397
|
+
</div>
|
|
398
|
+
</Timegroup>
|
|
399
|
+
);
|
|
400
|
+
};
|
|
401
|
+
```
|
|
402
|
+
<!-- /react-only -->
|
|
403
|
+
|
|
404
|
+
### Color Interpolation
|
|
405
|
+
|
|
406
|
+
<!-- html-only -->
|
|
407
|
+
```html
|
|
408
|
+
<ef-timegroup mode="fixed" duration="5s">
|
|
409
|
+
<div class="color-changing">Text</div>
|
|
410
|
+
</ef-timegroup>
|
|
411
|
+
|
|
412
|
+
<style>
|
|
413
|
+
.color-changing {
|
|
414
|
+
/* Interpolate between colors using progress */
|
|
415
|
+
color: rgb(
|
|
416
|
+
calc(255 * var(--ef-progress)),
|
|
417
|
+
calc(128 * (1 - var(--ef-progress))),
|
|
418
|
+
255
|
|
419
|
+
);
|
|
420
|
+
}
|
|
421
|
+
</style>
|
|
422
|
+
```
|
|
423
|
+
<!-- /html-only -->
|
|
424
|
+
<!-- react-only -->
|
|
425
|
+
```tsx
|
|
426
|
+
const ColorChanging = () => {
|
|
427
|
+
return (
|
|
428
|
+
<Timegroup mode="fixed" duration="5s">
|
|
429
|
+
<div
|
|
430
|
+
className="text-4xl font-bold"
|
|
431
|
+
style={{
|
|
432
|
+
color: `rgb(
|
|
433
|
+
calc(255 * var(--ef-progress)),
|
|
434
|
+
calc(128 * (1 - var(--ef-progress))),
|
|
435
|
+
255
|
|
436
|
+
)`
|
|
437
|
+
}}
|
|
438
|
+
>
|
|
439
|
+
Text
|
|
440
|
+
</div>
|
|
441
|
+
</Timegroup>
|
|
442
|
+
);
|
|
443
|
+
};
|
|
444
|
+
```
|
|
445
|
+
<!-- /react-only -->
|
|
446
|
+
|
|
447
|
+
### Rotation
|
|
448
|
+
|
|
449
|
+
<!-- html-only -->
|
|
450
|
+
```html
|
|
451
|
+
<ef-timegroup mode="fixed" duration="3s">
|
|
452
|
+
<div class="rotating-element">↑</div>
|
|
453
|
+
</ef-timegroup>
|
|
454
|
+
|
|
455
|
+
<style>
|
|
456
|
+
.rotating-element {
|
|
457
|
+
/* Rotate 360 degrees over duration */
|
|
458
|
+
transform: rotate(calc(var(--ef-progress) * 360deg));
|
|
459
|
+
}
|
|
460
|
+
</style>
|
|
461
|
+
```
|
|
462
|
+
<!-- /html-only -->
|
|
463
|
+
<!-- react-only -->
|
|
464
|
+
```tsx
|
|
465
|
+
const RotatingElement = () => {
|
|
466
|
+
return (
|
|
467
|
+
<Timegroup mode="fixed" duration="3s">
|
|
468
|
+
<div
|
|
469
|
+
className="text-6xl"
|
|
470
|
+
style={{
|
|
471
|
+
transform: "rotate(calc(var(--ef-progress) * 360deg))"
|
|
472
|
+
}}
|
|
473
|
+
>
|
|
474
|
+
↑
|
|
475
|
+
</div>
|
|
476
|
+
</Timegroup>
|
|
477
|
+
);
|
|
478
|
+
};
|
|
479
|
+
```
|
|
480
|
+
<!-- /react-only -->
|
|
481
|
+
|
|
482
|
+
## Combining Variables
|
|
483
|
+
|
|
484
|
+
Use multiple variables together:
|
|
485
|
+
|
|
486
|
+
<!-- html-only -->
|
|
487
|
+
```html
|
|
488
|
+
<ef-timegroup mode="sequence" overlap="1s">
|
|
489
|
+
<ef-timegroup mode="contain">
|
|
490
|
+
<ef-video
|
|
491
|
+
src="clip.mp4"
|
|
492
|
+
style="
|
|
493
|
+
animation:
|
|
494
|
+
2s fade-in 0s,
|
|
495
|
+
var(--ef-transition-duration) fade-out var(--ef-transition-out-start);
|
|
496
|
+
"
|
|
497
|
+
></ef-video>
|
|
498
|
+
</ef-timegroup>
|
|
499
|
+
</ef-timegroup>
|
|
500
|
+
```
|
|
501
|
+
<!-- /html-only -->
|
|
502
|
+
<!-- react-only -->
|
|
503
|
+
```tsx
|
|
504
|
+
<Timegroup mode="sequence" overlap="1s">
|
|
505
|
+
<Timegroup mode="contain">
|
|
506
|
+
<Video
|
|
507
|
+
src="/assets/clip.mp4"
|
|
508
|
+
style={{
|
|
509
|
+
animation: `
|
|
510
|
+
2s fade-in 0s,
|
|
511
|
+
var(--ef-transition-duration) fade-out var(--ef-transition-out-start)
|
|
512
|
+
`
|
|
513
|
+
}}
|
|
514
|
+
/>
|
|
515
|
+
</Timegroup>
|
|
516
|
+
</Timegroup>
|
|
517
|
+
```
|
|
518
|
+
<!-- /react-only -->
|
|
519
|
+
|
|
520
|
+
<!-- react-only -->
|
|
521
|
+
## With Inline Styles
|
|
522
|
+
|
|
523
|
+
React style prop syntax:
|
|
524
|
+
|
|
525
|
+
```tsx
|
|
526
|
+
<div
|
|
527
|
+
style={{
|
|
528
|
+
width: "calc(var(--ef-progress) * 100%)",
|
|
529
|
+
opacity: "var(--ef-progress)",
|
|
530
|
+
transform: "scale(var(--ef-progress))"
|
|
531
|
+
}}
|
|
532
|
+
/>
|
|
533
|
+
```
|
|
534
|
+
|
|
535
|
+
## With Tailwind CSS
|
|
536
|
+
|
|
537
|
+
Use arbitrary values with CSS variables:
|
|
538
|
+
|
|
539
|
+
```tsx
|
|
540
|
+
<div
|
|
541
|
+
className="w-full h-4 bg-blue-500"
|
|
542
|
+
style={{
|
|
543
|
+
width: "calc(var(--ef-progress) * 100%)"
|
|
544
|
+
}}
|
|
545
|
+
/>
|
|
546
|
+
```
|
|
547
|
+
<!-- /react-only -->
|
|
548
|
+
|
|
549
|
+
## Browser Compatibility
|
|
550
|
+
|
|
551
|
+
CSS variables work in all modern browsers. For rendering, they're evaluated during frame capture.
|
|
552
|
+
|
|
553
|
+
## Performance
|
|
554
|
+
|
|
555
|
+
CSS variables are updated on each frame. Keep calculations simple for best performance:
|
|
556
|
+
|
|
557
|
+
<!-- html-only -->
|
|
558
|
+
```css
|
|
559
|
+
/* Good: Simple calculation */
|
|
560
|
+
width: calc(var(--ef-progress) * 100%);
|
|
561
|
+
|
|
562
|
+
/* Avoid: Complex nested calculations */
|
|
563
|
+
width: calc(calc(var(--ef-progress) * 50%) + calc(var(--ef-progress) * 50%));
|
|
564
|
+
```
|
|
565
|
+
<!-- /html-only -->
|
|
566
|
+
<!-- react-only -->
|
|
567
|
+
```tsx
|
|
568
|
+
{/* Good: Simple calculation */}
|
|
569
|
+
<div style={{ width: "calc(var(--ef-progress) * 100%)" }} />
|
|
570
|
+
|
|
571
|
+
{/* Avoid: Complex nested calculations */}
|
|
572
|
+
<div style={{
|
|
573
|
+
width: "calc(calc(var(--ef-progress) * 50%) + calc(var(--ef-progress) * 50%))"
|
|
574
|
+
}} />
|
|
575
|
+
```
|
|
576
|
+
<!-- /react-only -->
|
|
577
|
+
|
|
578
|
+
<!-- react-only -->
|
|
579
|
+
## TypeScript Types
|
|
580
|
+
|
|
581
|
+
For style objects with CSS variables:
|
|
582
|
+
|
|
583
|
+
```tsx
|
|
584
|
+
import { CSSProperties } from "react";
|
|
585
|
+
|
|
586
|
+
const style: CSSProperties = {
|
|
587
|
+
width: "calc(var(--ef-progress) * 100%)",
|
|
588
|
+
opacity: "var(--ef-progress)",
|
|
589
|
+
};
|
|
590
|
+
|
|
591
|
+
<div style={style} />
|
|
592
|
+
```
|
|
593
|
+
|
|
594
|
+
## Reusable Progress Component
|
|
595
|
+
|
|
596
|
+
```tsx
|
|
597
|
+
interface ProgressProps {
|
|
598
|
+
className?: string;
|
|
599
|
+
color?: string;
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
const Progress = ({ className = "", color = "bg-blue-500" }: ProgressProps) => {
|
|
603
|
+
return (
|
|
604
|
+
<div className={`w-full h-2 bg-gray-200 ${className}`}>
|
|
605
|
+
<div
|
|
606
|
+
className={`h-full ${color}`}
|
|
607
|
+
style={{
|
|
608
|
+
width: "calc(var(--ef-progress) * 100%)"
|
|
609
|
+
}}
|
|
610
|
+
/>
|
|
611
|
+
</div>
|
|
612
|
+
);
|
|
613
|
+
};
|
|
614
|
+
|
|
615
|
+
// Usage
|
|
616
|
+
<Timegroup mode="fixed" duration="5s">
|
|
617
|
+
<Progress color="bg-green-500" />
|
|
618
|
+
</Timegroup>
|
|
619
|
+
```
|
|
620
|
+
<!-- /react-only -->
|
|
621
|
+
|
|
622
|
+
## Tips
|
|
623
|
+
|
|
624
|
+
1. **Use --ef-progress for interpolation** - Perfect for smooth animations
|
|
625
|
+
2. **Multiply by 100% for percentages** - Don't use progress value directly
|
|
626
|
+
3. **Match transition durations** - Use `--ef-transition-duration` for consistency
|
|
627
|
+
4. **Test in preview** - Verify animations work before rendering
|
|
628
|
+
5. **Keep calculations simple** - Better performance and easier debugging
|
|
629
|
+
<!-- react-only -->
|
|
630
|
+
6. **Use TypeScript** - Type your style objects for better IDE support
|
|
631
|
+
7. **Extract to components** - Create reusable animated components
|
|
632
|
+
<!-- /react-only -->
|
|
633
|
+
|
|
634
|
+
## See Also
|
|
635
|
+
|
|
636
|
+
- [transitions.md](references/transitions.md) - Transition examples using CSS variables
|
|
637
|
+
- [scripting.md](references/scripting.md) - JavaScript-based animations
|
|
638
|
+
<!-- react-only -->
|
|
639
|
+
- [hooks.md](references/hooks.md) - React hooks for timing information
|
|
640
|
+
<!-- /react-only -->
|