@editframe/create 0.43.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/README.md +11 -0
- 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 +2 -2
- package/tsdown.config.ts +4 -0
- package/dist/detectAgent.js +0 -89
- package/dist/detectAgent.js.map +0 -1
|
@@ -0,0 +1,627 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Text Element
|
|
3
|
+
description: Animated text element with automatic character, word, and line splitting for per-unit CSS animation and stagger effects.
|
|
4
|
+
type: reference
|
|
5
|
+
nav:
|
|
6
|
+
parent: "Media"
|
|
7
|
+
priority: 20
|
|
8
|
+
related: ["captions"]
|
|
9
|
+
api:
|
|
10
|
+
attributes:
|
|
11
|
+
- name: split
|
|
12
|
+
type: string
|
|
13
|
+
default: "word"
|
|
14
|
+
description: Split mode
|
|
15
|
+
values: ["line", "word", "char"]
|
|
16
|
+
- name: stagger
|
|
17
|
+
type: timestring
|
|
18
|
+
description: Delay between segments (e.g., "100ms")
|
|
19
|
+
- name: easing
|
|
20
|
+
type: string
|
|
21
|
+
default: "linear"
|
|
22
|
+
description: Easing function
|
|
23
|
+
- name: duration
|
|
24
|
+
type: timestring
|
|
25
|
+
description: Total duration
|
|
26
|
+
sub_elements:
|
|
27
|
+
- tag: ef-text-segment
|
|
28
|
+
description: Individual segment created when splitting text by word, character, or line
|
|
29
|
+
attributes:
|
|
30
|
+
- name: segmentIndex
|
|
31
|
+
type: number
|
|
32
|
+
description: Index of this segment in the text
|
|
33
|
+
- name: segmentText
|
|
34
|
+
type: string
|
|
35
|
+
description: Text content of this segment
|
|
36
|
+
- name: staggerOffsetMs
|
|
37
|
+
type: number
|
|
38
|
+
description: Calculated stagger delay for this segment
|
|
39
|
+
- name: segmentStartMs
|
|
40
|
+
type: number
|
|
41
|
+
description: Start time of segment relative to parent
|
|
42
|
+
- name: segmentEndMs
|
|
43
|
+
type: number
|
|
44
|
+
description: End time of segment relative to parent
|
|
45
|
+
- name: hidden
|
|
46
|
+
type: boolean
|
|
47
|
+
description: Whether segment is hidden
|
|
48
|
+
methods:
|
|
49
|
+
- name: registerAnimations()
|
|
50
|
+
signature: "static registerAnimations(id: string, cssText: string): void"
|
|
51
|
+
description: Register animation styles globally for all text segments
|
|
52
|
+
- name: unregisterAnimations()
|
|
53
|
+
signature: "static unregisterAnimations(id: string): void"
|
|
54
|
+
description: Unregister previously registered animation styles
|
|
55
|
+
css_variables:
|
|
56
|
+
- name: --ef-index
|
|
57
|
+
type: number
|
|
58
|
+
description: Segment index (0, 1, 2, ...)
|
|
59
|
+
- name: --ef-stagger-offset
|
|
60
|
+
type: time
|
|
61
|
+
description: Calculated stagger delay (e.g., "0ms", "100ms")
|
|
62
|
+
- name: --ef-seed
|
|
63
|
+
type: number
|
|
64
|
+
description: Deterministic random (0-1) based on index
|
|
65
|
+
react:
|
|
66
|
+
generate: true
|
|
67
|
+
componentName: Text
|
|
68
|
+
importPath: "@editframe/react"
|
|
69
|
+
additionalProps:
|
|
70
|
+
- name: className
|
|
71
|
+
type: string
|
|
72
|
+
description: CSS classes for styling
|
|
73
|
+
- name: children
|
|
74
|
+
type: React.ReactNode
|
|
75
|
+
description: Text content or TextSegment components
|
|
76
|
+
nav:
|
|
77
|
+
parent: "Components / Text & Graphics"
|
|
78
|
+
priority: 30
|
|
79
|
+
related: ["captions"]
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
<!-- html-only -->
|
|
83
|
+
# ef-text
|
|
84
|
+
<!-- /html-only -->
|
|
85
|
+
<!-- react-only -->
|
|
86
|
+
# Text
|
|
87
|
+
<!-- /react-only -->
|
|
88
|
+
|
|
89
|
+
Animated text with character/word/line splitting.
|
|
90
|
+
|
|
91
|
+
<!-- react-only -->
|
|
92
|
+
## Import
|
|
93
|
+
|
|
94
|
+
```tsx
|
|
95
|
+
import { Text, TextSegment } from "@editframe/react";
|
|
96
|
+
```
|
|
97
|
+
<!-- /react-only -->
|
|
98
|
+
|
|
99
|
+
## Basic Usage
|
|
100
|
+
|
|
101
|
+
<!-- html-only -->
|
|
102
|
+
```html live
|
|
103
|
+
<ef-timegroup mode="contain" class="w-[720px] h-[480px] bg-black flex items-center justify-center">
|
|
104
|
+
<ef-text duration="5s" class="text-white text-2xl">Static text</ef-text>
|
|
105
|
+
</ef-timegroup>
|
|
106
|
+
```
|
|
107
|
+
<!-- /html-only -->
|
|
108
|
+
<!-- react-only -->
|
|
109
|
+
```tsx
|
|
110
|
+
<Text duration="5s" className="text-white text-4xl">
|
|
111
|
+
Hello World
|
|
112
|
+
</Text>
|
|
113
|
+
```
|
|
114
|
+
<!-- /react-only -->
|
|
115
|
+
|
|
116
|
+
<!-- react-only -->
|
|
117
|
+
## Styled Text
|
|
118
|
+
|
|
119
|
+
```tsx
|
|
120
|
+
<Text
|
|
121
|
+
duration="3s"
|
|
122
|
+
className="text-white text-6xl font-bold text-center"
|
|
123
|
+
>
|
|
124
|
+
Welcome to Editframe
|
|
125
|
+
</Text>
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## Positioned Text
|
|
129
|
+
|
|
130
|
+
```tsx
|
|
131
|
+
<Timegroup mode="fixed" duration="5s" className="absolute w-full h-full">
|
|
132
|
+
<Text
|
|
133
|
+
duration="5s"
|
|
134
|
+
className="absolute top-8 left-8 text-white text-3xl"
|
|
135
|
+
>
|
|
136
|
+
Top Left
|
|
137
|
+
</Text>
|
|
138
|
+
|
|
139
|
+
<Text
|
|
140
|
+
duration="5s"
|
|
141
|
+
className="absolute bottom-8 right-8 text-white text-2xl"
|
|
142
|
+
>
|
|
143
|
+
Bottom Right
|
|
144
|
+
</Text>
|
|
145
|
+
</Timegroup>
|
|
146
|
+
```
|
|
147
|
+
<!-- /react-only -->
|
|
148
|
+
|
|
149
|
+
## Word Split with Stagger
|
|
150
|
+
|
|
151
|
+
<!-- html-only -->
|
|
152
|
+
Use `split="word"` to animate each word independently with stagger delays.
|
|
153
|
+
|
|
154
|
+
```html live
|
|
155
|
+
<ef-timegroup mode="contain" class="w-[720px] h-[480px] bg-black flex items-center justify-center">
|
|
156
|
+
<ef-text split="word" stagger="100ms" duration="4s" class="text-white text-3xl">
|
|
157
|
+
<template>
|
|
158
|
+
<ef-text-segment class="fade-in"></ef-text-segment>
|
|
159
|
+
</template>
|
|
160
|
+
Each word appears with timing
|
|
161
|
+
</ef-text>
|
|
162
|
+
|
|
163
|
+
<style>
|
|
164
|
+
@keyframes fadeIn {
|
|
165
|
+
from { opacity: 0; transform: translateY(20px); }
|
|
166
|
+
to { opacity: 1; transform: translateY(0); }
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
.fade-in {
|
|
170
|
+
animation: fadeIn 0.5s ease-out;
|
|
171
|
+
animation-delay: var(--ef-stagger-offset);
|
|
172
|
+
}
|
|
173
|
+
</style>
|
|
174
|
+
</ef-timegroup>
|
|
175
|
+
```
|
|
176
|
+
<!-- /html-only -->
|
|
177
|
+
<!-- react-only -->
|
|
178
|
+
Control individual words with `TextSegment`:
|
|
179
|
+
|
|
180
|
+
```tsx
|
|
181
|
+
<Text duration="3s" className="text-white text-4xl">
|
|
182
|
+
<TextSegment className="text-red-500">Red</TextSegment>
|
|
183
|
+
{" "}
|
|
184
|
+
<TextSegment className="text-blue-500">Blue</TextSegment>
|
|
185
|
+
{" "}
|
|
186
|
+
<TextSegment className="text-green-500">Green</TextSegment>
|
|
187
|
+
</Text>
|
|
188
|
+
```
|
|
189
|
+
<!-- /react-only -->
|
|
190
|
+
|
|
191
|
+
## Character-by-Character Animation
|
|
192
|
+
|
|
193
|
+
<!-- html-only -->
|
|
194
|
+
Use `split="char"` for character-level effects.
|
|
195
|
+
|
|
196
|
+
```html live
|
|
197
|
+
<ef-timegroup mode="contain" class="w-[720px] h-[480px] bg-black flex items-center justify-center">
|
|
198
|
+
<ef-text split="char" stagger="30ms" duration="3s" class="text-yellow-400 text-5xl font-bold">
|
|
199
|
+
<template>
|
|
200
|
+
<ef-text-segment class="char-slide"></ef-text-segment>
|
|
201
|
+
</template>
|
|
202
|
+
HEADLINES
|
|
203
|
+
</ef-text>
|
|
204
|
+
|
|
205
|
+
<style>
|
|
206
|
+
@keyframes charSlide {
|
|
207
|
+
from { opacity: 0; transform: translateX(-20px) rotate(-5deg); }
|
|
208
|
+
to { opacity: 1; transform: translateX(0) rotate(0); }
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
.char-slide {
|
|
212
|
+
animation: charSlide 0.3s ease-out;
|
|
213
|
+
animation-delay: var(--ef-stagger-offset);
|
|
214
|
+
}
|
|
215
|
+
</style>
|
|
216
|
+
</ef-timegroup>
|
|
217
|
+
```
|
|
218
|
+
<!-- /html-only -->
|
|
219
|
+
|
|
220
|
+
## Line-by-Line Reveal
|
|
221
|
+
|
|
222
|
+
<!-- html-only -->
|
|
223
|
+
Use `split="line"` for line-based animations.
|
|
224
|
+
|
|
225
|
+
```html live
|
|
226
|
+
<ef-timegroup mode="contain" class="w-[720px] h-[480px] bg-black flex items-center justify-center">
|
|
227
|
+
<ef-text split="line" stagger="800ms" duration="5s" class="text-white text-2xl text-center">
|
|
228
|
+
<template>
|
|
229
|
+
<ef-text-segment class="line-reveal"></ef-text-segment>
|
|
230
|
+
</template>
|
|
231
|
+
First line appears
|
|
232
|
+
Then the second line
|
|
233
|
+
Finally the third line
|
|
234
|
+
</ef-text>
|
|
235
|
+
|
|
236
|
+
<style>
|
|
237
|
+
@keyframes lineReveal {
|
|
238
|
+
from { opacity: 0; transform: translateX(-40px); }
|
|
239
|
+
to { opacity: 1; transform: translateX(0); }
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
.line-reveal {
|
|
243
|
+
animation: lineReveal 0.6s ease-out;
|
|
244
|
+
animation-delay: var(--ef-stagger-offset);
|
|
245
|
+
display: block;
|
|
246
|
+
}
|
|
247
|
+
</style>
|
|
248
|
+
</ef-timegroup>
|
|
249
|
+
```
|
|
250
|
+
<!-- /html-only -->
|
|
251
|
+
|
|
252
|
+
<!-- html-only -->
|
|
253
|
+
## Custom Animations with registerAnimations()
|
|
254
|
+
|
|
255
|
+
Use `registerAnimations()` to define reusable animation styles globally.
|
|
256
|
+
|
|
257
|
+
```html live
|
|
258
|
+
<ef-timegroup mode="contain" class="w-[720px] h-[480px] bg-black flex items-center justify-center">
|
|
259
|
+
<ef-text split="word" stagger="80ms" duration="4s" class="text-cyan-400 text-4xl font-bold">
|
|
260
|
+
<template>
|
|
261
|
+
<ef-text-segment class="bounce-in"></ef-text-segment>
|
|
262
|
+
</template>
|
|
263
|
+
BOUNCE EFFECT
|
|
264
|
+
</ef-text>
|
|
265
|
+
|
|
266
|
+
<script>
|
|
267
|
+
customElements.whenDefined('ef-text-segment').then(() => {
|
|
268
|
+
const EFTextSegment = customElements.get('ef-text-segment');
|
|
269
|
+
EFTextSegment.registerAnimations('bounce-demo', `
|
|
270
|
+
@keyframes bounceIn {
|
|
271
|
+
0% { transform: scale(0) rotate(-180deg); opacity: 0; }
|
|
272
|
+
50% { transform: scale(1.3) rotate(0deg); }
|
|
273
|
+
100% { transform: scale(1) rotate(0deg); opacity: 1; }
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
.bounce-in {
|
|
277
|
+
animation: bounceIn 0.6s cubic-bezier(0.68, -0.55, 0.265, 1.55);
|
|
278
|
+
animation-delay: var(--ef-stagger-offset);
|
|
279
|
+
}
|
|
280
|
+
`);
|
|
281
|
+
});
|
|
282
|
+
</script>
|
|
283
|
+
</ef-timegroup>
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
## Easing Options
|
|
287
|
+
|
|
288
|
+
Different easing functions create different animation feels.
|
|
289
|
+
|
|
290
|
+
```html live
|
|
291
|
+
<ef-timegroup mode="contain" class="w-[720px] h-[480px] bg-black flex flex-col items-center justify-center gap-8">
|
|
292
|
+
<!-- Linear easing -->
|
|
293
|
+
<ef-text split="word" stagger="60ms" easing="linear" duration="3s" class="text-white text-xl">
|
|
294
|
+
<template>
|
|
295
|
+
<ef-text-segment class="scale-in"></ef-text-segment>
|
|
296
|
+
</template>
|
|
297
|
+
Linear easing (constant speed)
|
|
298
|
+
</ef-text>
|
|
299
|
+
|
|
300
|
+
<!-- Ease-out easing -->
|
|
301
|
+
<ef-text split="word" stagger="60ms" easing="ease-out" duration="3s" class="text-green-400 text-xl">
|
|
302
|
+
<template>
|
|
303
|
+
<ef-text-segment class="scale-in"></ef-text-segment>
|
|
304
|
+
</template>
|
|
305
|
+
Ease-out (starts fast ends slow)
|
|
306
|
+
</ef-text>
|
|
307
|
+
|
|
308
|
+
<!-- Cubic-bezier easing -->
|
|
309
|
+
<ef-text split="word" stagger="60ms" duration="3s" class="text-blue-400 text-xl">
|
|
310
|
+
<template>
|
|
311
|
+
<ef-text-segment class="scale-bounce"></ef-text-segment>
|
|
312
|
+
</template>
|
|
313
|
+
Custom cubic-bezier (bouncy)
|
|
314
|
+
</ef-text>
|
|
315
|
+
|
|
316
|
+
<style>
|
|
317
|
+
@keyframes scaleIn {
|
|
318
|
+
from { opacity: 0; transform: scale(0); }
|
|
319
|
+
to { opacity: 1; transform: scale(1); }
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
.scale-in {
|
|
323
|
+
animation: scaleIn 0.4s;
|
|
324
|
+
animation-delay: var(--ef-stagger-offset);
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
.scale-bounce {
|
|
328
|
+
animation: scaleIn 0.5s cubic-bezier(0.68, -0.55, 0.265, 1.55);
|
|
329
|
+
animation-delay: var(--ef-stagger-offset);
|
|
330
|
+
}
|
|
331
|
+
</style>
|
|
332
|
+
</ef-timegroup>
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
## StaggerMs Timing Variations
|
|
336
|
+
|
|
337
|
+
Control the delay between segments to create different rhythms.
|
|
338
|
+
|
|
339
|
+
```html live
|
|
340
|
+
<ef-timegroup mode="contain" class="w-[720px] h-[480px] bg-black flex flex-col items-center justify-center gap-10">
|
|
341
|
+
<!-- Fast stagger -->
|
|
342
|
+
<ef-text split="word" stagger="40ms" duration="3s" class="text-white text-2xl">
|
|
343
|
+
<template>
|
|
344
|
+
<ef-text-segment class="pop-in"></ef-text-segment>
|
|
345
|
+
</template>
|
|
346
|
+
Fast stagger feels energetic
|
|
347
|
+
</ef-text>
|
|
348
|
+
|
|
349
|
+
<!-- Medium stagger -->
|
|
350
|
+
<ef-text split="word" stagger="120ms" duration="4s" class="text-yellow-400 text-2xl">
|
|
351
|
+
<template>
|
|
352
|
+
<ef-text-segment class="pop-in"></ef-text-segment>
|
|
353
|
+
</template>
|
|
354
|
+
Medium stagger is balanced
|
|
355
|
+
</ef-text>
|
|
356
|
+
|
|
357
|
+
<!-- Slow stagger -->
|
|
358
|
+
<ef-text split="word" stagger="250ms" duration="5s" class="text-pink-400 text-2xl">
|
|
359
|
+
<template>
|
|
360
|
+
<ef-text-segment class="pop-in"></ef-text-segment>
|
|
361
|
+
</template>
|
|
362
|
+
Slow stagger adds drama
|
|
363
|
+
</ef-text>
|
|
364
|
+
|
|
365
|
+
<style>
|
|
366
|
+
@keyframes popIn {
|
|
367
|
+
from { opacity: 0; transform: scale(0.5) translateY(10px); }
|
|
368
|
+
to { opacity: 1; transform: scale(1) translateY(0); }
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
.pop-in {
|
|
372
|
+
animation: popIn 0.4s ease-out;
|
|
373
|
+
animation-delay: var(--ef-stagger-offset);
|
|
374
|
+
}
|
|
375
|
+
</style>
|
|
376
|
+
</ef-timegroup>
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
## Using --ef-seed for Random Variation
|
|
380
|
+
|
|
381
|
+
The `--ef-seed` CSS variable provides deterministic randomness per segment.
|
|
382
|
+
|
|
383
|
+
```html live
|
|
384
|
+
<ef-timegroup mode="contain" class="w-[720px] h-[480px] bg-black flex items-center justify-center">
|
|
385
|
+
<ef-text split="word" stagger="100ms" duration="4s" class="text-white text-3xl">
|
|
386
|
+
<template>
|
|
387
|
+
<ef-text-segment class="random-slide"></ef-text-segment>
|
|
388
|
+
</template>
|
|
389
|
+
Words slide from random angles
|
|
390
|
+
</ef-text>
|
|
391
|
+
|
|
392
|
+
<style>
|
|
393
|
+
@keyframes randomSlide {
|
|
394
|
+
from {
|
|
395
|
+
opacity: 0;
|
|
396
|
+
transform:
|
|
397
|
+
translateX(calc(var(--ef-seed) * 80px - 40px))
|
|
398
|
+
translateY(calc(var(--ef-seed) * 60px - 30px))
|
|
399
|
+
rotate(calc(var(--ef-seed) * 60deg - 30deg));
|
|
400
|
+
}
|
|
401
|
+
to {
|
|
402
|
+
opacity: 1;
|
|
403
|
+
transform: translateX(0) translateY(0) rotate(0);
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
.random-slide {
|
|
408
|
+
animation: randomSlide 0.6s cubic-bezier(0.34, 1.56, 0.64, 1);
|
|
409
|
+
animation-delay: var(--ef-stagger-offset);
|
|
410
|
+
}
|
|
411
|
+
</style>
|
|
412
|
+
</ef-timegroup>
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
## Lower Third
|
|
416
|
+
|
|
417
|
+
```html live
|
|
418
|
+
<ef-timegroup mode="contain" class="w-[720px] h-[480px] bg-black relative">
|
|
419
|
+
<ef-text duration="4s" class="absolute bottom-16 left-4 bg-blue-600/90 text-white px-4 py-2 rounded-md text-sm font-semibold">
|
|
420
|
+
Scene Label
|
|
421
|
+
</ef-text>
|
|
422
|
+
</ef-timegroup>
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
## Multiple Segments Per Word
|
|
426
|
+
|
|
427
|
+
Create multiple segments for each text unit by using multiple `ef-text-segment` elements in the template.
|
|
428
|
+
|
|
429
|
+
```html live
|
|
430
|
+
<ef-timegroup mode="contain" class="w-[720px] h-[480px] bg-black flex items-center justify-center">
|
|
431
|
+
<ef-text split="word" stagger="120ms" duration="4s" class="text-white text-3xl">
|
|
432
|
+
<template>
|
|
433
|
+
<!-- Shadow segment behind -->
|
|
434
|
+
<ef-text-segment class="segment-shadow"></ef-text-segment>
|
|
435
|
+
<!-- Main segment on top -->
|
|
436
|
+
<ef-text-segment class="segment-main"></ef-text-segment>
|
|
437
|
+
</template>
|
|
438
|
+
Layered shadow effect
|
|
439
|
+
</ef-text>
|
|
440
|
+
|
|
441
|
+
<style>
|
|
442
|
+
.segment-shadow {
|
|
443
|
+
position: absolute;
|
|
444
|
+
color: #3b82f6;
|
|
445
|
+
filter: blur(4px);
|
|
446
|
+
animation: shadowSlide 0.6s ease-out;
|
|
447
|
+
animation-delay: var(--ef-stagger-offset);
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
.segment-main {
|
|
451
|
+
position: relative;
|
|
452
|
+
animation: mainSlide 0.6s ease-out;
|
|
453
|
+
animation-delay: var(--ef-stagger-offset);
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
@keyframes shadowSlide {
|
|
457
|
+
from { opacity: 0; transform: translate(-20px, 10px); }
|
|
458
|
+
to { opacity: 0.6; transform: translate(4px, 4px); }
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
@keyframes mainSlide {
|
|
462
|
+
from { opacity: 0; transform: translate(-20px, 0); }
|
|
463
|
+
to { opacity: 1; transform: translate(0, 0); }
|
|
464
|
+
}
|
|
465
|
+
</style>
|
|
466
|
+
</ef-timegroup>
|
|
467
|
+
```
|
|
468
|
+
|
|
469
|
+
## Unregistering Animations
|
|
470
|
+
|
|
471
|
+
Remove previously registered animations when no longer needed.
|
|
472
|
+
|
|
473
|
+
```javascript
|
|
474
|
+
const EFTextSegment = customElements.get('ef-text-segment');
|
|
475
|
+
EFTextSegment.unregisterAnimations('bounce');
|
|
476
|
+
```
|
|
477
|
+
|
|
478
|
+
## ef-text-segment Reference
|
|
479
|
+
|
|
480
|
+
`ef-text-segment` elements are automatically created by `ef-text` when using split modes. Each segment represents a word, character, or line and can be styled and animated independently.
|
|
481
|
+
|
|
482
|
+
### CSS Variables
|
|
483
|
+
|
|
484
|
+
| Variable | Type | Description |
|
|
485
|
+
|----------|------|-------------|
|
|
486
|
+
| `--ef-index` | number | Segment index (0, 1, 2, ...) |
|
|
487
|
+
| `--ef-stagger-offset` | time | Calculated stagger delay (e.g., "0ms", "100ms") |
|
|
488
|
+
| `--ef-seed` | number | Deterministic random (0-1) based on index |
|
|
489
|
+
|
|
490
|
+
### Technical Notes
|
|
491
|
+
|
|
492
|
+
- Segments are automatically created by `ef-text` when using split modes
|
|
493
|
+
- Segments inherit animation properties from parent `ef-text` element
|
|
494
|
+
- `registerAnimations()` uses adopted stylesheets for efficient global sharing
|
|
495
|
+
- Non-whitespace segments automatically become `inline-block` when animated to enable transforms
|
|
496
|
+
- Whitespace segments remain `inline` to preserve text flow
|
|
497
|
+
<!-- /html-only -->
|
|
498
|
+
|
|
499
|
+
<!-- react-only -->
|
|
500
|
+
## Dynamic Text
|
|
501
|
+
|
|
502
|
+
```tsx
|
|
503
|
+
interface TitleData {
|
|
504
|
+
text: string;
|
|
505
|
+
duration: string;
|
|
506
|
+
className: string;
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
const titles: TitleData[] = [
|
|
510
|
+
{ text: "Scene 1", duration: "3s", className: "text-red-500" },
|
|
511
|
+
{ text: "Scene 2", duration: "3s", className: "text-blue-500" },
|
|
512
|
+
{ text: "Scene 3", duration: "3s", className: "text-green-500" },
|
|
513
|
+
];
|
|
514
|
+
|
|
515
|
+
<Timegroup mode="sequence" className="w-[800px] h-[500px]">
|
|
516
|
+
{titles.map((title, i) => (
|
|
517
|
+
<Timegroup key={i} mode="fixed" duration={title.duration} className="absolute w-full h-full flex items-center justify-center">
|
|
518
|
+
<Text duration={title.duration} className={`text-4xl ${title.className}`}>
|
|
519
|
+
{title.text}
|
|
520
|
+
</Text>
|
|
521
|
+
</Timegroup>
|
|
522
|
+
))}
|
|
523
|
+
</Timegroup>
|
|
524
|
+
```
|
|
525
|
+
|
|
526
|
+
## Text with Background
|
|
527
|
+
|
|
528
|
+
```tsx
|
|
529
|
+
<Text
|
|
530
|
+
duration="5s"
|
|
531
|
+
className="bg-black/50 text-white text-3xl px-4 py-2 rounded"
|
|
532
|
+
>
|
|
533
|
+
Overlay Text
|
|
534
|
+
</Text>
|
|
535
|
+
```
|
|
536
|
+
|
|
537
|
+
## Multi-line Text
|
|
538
|
+
|
|
539
|
+
```tsx
|
|
540
|
+
<Text
|
|
541
|
+
duration="5s"
|
|
542
|
+
className="text-white text-2xl text-center max-w-[600px]"
|
|
543
|
+
>
|
|
544
|
+
This is a longer text that will wrap across multiple lines
|
|
545
|
+
when it reaches the maximum width.
|
|
546
|
+
</Text>
|
|
547
|
+
```
|
|
548
|
+
|
|
549
|
+
## Animated Text with useTimingInfo
|
|
550
|
+
|
|
551
|
+
```tsx
|
|
552
|
+
import { Text } from "@editframe/react";
|
|
553
|
+
import { useTimingInfo } from "@editframe/react";
|
|
554
|
+
|
|
555
|
+
const FadingText = ({ children }: { children: React.ReactNode }) => {
|
|
556
|
+
const { ref, percentComplete } = useTimingInfo();
|
|
557
|
+
|
|
558
|
+
return (
|
|
559
|
+
<Text
|
|
560
|
+
ref={ref}
|
|
561
|
+
duration="5s"
|
|
562
|
+
className="text-white text-4xl"
|
|
563
|
+
style={{ opacity: percentComplete }}
|
|
564
|
+
>
|
|
565
|
+
{children}
|
|
566
|
+
</Text>
|
|
567
|
+
);
|
|
568
|
+
};
|
|
569
|
+
```
|
|
570
|
+
|
|
571
|
+
## Register Custom Animations
|
|
572
|
+
|
|
573
|
+
Use `TextSegment.registerAnimations()` to define animations shared across all segments:
|
|
574
|
+
|
|
575
|
+
```tsx
|
|
576
|
+
import { TextSegment } from "@editframe/react";
|
|
577
|
+
|
|
578
|
+
TextSegment.registerAnimations("customAnimations", `
|
|
579
|
+
@keyframes slideIn {
|
|
580
|
+
from { transform: translateX(-100%); opacity: 0; }
|
|
581
|
+
to { transform: translateX(0); opacity: 1; }
|
|
582
|
+
}
|
|
583
|
+
.slide-in { animation: slideIn 0.5s ease-out; }
|
|
584
|
+
`);
|
|
585
|
+
|
|
586
|
+
const AnimatedText = () => (
|
|
587
|
+
<Text duration="5s" className="text-white text-4xl">
|
|
588
|
+
<TextSegment className="slide-in inline-block">Slides</TextSegment>
|
|
589
|
+
{" "}
|
|
590
|
+
<TextSegment className="bounce-in inline-block">Bounces</TextSegment>
|
|
591
|
+
</Text>
|
|
592
|
+
);
|
|
593
|
+
```
|
|
594
|
+
|
|
595
|
+
Unregister animations when no longer needed:
|
|
596
|
+
|
|
597
|
+
```tsx
|
|
598
|
+
import { useEffect } from "react";
|
|
599
|
+
import { TextSegment } from "@editframe/react";
|
|
600
|
+
|
|
601
|
+
const MyComponent = () => {
|
|
602
|
+
useEffect(() => {
|
|
603
|
+
TextSegment.registerAnimations("myAnimations", `/* styles */`);
|
|
604
|
+
return () => {
|
|
605
|
+
TextSegment.unregisterAnimations("myAnimations");
|
|
606
|
+
};
|
|
607
|
+
}, []);
|
|
608
|
+
|
|
609
|
+
return (/* ... */);
|
|
610
|
+
};
|
|
611
|
+
```
|
|
612
|
+
|
|
613
|
+
## TextSegment Reference
|
|
614
|
+
|
|
615
|
+
Each TextSegment has access to CSS variables for advanced animations:
|
|
616
|
+
|
|
617
|
+
| Variable | Type | Description |
|
|
618
|
+
|----------|------|-------------|
|
|
619
|
+
| `--ef-index` | number | Segment index (0, 1, 2, ...) |
|
|
620
|
+
| `--ef-stagger-offset` | time | Calculated stagger delay |
|
|
621
|
+
| `--ef-seed` | number | Deterministic random (0-1) based on index |
|
|
622
|
+
|
|
623
|
+
- TextSegment requires a parent `Text` component
|
|
624
|
+
- Use `inline-block` display for transform animations to work correctly
|
|
625
|
+
- Animation styles are shared globally across all TextSegment instances
|
|
626
|
+
- Each segment's `--ef-seed` value is deterministic based on its index
|
|
627
|
+
<!-- /react-only -->
|