egaki 0.5.0 → 0.7.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/CHANGELOG.md +188 -0
- package/dist/cli/cache-utils.d.ts +33 -0
- package/dist/cli/cache-utils.d.ts.map +1 -0
- package/dist/cli/cache-utils.js +157 -0
- package/dist/cli/cached-generate.d.ts +105 -0
- package/dist/cli/cached-generate.d.ts.map +1 -0
- package/dist/cli/cached-generate.js +208 -0
- package/dist/cli/cached-generate.test.d.ts +11 -0
- package/dist/cli/cached-generate.test.d.ts.map +1 -0
- package/dist/cli/cached-generate.test.js +431 -0
- package/dist/cli/cartesia-provider.d.ts +16 -0
- package/dist/cli/cartesia-provider.d.ts.map +1 -0
- package/dist/cli/cartesia-provider.js +184 -0
- package/dist/cli/chatgpt-auth.d.ts.map +1 -0
- package/dist/cli/cli.d.ts +4 -0
- package/dist/cli/cli.d.ts.map +1 -0
- package/dist/cli/cli.js +1329 -0
- package/dist/cli/clone-generate.d.ts +26 -0
- package/dist/cli/clone-generate.d.ts.map +1 -0
- package/dist/cli/clone-generate.js +148 -0
- package/dist/{credentials.d.ts → cli/credentials.d.ts} +11 -2
- package/dist/cli/credentials.d.ts.map +1 -0
- package/dist/{credentials.js → cli/credentials.js} +88 -5
- package/dist/cli/elevenlabs-speech-provider.d.ts +26 -0
- package/dist/cli/elevenlabs-speech-provider.d.ts.map +1 -0
- package/dist/cli/elevenlabs-speech-provider.js +199 -0
- package/dist/cli/generate.d.ts +140 -0
- package/dist/cli/generate.d.ts.map +1 -0
- package/dist/cli/generate.js +604 -0
- package/dist/cli/generate.test.d.ts +2 -0
- package/dist/cli/generate.test.d.ts.map +1 -0
- package/dist/cli/generate.test.js +131 -0
- package/dist/cli/login.d.ts.map +1 -0
- package/dist/{login.js → cli/login.js} +45 -4
- package/dist/cli/main.d.ts +3 -0
- package/dist/cli/main.d.ts.map +1 -0
- package/dist/cli/main.js +7 -0
- package/dist/cli/model-catalog.d.ts +141 -0
- package/dist/cli/model-catalog.d.ts.map +1 -0
- package/dist/cli/model-catalog.js +2135 -0
- package/dist/{models.d.ts → cli/models.d.ts} +16 -9
- package/dist/cli/models.d.ts.map +1 -0
- package/dist/cli/models.js +313 -0
- package/dist/cli/open-browser.d.ts.map +1 -0
- package/dist/cli/openai-speech-provider.d.ts +3 -0
- package/dist/cli/openai-speech-provider.d.ts.map +1 -0
- package/dist/cli/openai-speech-provider.js +28 -0
- package/dist/cli/separation-generate.d.ts +34 -0
- package/dist/cli/separation-generate.d.ts.map +1 -0
- package/dist/cli/separation-generate.js +117 -0
- package/dist/cli/speech-catalog.d.ts +35 -0
- package/dist/cli/speech-catalog.d.ts.map +1 -0
- package/dist/cli/speech-catalog.js +195 -0
- package/dist/cli/speech-generate.d.ts +86 -0
- package/dist/cli/speech-generate.d.ts.map +1 -0
- package/dist/cli/speech-generate.js +156 -0
- package/dist/cli/speech-models.d.ts +8 -0
- package/dist/cli/speech-models.d.ts.map +1 -0
- package/dist/cli/speech-models.js +109 -0
- package/dist/cli/speech-provider.test.d.ts +2 -0
- package/dist/cli/speech-provider.test.d.ts.map +1 -0
- package/dist/cli/speech-provider.test.js +197 -0
- package/dist/cli/subscription.d.ts.map +1 -0
- package/dist/cli/transcription-catalog.d.ts +35 -0
- package/dist/cli/transcription-catalog.d.ts.map +1 -0
- package/dist/cli/transcription-catalog.js +192 -0
- package/dist/cli/transcription-generate.d.ts +62 -0
- package/dist/cli/transcription-generate.d.ts.map +1 -0
- package/dist/cli/transcription-generate.js +144 -0
- package/dist/cli/transcription-models.d.ts +9 -0
- package/dist/cli/transcription-models.d.ts.map +1 -0
- package/dist/cli/transcription-models.js +100 -0
- package/dist/cli/transcription-providers.d.ts +22 -0
- package/dist/cli/transcription-providers.d.ts.map +1 -0
- package/dist/cli/transcription-providers.js +290 -0
- package/dist/cli/video-model-catalog.d.ts +2 -0
- package/dist/cli/video-model-catalog.d.ts.map +1 -0
- package/dist/cli/video-model-catalog.js +5 -0
- package/dist/cli/xai-auth.d.ts +29 -0
- package/dist/cli/xai-auth.d.ts.map +1 -0
- package/dist/cli/xai-auth.js +325 -0
- package/dist/vite/angled-screen.d.ts +57 -0
- package/dist/vite/angled-screen.d.ts.map +1 -0
- package/dist/vite/angled-screen.js +115 -0
- package/dist/vite/app.d.ts +51 -0
- package/dist/vite/app.d.ts.map +1 -0
- package/dist/vite/app.js +150 -0
- package/dist/vite/bands-shader.d.ts +47 -0
- package/dist/vite/bands-shader.d.ts.map +1 -0
- package/dist/vite/bands-shader.js +267 -0
- package/dist/vite/code-block.d.ts +107 -0
- package/dist/vite/code-block.d.ts.map +1 -0
- package/dist/vite/code-block.js +641 -0
- package/dist/vite/components.d.ts +36 -0
- package/dist/vite/components.d.ts.map +1 -0
- package/dist/vite/components.js +113 -0
- package/dist/vite/dispersion-rings-shader.d.ts +44 -0
- package/dist/vite/dispersion-rings-shader.d.ts.map +1 -0
- package/dist/vite/dispersion-rings-shader.js +282 -0
- package/dist/vite/easing-curves.d.ts +129 -0
- package/dist/vite/easing-curves.d.ts.map +1 -0
- package/dist/vite/easing-curves.js +584 -0
- package/dist/vite/easing-curves.test.d.ts +2 -0
- package/dist/vite/easing-curves.test.d.ts.map +1 -0
- package/dist/vite/easing-curves.test.js +200 -0
- package/dist/vite/generated-media-client.d.ts +35 -0
- package/dist/vite/generated-media-client.d.ts.map +1 -0
- package/dist/vite/generated-media-client.js +76 -0
- package/dist/vite/keyframes.d.ts +129 -0
- package/dist/vite/keyframes.d.ts.map +1 -0
- package/dist/vite/keyframes.js +194 -0
- package/dist/vite/layout-editor.d.ts +45 -0
- package/dist/vite/layout-editor.d.ts.map +1 -0
- package/dist/vite/layout-editor.js +587 -0
- package/dist/vite/layout-transition.d.ts +136 -0
- package/dist/vite/layout-transition.d.ts.map +1 -0
- package/dist/vite/layout-transition.js +581 -0
- package/dist/vite/liquid-gradient-shader.d.ts +62 -0
- package/dist/vite/liquid-gradient-shader.d.ts.map +1 -0
- package/dist/vite/liquid-gradient-shader.js +413 -0
- package/dist/vite/mdx-client.d.ts +15 -0
- package/dist/vite/mdx-client.d.ts.map +1 -0
- package/dist/vite/mdx-client.js +265 -0
- package/dist/vite/mdx-parse.d.ts +102 -0
- package/dist/vite/mdx-parse.d.ts.map +1 -0
- package/dist/vite/mdx-parse.js +251 -0
- package/dist/vite/mdx-provided-components.d.ts +18 -0
- package/dist/vite/mdx-provided-components.d.ts.map +1 -0
- package/dist/vite/mdx-provided-components.js +14 -0
- package/dist/vite/mdx-video.d.ts +327 -0
- package/dist/vite/mdx-video.d.ts.map +1 -0
- package/dist/vite/mdx-video.js +596 -0
- package/dist/vite/mdx-video.test.d.ts +9 -0
- package/dist/vite/mdx-video.test.d.ts.map +1 -0
- package/dist/vite/mdx-video.test.js +1945 -0
- package/dist/vite/media-components.d.ts +45 -0
- package/dist/vite/media-components.d.ts.map +1 -0
- package/dist/vite/media-components.js +355 -0
- package/dist/vite/media-duration-store.d.ts +66 -0
- package/dist/vite/media-duration-store.d.ts.map +1 -0
- package/dist/vite/media-duration-store.js +204 -0
- package/dist/vite/player-page.d.ts +35 -0
- package/dist/vite/player-page.d.ts.map +1 -0
- package/dist/vite/player-page.js +720 -0
- package/dist/vite/render-client.d.ts +18 -0
- package/dist/vite/render-client.d.ts.map +1 -0
- package/dist/vite/render-client.js +67 -0
- package/dist/vite/sdk.d.ts +221 -0
- package/dist/vite/sdk.d.ts.map +1 -0
- package/dist/vite/sdk.js +355 -0
- package/dist/vite/server-components.d.ts +55 -0
- package/dist/vite/server-components.d.ts.map +1 -0
- package/dist/vite/server-components.js +156 -0
- package/dist/vite/server-mdx.d.ts +74 -0
- package/dist/vite/server-mdx.d.ts.map +1 -0
- package/dist/vite/server-mdx.js +259 -0
- package/dist/vite/shader-renderer.d.ts +48 -0
- package/dist/vite/shader-renderer.d.ts.map +1 -0
- package/dist/vite/shader-renderer.js +411 -0
- package/dist/vite/store-hooks.d.ts +12 -0
- package/dist/vite/store-hooks.d.ts.map +1 -0
- package/dist/vite/store-hooks.js +93 -0
- package/dist/vite/store.d.ts +75 -0
- package/dist/vite/store.d.ts.map +1 -0
- package/dist/vite/store.js +52 -0
- package/dist/vite/store.test.d.ts +6 -0
- package/dist/vite/store.test.d.ts.map +1 -0
- package/dist/vite/store.test.js +172 -0
- package/dist/vite/tweakpane-hook.d.ts +94 -0
- package/dist/vite/tweakpane-hook.d.ts.map +1 -0
- package/dist/vite/tweakpane-hook.js +450 -0
- package/dist/vite/vite-plugin.d.ts +28 -0
- package/dist/vite/vite-plugin.d.ts.map +1 -0
- package/dist/vite/vite-plugin.js +538 -0
- package/dist/vite/wave-gradient-shader.d.ts +41 -0
- package/dist/vite/wave-gradient-shader.d.ts.map +1 -0
- package/dist/vite/wave-gradient-shader.js +207 -0
- package/package.json +103 -25
- package/skills/egaki/SKILL.md +162 -1
- package/src/cli/cache-utils.ts +169 -0
- package/src/cli/cached-generate.test.ts +531 -0
- package/src/cli/cached-generate.ts +348 -0
- package/src/cli/cartesia-provider.ts +249 -0
- package/src/cli/cli.ts +1818 -0
- package/src/cli/clone-generate.ts +202 -0
- package/src/{credentials.ts → cli/credentials.ts} +90 -7
- package/src/cli/elevenlabs-speech-provider.ts +243 -0
- package/src/cli/generate.test.ts +166 -0
- package/src/cli/generate.ts +912 -0
- package/src/{login.ts → cli/login.ts} +48 -3
- package/src/cli/main.ts +8 -0
- package/src/cli/model-catalog.ts +2336 -0
- package/src/cli/models.ts +408 -0
- package/src/cli/openai-speech-provider.ts +34 -0
- package/src/cli/separation-generate.ts +187 -0
- package/src/cli/speech-catalog.ts +253 -0
- package/src/cli/speech-generate.ts +275 -0
- package/src/cli/speech-models.ts +146 -0
- package/src/cli/speech-provider.test.ts +226 -0
- package/src/cli/transcription-catalog.ts +250 -0
- package/src/cli/transcription-generate.ts +214 -0
- package/src/cli/transcription-models.ts +136 -0
- package/src/cli/transcription-providers.ts +427 -0
- package/src/cli/video-model-catalog.ts +14 -0
- package/src/cli/xai-auth.ts +396 -0
- package/src/vite/angled-screen.tsx +214 -0
- package/src/vite/app.tsx +197 -0
- package/src/vite/bands-shader.tsx +319 -0
- package/src/vite/code-block.tsx +939 -0
- package/src/vite/components.tsx +278 -0
- package/src/vite/dispersion-rings-shader.tsx +331 -0
- package/src/vite/easing-curves.test.ts +232 -0
- package/src/vite/easing-curves.ts +743 -0
- package/src/vite/generated-media-client.tsx +121 -0
- package/src/vite/keyframes.tsx +347 -0
- package/src/vite/layout-editor.tsx +709 -0
- package/src/vite/layout-transition.tsx +706 -0
- package/src/vite/liquid-gradient-shader.tsx +474 -0
- package/src/vite/mdx-client.tsx +420 -0
- package/src/vite/mdx-parse.ts +343 -0
- package/src/vite/mdx-provided-components.ts +19 -0
- package/src/vite/mdx-video.test.tsx +2219 -0
- package/src/vite/mdx-video.tsx +976 -0
- package/src/vite/media-components.tsx +473 -0
- package/src/vite/media-duration-store.ts +225 -0
- package/src/vite/motion-timing.ts +194 -0
- package/src/vite/player-page.tsx +1107 -0
- package/src/vite/render-client.ts +84 -0
- package/src/vite/sdk.ts +598 -0
- package/src/vite/server-components.tsx +241 -0
- package/src/vite/server-mdx.ts +285 -0
- package/src/vite/shader-renderer.tsx +535 -0
- package/src/vite/store-hooks.ts +117 -0
- package/src/vite/store.test.ts +202 -0
- package/src/vite/store.ts +115 -0
- package/src/vite/styles.css +21 -0
- package/src/vite/tweakpane-hook.tsx +593 -0
- package/src/vite/virtual-modules.d.ts +30 -0
- package/src/vite/vite-plugin.ts +584 -0
- package/src/vite/wave-gradient-shader.tsx +253 -0
- package/README.md +0 -266
- package/dist/antigravity-auth.d.ts +0 -15
- package/dist/antigravity-auth.d.ts.map +0 -1
- package/dist/antigravity-auth.js +0 -544
- package/dist/antigravity-image.d.ts +0 -11
- package/dist/antigravity-image.d.ts.map +0 -1
- package/dist/antigravity-image.js +0 -285
- package/dist/chatgpt-auth.d.ts.map +0 -1
- package/dist/cli.d.ts +0 -3
- package/dist/cli.d.ts.map +0 -1
- package/dist/cli.js +0 -968
- package/dist/credentials.d.ts.map +0 -1
- package/dist/gateway-model-candidates.generated.d.ts +0 -11
- package/dist/gateway-model-candidates.generated.d.ts.map +0 -1
- package/dist/gateway-model-candidates.generated.js +0 -64
- package/dist/login.d.ts.map +0 -1
- package/dist/model-catalog.d.ts +0 -42
- package/dist/model-catalog.d.ts.map +0 -1
- package/dist/model-catalog.js +0 -1001
- package/dist/models.d.ts.map +0 -1
- package/dist/models.js +0 -246
- package/dist/open-browser.d.ts.map +0 -1
- package/dist/subscription.d.ts.map +0 -1
- package/dist/video-model-catalog.d.ts +0 -52
- package/dist/video-model-catalog.d.ts.map +0 -1
- package/dist/video-model-catalog.js +0 -306
- package/src/cli.ts +0 -1378
- package/src/model-catalog.ts +0 -1077
- package/src/models.ts +0 -309
- package/src/video-model-catalog.ts +0 -363
- /package/dist/{chatgpt-auth.d.ts → cli/chatgpt-auth.d.ts} +0 -0
- /package/dist/{chatgpt-auth.js → cli/chatgpt-auth.js} +0 -0
- /package/dist/{login.d.ts → cli/login.d.ts} +0 -0
- /package/dist/{open-browser.d.ts → cli/open-browser.d.ts} +0 -0
- /package/dist/{open-browser.js → cli/open-browser.js} +0 -0
- /package/dist/{subscription.d.ts → cli/subscription.d.ts} +0 -0
- /package/dist/{subscription.js → cli/subscription.js} +0 -0
- /package/src/{chatgpt-auth.ts → cli/chatgpt-auth.ts} +0 -0
- /package/src/{open-browser.ts → cli/open-browser.ts} +0 -0
- /package/src/{subscription.ts → cli/subscription.ts} +0 -0
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Visual text effect components for egaki video.
|
|
5
|
+
*
|
|
6
|
+
* Must be 'use client' because they use Remotion hooks (useCurrentFrame,
|
|
7
|
+
* useVideoConfig, spring, interpolate) which only work inside the Player
|
|
8
|
+
* render context on the client.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import {
|
|
12
|
+
AbsoluteFill,
|
|
13
|
+
interpolate,
|
|
14
|
+
spring,
|
|
15
|
+
useCurrentFrame,
|
|
16
|
+
useVideoConfig,
|
|
17
|
+
} from 'remotion'
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
// ---------------------------------------------------------------------------
|
|
21
|
+
// Shared constants
|
|
22
|
+
// ---------------------------------------------------------------------------
|
|
23
|
+
|
|
24
|
+
const FONT_SANS =
|
|
25
|
+
'-apple-system, BlinkMacSystemFont, "SF Pro Display", "Segoe UI", sans-serif'
|
|
26
|
+
|
|
27
|
+
// ---------------------------------------------------------------------------
|
|
28
|
+
// BlurReveal — text fades in from blurred to sharp
|
|
29
|
+
// ---------------------------------------------------------------------------
|
|
30
|
+
|
|
31
|
+
export interface BlurRevealProps {
|
|
32
|
+
text: string
|
|
33
|
+
blur?: number
|
|
34
|
+
fontSize?: number
|
|
35
|
+
color?: string
|
|
36
|
+
fontWeight?: number
|
|
37
|
+
/** Duration of the reveal in frames (defaults to 60% of composition) */
|
|
38
|
+
revealFrames?: number
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function BlurReveal({
|
|
42
|
+
text,
|
|
43
|
+
blur = 20,
|
|
44
|
+
fontSize = 96,
|
|
45
|
+
color = '#fafafa',
|
|
46
|
+
fontWeight = 700,
|
|
47
|
+
revealFrames,
|
|
48
|
+
}: BlurRevealProps) {
|
|
49
|
+
const frame = useCurrentFrame()
|
|
50
|
+
const { durationInFrames } = useVideoConfig()
|
|
51
|
+
const dur = revealFrames ?? durationInFrames * 0.6
|
|
52
|
+
|
|
53
|
+
const opacity = interpolate(frame, [0, dur], [0, 1], {
|
|
54
|
+
extrapolateRight: 'clamp',
|
|
55
|
+
})
|
|
56
|
+
const blurAmount = interpolate(frame, [0, dur], [blur, 0], {
|
|
57
|
+
extrapolateRight: 'clamp',
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
return (
|
|
61
|
+
<AbsoluteFill
|
|
62
|
+
style={{ display: 'flex', alignItems: 'center', justifyContent: 'center' }}
|
|
63
|
+
>
|
|
64
|
+
<span
|
|
65
|
+
style={{
|
|
66
|
+
opacity,
|
|
67
|
+
filter: `blur(${blurAmount}px)`,
|
|
68
|
+
fontSize,
|
|
69
|
+
fontWeight,
|
|
70
|
+
color,
|
|
71
|
+
letterSpacing: '-0.04em',
|
|
72
|
+
fontFamily: FONT_SANS,
|
|
73
|
+
}}
|
|
74
|
+
>
|
|
75
|
+
{text}
|
|
76
|
+
</span>
|
|
77
|
+
</AbsoluteFill>
|
|
78
|
+
)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// ---------------------------------------------------------------------------
|
|
82
|
+
// MaskedSlideReveal — words slide up from behind a mask
|
|
83
|
+
// ---------------------------------------------------------------------------
|
|
84
|
+
|
|
85
|
+
export interface MaskedSlideRevealProps {
|
|
86
|
+
text: string
|
|
87
|
+
staggerDelay?: number
|
|
88
|
+
fontSize?: number
|
|
89
|
+
color?: string
|
|
90
|
+
fontWeight?: number
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export function MaskedSlideReveal({
|
|
94
|
+
text,
|
|
95
|
+
staggerDelay = 3,
|
|
96
|
+
fontSize = 56,
|
|
97
|
+
color = '#fafafa',
|
|
98
|
+
fontWeight = 600,
|
|
99
|
+
}: MaskedSlideRevealProps) {
|
|
100
|
+
const frame = useCurrentFrame()
|
|
101
|
+
const { fps } = useVideoConfig()
|
|
102
|
+
const words = text.split(' ')
|
|
103
|
+
|
|
104
|
+
return (
|
|
105
|
+
<AbsoluteFill
|
|
106
|
+
style={{ display: 'flex', alignItems: 'center', justifyContent: 'center' }}
|
|
107
|
+
>
|
|
108
|
+
<span
|
|
109
|
+
style={{
|
|
110
|
+
fontSize,
|
|
111
|
+
fontWeight,
|
|
112
|
+
color,
|
|
113
|
+
letterSpacing: '-0.03em',
|
|
114
|
+
fontFamily: FONT_SANS,
|
|
115
|
+
}}
|
|
116
|
+
>
|
|
117
|
+
{words.map((word, i) => {
|
|
118
|
+
const t = spring({
|
|
119
|
+
frame: frame - i * staggerDelay,
|
|
120
|
+
fps,
|
|
121
|
+
config: { damping: 14 },
|
|
122
|
+
})
|
|
123
|
+
return (
|
|
124
|
+
<span
|
|
125
|
+
key={i}
|
|
126
|
+
style={{
|
|
127
|
+
display: 'inline-block',
|
|
128
|
+
overflow: 'hidden',
|
|
129
|
+
verticalAlign: 'bottom',
|
|
130
|
+
lineHeight: 1.1,
|
|
131
|
+
marginRight: '0.25em',
|
|
132
|
+
}}
|
|
133
|
+
>
|
|
134
|
+
<span
|
|
135
|
+
style={{
|
|
136
|
+
display: 'inline-block',
|
|
137
|
+
transform: `translateY(${(1 - t) * 100}%)`,
|
|
138
|
+
}}
|
|
139
|
+
>
|
|
140
|
+
{word}
|
|
141
|
+
</span>
|
|
142
|
+
</span>
|
|
143
|
+
)
|
|
144
|
+
})}
|
|
145
|
+
</span>
|
|
146
|
+
</AbsoluteFill>
|
|
147
|
+
)
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// ---------------------------------------------------------------------------
|
|
151
|
+
// StaggeredFadeUp
|
|
152
|
+
// ---------------------------------------------------------------------------
|
|
153
|
+
|
|
154
|
+
export interface StaggeredFadeUpProps {
|
|
155
|
+
text: string
|
|
156
|
+
staggerDelay?: number
|
|
157
|
+
distance?: number
|
|
158
|
+
fontSize?: number
|
|
159
|
+
color?: string
|
|
160
|
+
fontWeight?: number
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
export function StaggeredFadeUp({
|
|
164
|
+
text,
|
|
165
|
+
staggerDelay = 4,
|
|
166
|
+
distance = 24,
|
|
167
|
+
fontSize = 48,
|
|
168
|
+
color = '#a1a1aa',
|
|
169
|
+
fontWeight = 400,
|
|
170
|
+
}: StaggeredFadeUpProps) {
|
|
171
|
+
const frame = useCurrentFrame()
|
|
172
|
+
const words = text.split(' ')
|
|
173
|
+
|
|
174
|
+
return (
|
|
175
|
+
<AbsoluteFill
|
|
176
|
+
style={{ display: 'flex', alignItems: 'center', justifyContent: 'center' }}
|
|
177
|
+
>
|
|
178
|
+
<span
|
|
179
|
+
style={{
|
|
180
|
+
fontSize,
|
|
181
|
+
fontWeight,
|
|
182
|
+
color,
|
|
183
|
+
letterSpacing: '-0.02em',
|
|
184
|
+
fontFamily: FONT_SANS,
|
|
185
|
+
}}
|
|
186
|
+
>
|
|
187
|
+
{words.map((word, i) => {
|
|
188
|
+
const local = frame - i * staggerDelay
|
|
189
|
+
const opacity = interpolate(local, [0, 14], [0, 1], {
|
|
190
|
+
extrapolateLeft: 'clamp',
|
|
191
|
+
extrapolateRight: 'clamp',
|
|
192
|
+
})
|
|
193
|
+
const y = interpolate(local, [0, 14], [distance, 0], {
|
|
194
|
+
extrapolateLeft: 'clamp',
|
|
195
|
+
extrapolateRight: 'clamp',
|
|
196
|
+
})
|
|
197
|
+
return (
|
|
198
|
+
<span
|
|
199
|
+
key={i}
|
|
200
|
+
style={{
|
|
201
|
+
display: 'inline-block',
|
|
202
|
+
marginRight: '0.25em',
|
|
203
|
+
opacity,
|
|
204
|
+
transform: `translateY(${y}px)`,
|
|
205
|
+
}}
|
|
206
|
+
>
|
|
207
|
+
{word}
|
|
208
|
+
</span>
|
|
209
|
+
)
|
|
210
|
+
})}
|
|
211
|
+
</span>
|
|
212
|
+
</AbsoluteFill>
|
|
213
|
+
)
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// ---------------------------------------------------------------------------
|
|
217
|
+
// ShimmerSweep — light sweep across text
|
|
218
|
+
// ---------------------------------------------------------------------------
|
|
219
|
+
|
|
220
|
+
export interface ShimmerSweepProps {
|
|
221
|
+
text: string
|
|
222
|
+
baseColor?: string
|
|
223
|
+
shineColor?: string
|
|
224
|
+
fontSize?: number
|
|
225
|
+
fontWeight?: number
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
export function ShimmerSweep({
|
|
229
|
+
text,
|
|
230
|
+
baseColor = '#52525b',
|
|
231
|
+
shineColor = '#fafafa',
|
|
232
|
+
fontSize = 72,
|
|
233
|
+
fontWeight = 700,
|
|
234
|
+
}: ShimmerSweepProps) {
|
|
235
|
+
const frame = useCurrentFrame()
|
|
236
|
+
const { durationInFrames } = useVideoConfig()
|
|
237
|
+
|
|
238
|
+
const position = interpolate(
|
|
239
|
+
frame,
|
|
240
|
+
[0, durationInFrames * 0.75],
|
|
241
|
+
[200, -100],
|
|
242
|
+
{ extrapolateLeft: 'clamp', extrapolateRight: 'clamp' },
|
|
243
|
+
)
|
|
244
|
+
|
|
245
|
+
const textStyle: React.CSSProperties = {
|
|
246
|
+
fontSize,
|
|
247
|
+
fontWeight,
|
|
248
|
+
letterSpacing: '-0.04em',
|
|
249
|
+
fontFamily: FONT_SANS,
|
|
250
|
+
margin: 0,
|
|
251
|
+
lineHeight: 1,
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
return (
|
|
255
|
+
<AbsoluteFill
|
|
256
|
+
style={{ display: 'flex', alignItems: 'center', justifyContent: 'center' }}
|
|
257
|
+
>
|
|
258
|
+
<div style={{ position: 'relative', display: 'inline-block' }}>
|
|
259
|
+
<span style={{ ...textStyle, color: baseColor }}>{text}</span>
|
|
260
|
+
<span
|
|
261
|
+
style={{
|
|
262
|
+
...textStyle,
|
|
263
|
+
position: 'absolute',
|
|
264
|
+
inset: 0,
|
|
265
|
+
color: 'transparent',
|
|
266
|
+
backgroundClip: 'text',
|
|
267
|
+
WebkitBackgroundClip: 'text',
|
|
268
|
+
backgroundImage: `linear-gradient(110deg, transparent 30%, ${shineColor} 50%, transparent 70%)`,
|
|
269
|
+
backgroundSize: '200% 100%',
|
|
270
|
+
backgroundPosition: `${position}% 50%`,
|
|
271
|
+
}}
|
|
272
|
+
>
|
|
273
|
+
{text}
|
|
274
|
+
</span>
|
|
275
|
+
</div>
|
|
276
|
+
</AbsoluteFill>
|
|
277
|
+
)
|
|
278
|
+
}
|
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* DispersionRingsShader — chromatic dispersion through concentric ring lenses.
|
|
5
|
+
*
|
|
6
|
+
* Port of Framer's DispersionRings shader module for Remotion/egaki.
|
|
7
|
+
* Original source:
|
|
8
|
+
* https://framerusercontent.com/modules/VMKsfJdfTvRVeIoDd5X9/fXq10iSPqH2cgEWzpK4N/DispersionRings.js
|
|
9
|
+
*
|
|
10
|
+
* An animated gradient of user-defined colors is distorted through concentric
|
|
11
|
+
* ring-shaped lenses radiating from the center. Each ring splits light into
|
|
12
|
+
* RGB channels at its edges (chromatic dispersion), producing rainbow fringing
|
|
13
|
+
* similar to light passing through concentric prisms. 8-sample temporal
|
|
14
|
+
* anti-aliasing with per-sample spectral weighting gives the effect a soft,
|
|
15
|
+
* photographic quality.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import type { CSSProperties } from 'react'
|
|
19
|
+
import { defineShader } from './shader-renderer.tsx'
|
|
20
|
+
|
|
21
|
+
// ---------------------------------------------------------------------------
|
|
22
|
+
// Props
|
|
23
|
+
// ---------------------------------------------------------------------------
|
|
24
|
+
|
|
25
|
+
export interface DispersionRingsShaderProps {
|
|
26
|
+
/** Color palette for the gradient (max 8). Hex strings like "#91FFCC". */
|
|
27
|
+
colors?: string[]
|
|
28
|
+
/** Seed for gradient flow directions and frequencies. Different seeds = different patterns. */
|
|
29
|
+
seed?: number
|
|
30
|
+
/** Animation speed multiplier. 0 = frozen, 0.5 = default, 2 = fast. */
|
|
31
|
+
speed?: number
|
|
32
|
+
/** Wavy spatial jitter per sample. 0 = clean, higher = dreamy/melting distortion. */
|
|
33
|
+
ephemeralAmp?: number
|
|
34
|
+
/** UV scale before the ring grid. Higher = more zoomed in, fewer visible rings. */
|
|
35
|
+
lensScale?: number
|
|
36
|
+
/** Spacing between concentric rings. Smaller = tighter rings. */
|
|
37
|
+
ringSpacing?: number
|
|
38
|
+
/** Radius of each ring lens. Controls magnification area vs flat area. */
|
|
39
|
+
ringRadius?: number
|
|
40
|
+
/** How strongly the ring lens warps UVs. Higher = more magnification. */
|
|
41
|
+
ringWarpStrength?: number
|
|
42
|
+
/** How much R and B channels diverge from G at ring edges. 0 = none, 1 = maximum. */
|
|
43
|
+
ringDispersion?: number
|
|
44
|
+
/** Extra rainbow tint multiplier at ring edges. Pushes edge colors toward prismatic look. */
|
|
45
|
+
edgeDisp?: number
|
|
46
|
+
style?: CSSProperties
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// ---------------------------------------------------------------------------
|
|
50
|
+
// Fragment shader body
|
|
51
|
+
// ---------------------------------------------------------------------------
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Raw GLSL fragment body from DispersionRings.js.
|
|
55
|
+
* The defineShader engine prepends #version, precision, v_uv, fragColor,
|
|
56
|
+
* uniform declarations, and built-in uniforms automatically.
|
|
57
|
+
*
|
|
58
|
+
* Algorithm overview:
|
|
59
|
+
* 1. Gradient flow: seed-derived sin/cos waves create an organic color field
|
|
60
|
+
* 2. Ring lens: distance from center is divided into repeating ring cells;
|
|
61
|
+
* each ring has a spherical lens that warps UVs (magnification at center,
|
|
62
|
+
* edge factor at rim)
|
|
63
|
+
* 3. Chromatic dispersion: lens applied 3x per sample (R, G, B) with different
|
|
64
|
+
* index-of-refraction offsets, splitting color channels at ring edges
|
|
65
|
+
* 4. 8-sample TAA: per-pixel random offset + spectral tint weights, averaged
|
|
66
|
+
*/
|
|
67
|
+
const FRAGMENT_SOURCE = `
|
|
68
|
+
const int SAMPLES = 8;
|
|
69
|
+
const float EPHEMERAL_DRIP = 1.0;
|
|
70
|
+
|
|
71
|
+
// === PCG hash - https://www.jcgt.org/published/0009/03/02/
|
|
72
|
+
uvec3 hash3(uvec3 v) {
|
|
73
|
+
v = v * 1664525u + 1013904223u;
|
|
74
|
+
v.x += v.y * v.z;
|
|
75
|
+
v.y += v.z * v.x;
|
|
76
|
+
v.z += v.x * v.y;
|
|
77
|
+
v ^= v >> 16u;
|
|
78
|
+
v.x += v.y * v.z;
|
|
79
|
+
v.y += v.z * v.x;
|
|
80
|
+
v.z += v.x * v.y;
|
|
81
|
+
return v;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
uvec3 seed;
|
|
85
|
+
vec3 random3f() {
|
|
86
|
+
seed = hash3(seed);
|
|
87
|
+
return vec3(seed) / float(-1u);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
vec3 seedRandom(float seedVal) {
|
|
91
|
+
uvec3 s = uvec3(
|
|
92
|
+
floatBitsToUint(seedVal),
|
|
93
|
+
floatBitsToUint(seedVal * 1.5 + 7.31),
|
|
94
|
+
floatBitsToUint(seedVal * 2.7 + 13.37)
|
|
95
|
+
);
|
|
96
|
+
s = hash3(s);
|
|
97
|
+
return vec3(s) / float(0xFFFFFFFFu);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// === PALETTE SAMPLING ===
|
|
101
|
+
vec3 getColor(int idx) {
|
|
102
|
+
if (u_colors_length < 1) return vec3(0.0);
|
|
103
|
+
int safeIdx = clamp(idx, 0, u_colors_length - 1);
|
|
104
|
+
return u_colors[safeIdx].rgb;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
vec3 paletteN(float t, int count) {
|
|
108
|
+
if (count < 1) return vec3(0.0);
|
|
109
|
+
if (count < 2) return getColor(0);
|
|
110
|
+
t = clamp(t, 0.0, 1.0) * float(count - 1);
|
|
111
|
+
int idx = min(int(floor(t)), count - 2);
|
|
112
|
+
float localT = fract(t);
|
|
113
|
+
localT = localT * localT * (3.0 - 2.0 * localT);
|
|
114
|
+
return mix(getColor(idx), getColor(idx + 1), localT);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// === Gradient Flow ===
|
|
118
|
+
float getGradientT(vec2 uv, float t, vec2 dir1, vec2 dir2, vec3 freqs, vec2 dir3) {
|
|
119
|
+
vec2 suv = uv * 1.;
|
|
120
|
+
|
|
121
|
+
float flow = dot(suv, dir1) + sin(dot(suv, dir2) * freqs.x + t) * 0.3 + t * 0.2;
|
|
122
|
+
float flow2 = dot(suv, dir2.yx) + cos(dot(suv, dir1.yx) * freqs.y - t * 0.8) * 0.25;
|
|
123
|
+
|
|
124
|
+
float gradT = sin(flow * 1.5) * 0.5 + 0.5;
|
|
125
|
+
gradT += cos(flow2 * 1.2) * 1.3;
|
|
126
|
+
gradT += sin(dot(suv, dir3) * freqs.z + t * 3.5) * 1.2;
|
|
127
|
+
|
|
128
|
+
return smoothstep(0.0, 4.12, gradT);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// === RING LENS ===
|
|
132
|
+
void applyRingLens(vec2 pp, vec2 fragCoord, vec2 r, float iorOffset, out vec2 warpedUV, out float edgeFactor) {
|
|
133
|
+
float radiusSq = u_ringRadius * u_ringRadius;
|
|
134
|
+
|
|
135
|
+
vec2 lensUV = (fragCoord - vec2(r.x * 0.5, 0.0)) / r.y * u_lensScale;
|
|
136
|
+
float dist = length(lensUV);
|
|
137
|
+
|
|
138
|
+
float fw = fwidth(dist / u_ringSpacing) * u_ringSpacing;
|
|
139
|
+
|
|
140
|
+
float ringDist = mod(dist, u_ringSpacing) / u_ringSpacing;
|
|
141
|
+
float ringShifted = ringDist - 0.5;
|
|
142
|
+
float localR = ringShifted * 2.0;
|
|
143
|
+
|
|
144
|
+
float sp = radiusSq - localR * localR;
|
|
145
|
+
|
|
146
|
+
float edgeSdf = abs(localR) - u_ringRadius;
|
|
147
|
+
float edgeAA = smoothstep(fw, -fw, edgeSdf);
|
|
148
|
+
|
|
149
|
+
float lensAmount = smoothstep(0., 0.3, sp);
|
|
150
|
+
edgeFactor = (1.0 - smoothstep(0.0, radiusSq, sp)) * lensAmount * edgeAA;
|
|
151
|
+
|
|
152
|
+
vec2 dir = lensUV / max(dist, 0.001);
|
|
153
|
+
|
|
154
|
+
warpedUV = pp;
|
|
155
|
+
if (sp > 0.0) {
|
|
156
|
+
float lens = sqrt(sp) / max(u_ringRadius, 0.001);
|
|
157
|
+
float baseWarp = mix(1.0, u_ringWarpStrength, lens);
|
|
158
|
+
float warpAmount = baseWarp * (1.0 + iorOffset);
|
|
159
|
+
float ringCenter = (floor(dist / u_ringSpacing) + 0.5) * u_ringSpacing;
|
|
160
|
+
vec2 offset = pp - dir * ringCenter;
|
|
161
|
+
warpedUV = dir * ringCenter + offset * warpAmount;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
void main() {
|
|
166
|
+
vec2 fragCoord = v_uv * u_resolution;
|
|
167
|
+
seed = uvec3(uvec2(fragCoord), uint(fract(u_time) * 1000.0));
|
|
168
|
+
|
|
169
|
+
vec2 r = u_resolution;
|
|
170
|
+
vec2 p = (fragCoord * 2.0 - r) / r.y;
|
|
171
|
+
float t = u_time * u_speed;
|
|
172
|
+
|
|
173
|
+
int colorCount = u_colors_length;
|
|
174
|
+
|
|
175
|
+
// Early out: no colors -> black
|
|
176
|
+
if (colorCount < 1) {
|
|
177
|
+
fragColor = vec4(0.0, 0.0, 0.0, 1.0);
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// Seed-based flow directions (precomputed once)
|
|
182
|
+
vec3 seedOff1 = seedRandom(u_seed);
|
|
183
|
+
vec3 seedOff2 = seedRandom(u_seed + 100.0);
|
|
184
|
+
|
|
185
|
+
float angle1 = seedOff1.x * 6.28;
|
|
186
|
+
float angle2 = seedOff1.y * 6.28;
|
|
187
|
+
vec2 dir1 = vec2(cos(angle1), sin(angle1));
|
|
188
|
+
vec2 dir2 = vec2(cos(angle2), sin(angle2));
|
|
189
|
+
vec2 dir3 = dir1 + dir2;
|
|
190
|
+
vec3 freqs = vec3(
|
|
191
|
+
1.0 + seedOff1.z * 2.0,
|
|
192
|
+
1.0 + seedOff2.x * 1.5,
|
|
193
|
+
1.5 + seedOff2.y * 2.0
|
|
194
|
+
);
|
|
195
|
+
|
|
196
|
+
float dice = random3f().x;
|
|
197
|
+
|
|
198
|
+
vec3 ringIorOffsets = vec3(-1.0, 0.0, 1.0) * u_ringDispersion;
|
|
199
|
+
|
|
200
|
+
vec3 col = vec3(0.0);
|
|
201
|
+
|
|
202
|
+
for (int i = 0; i < SAMPLES; i++) {
|
|
203
|
+
float ephemeral = (float(i) + dice) / float(SAMPLES);
|
|
204
|
+
float sqEph = ephemeral * ephemeral;
|
|
205
|
+
|
|
206
|
+
vec2 pt = p;
|
|
207
|
+
pt.x += u_ephemeralAmp * sqEph * sin(p.y * 2.0 + t);
|
|
208
|
+
pt.y += u_ephemeralAmp * sqEph * cos(p.x * 1.5 - t) * 0.5;
|
|
209
|
+
pt.y -= (1.0 - exp(-EPHEMERAL_DRIP * sqEph)) * abs(pt.y) * sign(pt.y) * 0.3;
|
|
210
|
+
|
|
211
|
+
vec3 tint = smoothstep(1.0, 0.0, abs(3.0 * ephemeral - vec3(1.0, 1.5, 2.0)));
|
|
212
|
+
|
|
213
|
+
vec3 gradTs = vec3(0.0);
|
|
214
|
+
vec3 edgeFactors = vec3(0.0);
|
|
215
|
+
|
|
216
|
+
for (int c = 0; c < 3; c++) {
|
|
217
|
+
vec2 pp = pt * u_lensScale;
|
|
218
|
+
vec2 warpedUV;
|
|
219
|
+
float edgeFactor;
|
|
220
|
+
applyRingLens(pp, fragCoord, r, ringIorOffsets[c], warpedUV, edgeFactor);
|
|
221
|
+
|
|
222
|
+
vec2 gradUV = warpedUV / u_lensScale;
|
|
223
|
+
gradTs[c] = getGradientT(gradUV, t * 0.8, dir1, dir2, freqs, dir3);
|
|
224
|
+
edgeFactors[c] = edgeFactor;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
vec3 convergentColor = paletteN(gradTs.g, colorCount);
|
|
228
|
+
float edgeMix = max(max(edgeFactors.r, edgeFactors.g), edgeFactors.b);
|
|
229
|
+
|
|
230
|
+
vec3 dispersedColor = vec3(
|
|
231
|
+
paletteN(gradTs.r, colorCount).r,
|
|
232
|
+
convergentColor.g,
|
|
233
|
+
paletteN(gradTs.b, colorCount).b
|
|
234
|
+
);
|
|
235
|
+
|
|
236
|
+
vec3 finalColor = mix(convergentColor, dispersedColor, edgeMix * 2.0);
|
|
237
|
+
|
|
238
|
+
vec3 rainbow = (gradTs - gradTs.g) * 3.0;
|
|
239
|
+
finalColor += rainbow * edgeMix * u_edgeDisp;
|
|
240
|
+
|
|
241
|
+
col += tint * finalColor * (3.0 / float(SAMPLES));
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
fragColor = vec4(col, 1.0);
|
|
245
|
+
}
|
|
246
|
+
`
|
|
247
|
+
|
|
248
|
+
// ---------------------------------------------------------------------------
|
|
249
|
+
// Component
|
|
250
|
+
// ---------------------------------------------------------------------------
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* Property controls matching the original Framer DispersionRings module.
|
|
254
|
+
* Ranges, defaults, and step sizes are preserved from the original.
|
|
255
|
+
*/
|
|
256
|
+
export const DispersionRingsShader = defineShader({
|
|
257
|
+
title: 'DispersionRingsShader',
|
|
258
|
+
fragment: FRAGMENT_SOURCE,
|
|
259
|
+
propertyControls: {
|
|
260
|
+
colors: {
|
|
261
|
+
type: 'array',
|
|
262
|
+
control: { type: 'color' },
|
|
263
|
+
maxCount: 8,
|
|
264
|
+
maxVisible: 4,
|
|
265
|
+
defaultValue: ['#91FFCC', '#FFB938', '#FF4242'],
|
|
266
|
+
},
|
|
267
|
+
seed: {
|
|
268
|
+
type: 'number',
|
|
269
|
+
defaultValue: 47,
|
|
270
|
+
min: 0,
|
|
271
|
+
max: 1000,
|
|
272
|
+
step: 1,
|
|
273
|
+
},
|
|
274
|
+
speed: {
|
|
275
|
+
type: 'number',
|
|
276
|
+
defaultValue: 0.5,
|
|
277
|
+
min: 0,
|
|
278
|
+
max: 2,
|
|
279
|
+
step: 0.01,
|
|
280
|
+
},
|
|
281
|
+
ephemeralAmp: {
|
|
282
|
+
type: 'number',
|
|
283
|
+
defaultValue: 0.12,
|
|
284
|
+
min: 0,
|
|
285
|
+
max: 0.5,
|
|
286
|
+
step: 0.01,
|
|
287
|
+
},
|
|
288
|
+
lensScale: {
|
|
289
|
+
type: 'number',
|
|
290
|
+
defaultValue: 10,
|
|
291
|
+
min: 0.1,
|
|
292
|
+
max: 10,
|
|
293
|
+
step: 0.1,
|
|
294
|
+
},
|
|
295
|
+
ringSpacing: {
|
|
296
|
+
type: 'number',
|
|
297
|
+
defaultValue: 1.5,
|
|
298
|
+
min: 0.1,
|
|
299
|
+
max: 5,
|
|
300
|
+
step: 0.1,
|
|
301
|
+
},
|
|
302
|
+
ringRadius: {
|
|
303
|
+
type: 'number',
|
|
304
|
+
defaultValue: 1,
|
|
305
|
+
min: 0.1,
|
|
306
|
+
max: 2,
|
|
307
|
+
step: 0.01,
|
|
308
|
+
},
|
|
309
|
+
ringWarpStrength: {
|
|
310
|
+
type: 'number',
|
|
311
|
+
defaultValue: 4,
|
|
312
|
+
min: 0,
|
|
313
|
+
max: 5,
|
|
314
|
+
step: 0.1,
|
|
315
|
+
},
|
|
316
|
+
ringDispersion: {
|
|
317
|
+
type: 'number',
|
|
318
|
+
defaultValue: 0.4,
|
|
319
|
+
min: 0,
|
|
320
|
+
max: 1,
|
|
321
|
+
step: 0.01,
|
|
322
|
+
},
|
|
323
|
+
edgeDisp: {
|
|
324
|
+
type: 'number',
|
|
325
|
+
defaultValue: 1.3,
|
|
326
|
+
min: 0,
|
|
327
|
+
max: 5,
|
|
328
|
+
step: 0.1,
|
|
329
|
+
},
|
|
330
|
+
},
|
|
331
|
+
}) as React.FC<DispersionRingsShaderProps>
|