egaki 0.6.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.
Files changed (271) hide show
  1. package/CHANGELOG.md +140 -9
  2. package/dist/cli/cache-utils.d.ts +33 -0
  3. package/dist/cli/cache-utils.d.ts.map +1 -0
  4. package/dist/cli/cache-utils.js +157 -0
  5. package/dist/cli/cached-generate.d.ts +105 -0
  6. package/dist/cli/cached-generate.d.ts.map +1 -0
  7. package/dist/cli/cached-generate.js +208 -0
  8. package/dist/cli/cached-generate.test.d.ts +11 -0
  9. package/dist/cli/cached-generate.test.d.ts.map +1 -0
  10. package/dist/cli/cached-generate.test.js +431 -0
  11. package/dist/cli/cartesia-provider.d.ts +16 -0
  12. package/dist/cli/cartesia-provider.d.ts.map +1 -0
  13. package/dist/cli/cartesia-provider.js +184 -0
  14. package/dist/cli/chatgpt-auth.d.ts.map +1 -0
  15. package/dist/cli/cli.d.ts +4 -0
  16. package/dist/cli/cli.d.ts.map +1 -0
  17. package/dist/{cli.js → cli/cli.js} +626 -600
  18. package/dist/cli/clone-generate.d.ts +26 -0
  19. package/dist/cli/clone-generate.d.ts.map +1 -0
  20. package/dist/cli/clone-generate.js +148 -0
  21. package/dist/cli/credentials.d.ts.map +1 -0
  22. package/dist/{credentials.js → cli/credentials.js} +20 -0
  23. package/dist/cli/elevenlabs-speech-provider.d.ts +26 -0
  24. package/dist/cli/elevenlabs-speech-provider.d.ts.map +1 -0
  25. package/dist/cli/elevenlabs-speech-provider.js +199 -0
  26. package/dist/cli/generate.d.ts +140 -0
  27. package/dist/cli/generate.d.ts.map +1 -0
  28. package/dist/cli/generate.js +604 -0
  29. package/dist/cli/generate.test.d.ts +2 -0
  30. package/dist/cli/generate.test.d.ts.map +1 -0
  31. package/dist/cli/generate.test.js +131 -0
  32. package/dist/cli/login.d.ts.map +1 -0
  33. package/dist/cli/main.d.ts +3 -0
  34. package/dist/cli/main.d.ts.map +1 -0
  35. package/dist/cli/main.js +7 -0
  36. package/dist/{model-catalog.d.ts → cli/model-catalog.d.ts} +6 -0
  37. package/dist/cli/model-catalog.d.ts.map +1 -0
  38. package/dist/{model-catalog.js → cli/model-catalog.js} +714 -4
  39. package/dist/{models.d.ts → cli/models.d.ts} +12 -5
  40. package/dist/cli/models.d.ts.map +1 -0
  41. package/dist/{models.js → cli/models.js} +58 -57
  42. package/dist/cli/open-browser.d.ts.map +1 -0
  43. package/dist/cli/openai-speech-provider.d.ts +3 -0
  44. package/dist/cli/openai-speech-provider.d.ts.map +1 -0
  45. package/dist/cli/openai-speech-provider.js +28 -0
  46. package/dist/cli/separation-generate.d.ts +34 -0
  47. package/dist/cli/separation-generate.d.ts.map +1 -0
  48. package/dist/cli/separation-generate.js +117 -0
  49. package/dist/cli/speech-catalog.d.ts +35 -0
  50. package/dist/cli/speech-catalog.d.ts.map +1 -0
  51. package/dist/cli/speech-catalog.js +195 -0
  52. package/dist/cli/speech-generate.d.ts +86 -0
  53. package/dist/cli/speech-generate.d.ts.map +1 -0
  54. package/dist/cli/speech-generate.js +156 -0
  55. package/dist/cli/speech-models.d.ts +8 -0
  56. package/dist/cli/speech-models.d.ts.map +1 -0
  57. package/dist/cli/speech-models.js +109 -0
  58. package/dist/cli/speech-provider.test.d.ts +2 -0
  59. package/dist/cli/speech-provider.test.d.ts.map +1 -0
  60. package/dist/cli/speech-provider.test.js +197 -0
  61. package/dist/cli/subscription.d.ts.map +1 -0
  62. package/dist/cli/transcription-catalog.d.ts +35 -0
  63. package/dist/cli/transcription-catalog.d.ts.map +1 -0
  64. package/dist/cli/transcription-catalog.js +192 -0
  65. package/dist/cli/transcription-generate.d.ts +62 -0
  66. package/dist/cli/transcription-generate.d.ts.map +1 -0
  67. package/dist/cli/transcription-generate.js +144 -0
  68. package/dist/cli/transcription-models.d.ts +9 -0
  69. package/dist/cli/transcription-models.d.ts.map +1 -0
  70. package/dist/cli/transcription-models.js +100 -0
  71. package/dist/cli/transcription-providers.d.ts +22 -0
  72. package/dist/cli/transcription-providers.d.ts.map +1 -0
  73. package/dist/cli/transcription-providers.js +290 -0
  74. package/dist/cli/video-model-catalog.d.ts.map +1 -0
  75. package/dist/cli/xai-auth.d.ts.map +1 -0
  76. package/dist/{xai-auth.js → cli/xai-auth.js} +1 -1
  77. package/dist/vite/angled-screen.d.ts +57 -0
  78. package/dist/vite/angled-screen.d.ts.map +1 -0
  79. package/dist/vite/angled-screen.js +115 -0
  80. package/dist/vite/app.d.ts +51 -0
  81. package/dist/vite/app.d.ts.map +1 -0
  82. package/dist/vite/app.js +150 -0
  83. package/dist/vite/bands-shader.d.ts +47 -0
  84. package/dist/vite/bands-shader.d.ts.map +1 -0
  85. package/dist/vite/bands-shader.js +267 -0
  86. package/dist/vite/code-block.d.ts +107 -0
  87. package/dist/vite/code-block.d.ts.map +1 -0
  88. package/dist/vite/code-block.js +641 -0
  89. package/dist/vite/components.d.ts +36 -0
  90. package/dist/vite/components.d.ts.map +1 -0
  91. package/dist/vite/components.js +113 -0
  92. package/dist/vite/dispersion-rings-shader.d.ts +44 -0
  93. package/dist/vite/dispersion-rings-shader.d.ts.map +1 -0
  94. package/dist/vite/dispersion-rings-shader.js +282 -0
  95. package/dist/vite/easing-curves.d.ts +129 -0
  96. package/dist/vite/easing-curves.d.ts.map +1 -0
  97. package/dist/vite/easing-curves.js +584 -0
  98. package/dist/vite/easing-curves.test.d.ts +2 -0
  99. package/dist/vite/easing-curves.test.d.ts.map +1 -0
  100. package/dist/vite/easing-curves.test.js +200 -0
  101. package/dist/vite/generated-media-client.d.ts +35 -0
  102. package/dist/vite/generated-media-client.d.ts.map +1 -0
  103. package/dist/vite/generated-media-client.js +76 -0
  104. package/dist/vite/keyframes.d.ts +129 -0
  105. package/dist/vite/keyframes.d.ts.map +1 -0
  106. package/dist/vite/keyframes.js +194 -0
  107. package/dist/vite/layout-editor.d.ts +45 -0
  108. package/dist/vite/layout-editor.d.ts.map +1 -0
  109. package/dist/vite/layout-editor.js +587 -0
  110. package/dist/vite/layout-transition.d.ts +136 -0
  111. package/dist/vite/layout-transition.d.ts.map +1 -0
  112. package/dist/vite/layout-transition.js +581 -0
  113. package/dist/vite/liquid-gradient-shader.d.ts +62 -0
  114. package/dist/vite/liquid-gradient-shader.d.ts.map +1 -0
  115. package/dist/vite/liquid-gradient-shader.js +413 -0
  116. package/dist/vite/mdx-client.d.ts +15 -0
  117. package/dist/vite/mdx-client.d.ts.map +1 -0
  118. package/dist/vite/mdx-client.js +265 -0
  119. package/dist/vite/mdx-parse.d.ts +102 -0
  120. package/dist/vite/mdx-parse.d.ts.map +1 -0
  121. package/dist/vite/mdx-parse.js +251 -0
  122. package/dist/vite/mdx-provided-components.d.ts +18 -0
  123. package/dist/vite/mdx-provided-components.d.ts.map +1 -0
  124. package/dist/vite/mdx-provided-components.js +14 -0
  125. package/dist/vite/mdx-video.d.ts +327 -0
  126. package/dist/vite/mdx-video.d.ts.map +1 -0
  127. package/dist/vite/mdx-video.js +596 -0
  128. package/dist/vite/mdx-video.test.d.ts +9 -0
  129. package/dist/vite/mdx-video.test.d.ts.map +1 -0
  130. package/dist/vite/mdx-video.test.js +1945 -0
  131. package/dist/vite/media-components.d.ts +45 -0
  132. package/dist/vite/media-components.d.ts.map +1 -0
  133. package/dist/vite/media-components.js +355 -0
  134. package/dist/vite/media-duration-store.d.ts +66 -0
  135. package/dist/vite/media-duration-store.d.ts.map +1 -0
  136. package/dist/vite/media-duration-store.js +204 -0
  137. package/dist/vite/player-page.d.ts +35 -0
  138. package/dist/vite/player-page.d.ts.map +1 -0
  139. package/dist/vite/player-page.js +720 -0
  140. package/dist/vite/render-client.d.ts +18 -0
  141. package/dist/vite/render-client.d.ts.map +1 -0
  142. package/dist/vite/render-client.js +67 -0
  143. package/dist/vite/sdk.d.ts +221 -0
  144. package/dist/vite/sdk.d.ts.map +1 -0
  145. package/dist/vite/sdk.js +355 -0
  146. package/dist/vite/server-components.d.ts +55 -0
  147. package/dist/vite/server-components.d.ts.map +1 -0
  148. package/dist/vite/server-components.js +156 -0
  149. package/dist/vite/server-mdx.d.ts +74 -0
  150. package/dist/vite/server-mdx.d.ts.map +1 -0
  151. package/dist/vite/server-mdx.js +259 -0
  152. package/dist/vite/shader-renderer.d.ts +48 -0
  153. package/dist/vite/shader-renderer.d.ts.map +1 -0
  154. package/dist/vite/shader-renderer.js +411 -0
  155. package/dist/vite/store-hooks.d.ts +12 -0
  156. package/dist/vite/store-hooks.d.ts.map +1 -0
  157. package/dist/vite/store-hooks.js +93 -0
  158. package/dist/vite/store.d.ts +75 -0
  159. package/dist/vite/store.d.ts.map +1 -0
  160. package/dist/vite/store.js +52 -0
  161. package/dist/vite/store.test.d.ts +6 -0
  162. package/dist/vite/store.test.d.ts.map +1 -0
  163. package/dist/vite/store.test.js +172 -0
  164. package/dist/vite/tweakpane-hook.d.ts +94 -0
  165. package/dist/vite/tweakpane-hook.d.ts.map +1 -0
  166. package/dist/vite/tweakpane-hook.js +450 -0
  167. package/dist/vite/vite-plugin.d.ts +28 -0
  168. package/dist/vite/vite-plugin.d.ts.map +1 -0
  169. package/dist/vite/vite-plugin.js +538 -0
  170. package/dist/vite/wave-gradient-shader.d.ts +41 -0
  171. package/dist/vite/wave-gradient-shader.d.ts.map +1 -0
  172. package/dist/vite/wave-gradient-shader.js +207 -0
  173. package/package.json +101 -24
  174. package/skills/egaki/SKILL.md +162 -1
  175. package/src/cli/cache-utils.ts +169 -0
  176. package/src/cli/cached-generate.test.ts +531 -0
  177. package/src/cli/cached-generate.ts +348 -0
  178. package/src/cli/cartesia-provider.ts +249 -0
  179. package/src/{cli.ts → cli/cli.ts} +836 -884
  180. package/src/cli/clone-generate.ts +202 -0
  181. package/src/{credentials.ts → cli/credentials.ts} +20 -0
  182. package/src/cli/elevenlabs-speech-provider.ts +243 -0
  183. package/src/cli/generate.test.ts +166 -0
  184. package/src/cli/generate.ts +912 -0
  185. package/src/cli/main.ts +8 -0
  186. package/src/{model-catalog.ts → cli/model-catalog.ts} +787 -58
  187. package/src/{models.ts → cli/models.ts} +65 -86
  188. package/src/cli/openai-speech-provider.ts +34 -0
  189. package/src/cli/separation-generate.ts +187 -0
  190. package/src/cli/speech-catalog.ts +253 -0
  191. package/src/cli/speech-generate.ts +275 -0
  192. package/src/cli/speech-models.ts +146 -0
  193. package/src/cli/speech-provider.test.ts +226 -0
  194. package/src/cli/transcription-catalog.ts +250 -0
  195. package/src/cli/transcription-generate.ts +214 -0
  196. package/src/cli/transcription-models.ts +136 -0
  197. package/src/cli/transcription-providers.ts +427 -0
  198. package/src/{xai-auth.ts → cli/xai-auth.ts} +1 -1
  199. package/src/vite/angled-screen.tsx +214 -0
  200. package/src/vite/app.tsx +197 -0
  201. package/src/vite/bands-shader.tsx +319 -0
  202. package/src/vite/code-block.tsx +939 -0
  203. package/src/vite/components.tsx +278 -0
  204. package/src/vite/dispersion-rings-shader.tsx +331 -0
  205. package/src/vite/easing-curves.test.ts +232 -0
  206. package/src/vite/easing-curves.ts +743 -0
  207. package/src/vite/generated-media-client.tsx +121 -0
  208. package/src/vite/keyframes.tsx +347 -0
  209. package/src/vite/layout-editor.tsx +709 -0
  210. package/src/vite/layout-transition.tsx +706 -0
  211. package/src/vite/liquid-gradient-shader.tsx +474 -0
  212. package/src/vite/mdx-client.tsx +420 -0
  213. package/src/vite/mdx-parse.ts +343 -0
  214. package/src/vite/mdx-provided-components.ts +19 -0
  215. package/src/vite/mdx-video.test.tsx +2219 -0
  216. package/src/vite/mdx-video.tsx +976 -0
  217. package/src/vite/media-components.tsx +473 -0
  218. package/src/vite/media-duration-store.ts +225 -0
  219. package/src/vite/motion-timing.ts +194 -0
  220. package/src/vite/player-page.tsx +1107 -0
  221. package/src/vite/render-client.ts +84 -0
  222. package/src/vite/sdk.ts +598 -0
  223. package/src/vite/server-components.tsx +241 -0
  224. package/src/vite/server-mdx.ts +285 -0
  225. package/src/vite/shader-renderer.tsx +535 -0
  226. package/src/vite/store-hooks.ts +117 -0
  227. package/src/vite/store.test.ts +202 -0
  228. package/src/vite/store.ts +115 -0
  229. package/src/vite/styles.css +21 -0
  230. package/src/vite/tweakpane-hook.tsx +593 -0
  231. package/src/vite/virtual-modules.d.ts +30 -0
  232. package/src/vite/vite-plugin.ts +584 -0
  233. package/src/vite/wave-gradient-shader.tsx +253 -0
  234. package/README.md +0 -370
  235. package/dist/antigravity-auth.d.ts +0 -15
  236. package/dist/antigravity-auth.d.ts.map +0 -1
  237. package/dist/antigravity-auth.js +0 -544
  238. package/dist/antigravity-image.d.ts +0 -11
  239. package/dist/antigravity-image.d.ts.map +0 -1
  240. package/dist/antigravity-image.js +0 -285
  241. package/dist/chatgpt-auth.d.ts.map +0 -1
  242. package/dist/cli.d.ts +0 -3
  243. package/dist/cli.d.ts.map +0 -1
  244. package/dist/credentials.d.ts.map +0 -1
  245. package/dist/gateway-model-candidates.generated.d.ts +0 -11
  246. package/dist/gateway-model-candidates.generated.d.ts.map +0 -1
  247. package/dist/gateway-model-candidates.generated.js +0 -64
  248. package/dist/login.d.ts.map +0 -1
  249. package/dist/model-catalog.d.ts.map +0 -1
  250. package/dist/models.d.ts.map +0 -1
  251. package/dist/open-browser.d.ts.map +0 -1
  252. package/dist/subscription.d.ts.map +0 -1
  253. package/dist/video-model-catalog.d.ts.map +0 -1
  254. package/dist/xai-auth.d.ts.map +0 -1
  255. /package/dist/{chatgpt-auth.d.ts → cli/chatgpt-auth.d.ts} +0 -0
  256. /package/dist/{chatgpt-auth.js → cli/chatgpt-auth.js} +0 -0
  257. /package/dist/{credentials.d.ts → cli/credentials.d.ts} +0 -0
  258. /package/dist/{login.d.ts → cli/login.d.ts} +0 -0
  259. /package/dist/{login.js → cli/login.js} +0 -0
  260. /package/dist/{open-browser.d.ts → cli/open-browser.d.ts} +0 -0
  261. /package/dist/{open-browser.js → cli/open-browser.js} +0 -0
  262. /package/dist/{subscription.d.ts → cli/subscription.d.ts} +0 -0
  263. /package/dist/{subscription.js → cli/subscription.js} +0 -0
  264. /package/dist/{video-model-catalog.d.ts → cli/video-model-catalog.d.ts} +0 -0
  265. /package/dist/{video-model-catalog.js → cli/video-model-catalog.js} +0 -0
  266. /package/dist/{xai-auth.d.ts → cli/xai-auth.d.ts} +0 -0
  267. /package/src/{chatgpt-auth.ts → cli/chatgpt-auth.ts} +0 -0
  268. /package/src/{login.ts → cli/login.ts} +0 -0
  269. /package/src/{open-browser.ts → cli/open-browser.ts} +0 -0
  270. /package/src/{subscription.ts → cli/subscription.ts} +0 -0
  271. /package/src/{video-model-catalog.ts → cli/video-model-catalog.ts} +0 -0
@@ -0,0 +1,200 @@
1
+ /**
2
+ * Tests for the easing curve engine.
3
+ *
4
+ * The golden values below are the ORIGINAL hardcoded sample arrays that were
5
+ * extracted from Jitter's webpack bundle (before this file generated them
6
+ * from functions). They pin the generator output: every preset is checked at
7
+ * 10 spot indices per intensity level, plus structural invariants.
8
+ *
9
+ * During the port, ALL 3570 values (14 presets x 5 intensities x 51 samples)
10
+ * were verified Object.is-identical to the extracted arrays. These spot
11
+ * checks guard against regressions in the engine math.
12
+ */
13
+ import { describe, expect, test } from 'vitest';
14
+ import { accelerateElasticSamples, accelerateImpulseSamples, bounceAnticipateSamples, bounceSamples, bounceThrowSamples, cubicBezier, decelerateElasticSamples, decelerateOvershootSamples, elasticSnapSamples, impulseOvershootSamples, impulseSlowSamples, lerpSamples, naturalThrowSamples, overshootBouncySamples, overshootElasticSamples, overshootSamples, polybezier, } from "./easing-curves.js";
15
+ const SPOT_INDICES = [0, 1, 7, 13, 19, 25, 31, 37, 43, 50];
16
+ const GOLDEN = {
17
+ naturalThrow: {
18
+ 0: [0, -0.0004, -0.0275, -0.0921, -0.0621, 0.3395, 1.0399, 1.1399, 1.0314, 1],
19
+ 25: [0, -0.0005, -0.0453, -0.1428, -0.1247, 0.19, 0.9808, 1.1559, 1.0338, 1],
20
+ 50: [0, -0.0005, -0.0706, -0.1938, -0.1819, 0.0583, 0.8338, 1.1644, 1.0353, 1],
21
+ 75: [0, -0.0007, -0.0975, -0.2918, -0.2818, -0.0397, 0.7714, 1.198, 1.0418, 1],
22
+ 100: [0, -0.0008, -0.1164, -0.3903, -0.3819, -0.1404, 0.6832, 1.2223, 1.0467, 1],
23
+ },
24
+ decelerateOvershoot: {
25
+ 0: [0, 0.2145, 0.8308, 1.0582, 1.0982, 1.0661, 1.0335, 1.0137, 1.0035, 1],
26
+ 25: [0, 0.2486, 0.9403, 1.1731, 1.189, 1.1204, 1.0611, 1.0252, 1.0065, 1],
27
+ 50: [0, 0.2873, 1.058, 1.2874, 1.2684, 1.165, 1.0839, 1.0348, 1.0091, 1],
28
+ 75: [0, 0.4347, 1.2454, 1.4, 1.3216, 1.1915, 1.098, 1.041, 1.0108, 1],
29
+ 100: [0, 0.6371, 1.4202, 1.4889, 1.3572, 1.21, 1.1081, 1.0456, 1.0121, 1],
30
+ },
31
+ decelerateElastic: {
32
+ 0: [0, 0.2149, 0.7414, 0.9671, 1.0709, 1.1, 1.0805, 1.0411, 1.0115, 1],
33
+ 25: [0, 0.2642, 0.8047, 1.0237, 1.1226, 1.15, 1.1218, 1.0552, 1.0133, 1],
34
+ 50: [0, 0.3251, 0.8688, 1.0799, 1.1741, 1.2, 1.1642, 1.0638, 1.0137, 1],
35
+ 75: [0, 0.4212, 1.0067, 1.2265, 1.3235, 1.35, 1.3148, 1.1251, 1.0226, 1],
36
+ 100: [0, 0.5174, 1.1446, 1.3731, 1.4728, 1.5, 1.4704, 1.2162, 1.0302, 1],
37
+ },
38
+ accelerateImpulse: {
39
+ 0: [0, -0.0005, -0.0262, -0.0738, -0.0995, -0.0784, 0.0105, 0.1811, 0.4571, 1],
40
+ 25: [0, -0.0006, -0.0313, -0.0942, -0.1422, -0.1442, -0.0779, 0.079, 0.362, 1],
41
+ 50: [0, -0.0007, -0.0339, -0.1067, -0.1751, -0.2, -0.1606, -0.0241, 0.257, 1],
42
+ 75: [0, -0.0009, -0.0465, -0.1519, -0.2694, -0.3401, -0.3406, -0.2407, 0.0263, 1],
43
+ 100: [0, -0.0011, -0.0534, -0.1785, -0.334, -0.4539, -0.4997, -0.4487, -0.219, 1],
44
+ },
45
+ accelerateElastic: {
46
+ 0: [0, -0.0002, -0.0099, -0.0461, -0.0894, -0.1, -0.0763, 0.0101, 0.2036, 1],
47
+ 25: [0, -0.0002, -0.0131, -0.0685, -0.1363, -0.15, -0.1252, -0.0349, 0.1674, 1],
48
+ 50: [0, -0.0002, -0.0154, -0.0901, -0.1842, -0.2, -0.1741, -0.0799, 0.1312, 1],
49
+ 75: [0, -0.0003, -0.0253, -0.2024, -0.3329, -0.35, -0.3235, -0.2265, -0.0067, 1],
50
+ 100: [0, -0.0004, -0.0338, -0.3722, -0.4837, -0.5, -0.4728, -0.3731, -0.1446, 1],
51
+ },
52
+ elasticSnap: {
53
+ 0: [0, 0.0374, 0.6938, 1.0155, 1.0341, 1.0073, 0.9985, 0.9989, 0.9999, 1.0001],
54
+ 25: [0, 0.0507, 0.868, 1.088, 1.0153, 0.9919, 0.9983, 1.0007, 1.0002, 0.9999],
55
+ 50: [0, 0.0739, 1.0803, 1.0643, 0.9752, 1.0007, 1.0021, 0.9994, 1, 1],
56
+ 75: [0, 0.12, 1.2732, 0.9246, 1.0178, 0.9969, 1.0001, 1.0003, 0.9998, 1],
57
+ 100: [0, 0.2503, 0.9638, 1.0864, 0.9841, 0.9946, 1.0029, 0.9999, 0.9997, 1],
58
+ },
59
+ bounce: {
60
+ 0: [0, 0.0009, 0.0439, 0.1516, 0.3239, 0.5608, 0.8623, 0.9684, 0.9676, 1],
61
+ 25: [0, 0.0017, 0.0844, 0.2911, 0.622, 0.9751, 0.8814, 0.9117, 0.9864, 1],
62
+ 50: [0, 0.0036, 0.1771, 0.611, 0.8779, 0.7497, 0.8819, 0.938, 0.986, 1],
63
+ 75: [0, 0.0064, 0.3154, 0.9503, 0.6454, 0.8041, 0.8754, 0.9817, 0.9842, 1],
64
+ 100: [0, 0.0129, 0.6314, 0.56, 0.7178, 0.7621, 0.9245, 0.9541, 0.9972, 1],
65
+ },
66
+ bounceAnticipate: {
67
+ 0: [0, -0.312, -1.091, -0.25, 0.5362, 0.4344, 0.7219, 0.8843, 0.9941, 1],
68
+ 25: [0, -0.2805, -1.0932, -0.5893, 0.9879, 0.3642, 0.9834, 0.9, 0.9737, 1],
69
+ 50: [0, -0.2551, -1.0782, -0.8111, 0.3954, 0.505, 0.656, 0.8284, 0.9509, 1],
70
+ 75: [0, -0.2365, -1.0652, -0.9626, -0.0309, 0.7255, 0.5385, 0.9146, 0.9754, 1],
71
+ 100: [0, -0.2429, -1.1621, -1.1587, -0.2326, 0.7471, 0.4442, 0.9706, 0.9749, 1],
72
+ },
73
+ bounceThrow: {
74
+ 0: [0, 0.1176, 0.7764, 0.4171, 0.9877, 0.7378, 0.861, 0.9301, 0.9892, 1],
75
+ 25: [0, 0.1708, 0.7334, 0.3524, 0.5552, 0.8521, 0.8234, 0.9149, 0.9755, 1],
76
+ 50: [0, 0.2061, 0.7171, 0.3341, 0.3456, 0.7518, 0.842, 0.9146, 0.9687, 1],
77
+ 75: [0, 0.2215, 0.7562, 0.4077, 0.3207, 0.4954, 0.9317, 0.8906, 0.9953, 1],
78
+ 100: [0, 0.2124, 0.8436, 0.5714, 0.4552, 0.4949, 0.6907, 0.9883, 0.9576, 1],
79
+ },
80
+ impulseSlow: {
81
+ 0: [0, -0.0021, -0.0445, 0.0225, 0.3076, 0.5975, 0.7948, 0.9142, 0.9775, 1],
82
+ 25: [0, -0.0026, -0.0744, -0.1182, 0.1306, 0.5103, 0.7603, 0.9025, 0.9749, 1],
83
+ 50: [0, -0.0023, -0.0801, -0.1858, -0.0939, 0.3794, 0.7124, 0.8868, 0.9714, 1],
84
+ 75: [0, -0.003, -0.1348, -0.4006, -0.5995, -0.1034, 0.5564, 0.8363, 0.9601, 1],
85
+ 100: [0, -0.0024, -0.1252, -0.4364, -0.8436, -0.9544, 0.2787, 0.7605, 0.944, 1],
86
+ },
87
+ impulseOvershoot: {
88
+ 0: [0, -0.0036, -0.0922, -0.0004, 0.5079, 0.9071, 1.0402, 1.0393, 1.0103, 1],
89
+ 25: [0, -0.0046, -0.1285, -0.0668, 0.5603, 0.9749, 1.074, 1.0485, 1.0124, 1],
90
+ 50: [0, -0.0052, -0.1579, -0.136, 0.6332, 1.0386, 1.0987, 1.0533, 1.0135, 1],
91
+ 75: [0, -0.0113, -0.3777, -0.5814, 0.7836, 1.2858, 1.2451, 1.1111, 1.0287, 1],
92
+ 100: [0, -0.0142, -0.4997, -0.9951, 1.1135, 1.4876, 1.3082, 1.135, 1.0358, 1],
93
+ },
94
+ overshoot: {
95
+ 0: [0, 0.1632, 0.6829, 0.9265, 1.0324, 1.0477, 1.0265, 1.0105, 1.0026, 1],
96
+ 25: [0, 0.2168, 0.8435, 1.0785, 1.1234, 1.0823, 1.0407, 1.0165, 1.0042, 1],
97
+ 50: [0, 0.3067, 1.0551, 1.1997, 1.1519, 1.0857, 1.0427, 1.0176, 1.0046, 1],
98
+ 75: [0, 0.4862, 1.5158, 1.5525, 1.348, 1.1958, 1.1, 1.0422, 1.0112, 1],
99
+ 100: [0, 0.7533, 1.9953, 1.7321, 1.4428, 1.2546, 1.1327, 1.0569, 1.0153, 1],
100
+ },
101
+ overshootElastic: {
102
+ 0: [0, 0.0025, 0.1678, 0.685, 1.0242, 1.1, 1.0862, 1.0468, 1.0125, 1],
103
+ 25: [0, 0.0018, 0.1352, 0.7495, 1.0889, 1.15, 1.1342, 1.0692, 1.0148, 1],
104
+ 50: [0, 0.0014, 0.1068, 0.831, 1.1504, 1.2, 1.1842, 1.0901, 1.0154, 1],
105
+ 75: [0, 0.0014, 0.1046, 0.9685, 1.3005, 1.35, 1.3261, 1.155, 1.0239, 1],
106
+ 100: [0, 0.0013, 0.1014, 1.1166, 1.4511, 1.5, 1.4704, 1.2162, 1.0302, 1],
107
+ },
108
+ overshootBouncy: {
109
+ 0: [0, 0.001, 0.0631, 0.3011, 0.9441, 1.2, 1.1389, 1.0614, 1.0162, 1],
110
+ 25: [0, 0.001, 0.0606, 0.2711, 0.8628, 1.35, 1.22, 1.0928, 1.0242, 1],
111
+ 50: [0, 0.001, 0.0582, 0.249, 0.7417, 1.5, 1.2803, 1.115, 1.0298, 1],
112
+ 75: [0, 0.001, 0.0585, 0.2461, 0.7133, 1.7, 1.3355, 1.1298, 1.0326, 1],
113
+ 100: [0, 0.001, 0.0584, 0.2421, 0.6823, 1.9, 1.3601, 1.135, 1.0335, 1],
114
+ },
115
+ };
116
+ const ALL_SAMPLES = {
117
+ naturalThrow: naturalThrowSamples,
118
+ decelerateOvershoot: decelerateOvershootSamples,
119
+ decelerateElastic: decelerateElasticSamples,
120
+ accelerateImpulse: accelerateImpulseSamples,
121
+ accelerateElastic: accelerateElasticSamples,
122
+ elasticSnap: elasticSnapSamples,
123
+ bounce: bounceSamples,
124
+ bounceAnticipate: bounceAnticipateSamples,
125
+ bounceThrow: bounceThrowSamples,
126
+ impulseSlow: impulseSlowSamples,
127
+ impulseOvershoot: impulseOvershootSamples,
128
+ overshoot: overshootSamples,
129
+ overshootElastic: overshootElasticSamples,
130
+ overshootBouncy: overshootBouncySamples,
131
+ };
132
+ const INTENSITIES = [0, 25, 50, 75, 100];
133
+ describe('generated samples match the original Jitter-extracted values', () => {
134
+ for (const [name, golden] of Object.entries(GOLDEN)) {
135
+ test(name, () => {
136
+ const samples = ALL_SAMPLES[name];
137
+ for (const intensity of INTENSITIES) {
138
+ const actual = SPOT_INDICES.map((i) => samples[intensity][i]);
139
+ expect(actual, `${name}[${intensity}]`).toEqual(golden[intensity]);
140
+ }
141
+ });
142
+ }
143
+ });
144
+ describe('structural invariants', () => {
145
+ test('every curve has 51 samples and starts at 0', () => {
146
+ for (const samples of Object.values(ALL_SAMPLES)) {
147
+ for (const intensity of INTENSITIES) {
148
+ expect(samples[intensity]).toHaveLength(51);
149
+ expect(samples[intensity][0]).toBe(0);
150
+ }
151
+ }
152
+ });
153
+ test('path-based curves end exactly at 1', () => {
154
+ // elasticSnap is physics-based and may settle at e.g. 1.0001 or 0.9999.
155
+ const { elasticSnap: _elasticSnap, ...pathAndBounce } = ALL_SAMPLES;
156
+ for (const samples of Object.values(pathAndBounce)) {
157
+ for (const intensity of INTENSITIES) {
158
+ expect(samples[intensity][50]).toBe(1);
159
+ }
160
+ }
161
+ });
162
+ });
163
+ describe('cubicBezier', () => {
164
+ test('is identity for linear control points', () => {
165
+ const linear = cubicBezier(0.25, 0.25, 0.75, 0.75);
166
+ expect(linear(0.3)).toBe(0.3);
167
+ });
168
+ test('matches known css ease-like curve endpoints', () => {
169
+ const ease = cubicBezier(0.5, 0, 0, 1);
170
+ expect(ease(0)).toBe(0);
171
+ expect(ease(1)).toBe(1);
172
+ expect(ease(0.5)).toBeGreaterThan(0.5);
173
+ });
174
+ test('throws on x control points outside [0, 1]', () => {
175
+ expect(() => cubicBezier(-0.1, 0, 0.5, 1)).toThrow();
176
+ expect(() => cubicBezier(0, 0, 1.5, 1)).toThrow();
177
+ });
178
+ });
179
+ describe('polybezier', () => {
180
+ test('returns anchor y exactly when x hits an anchor', () => {
181
+ const curve = polybezier([
182
+ { x: 0, y: 0, upper: 0 },
183
+ { x: 0.5, y: 1.2, lower: 0.8, upper: 0.2 },
184
+ { x: 1, y: 1, lower: 0.7 },
185
+ ]);
186
+ expect(curve(0)).toBe(0);
187
+ expect(curve(0.5)).toBe(1.2);
188
+ expect(curve(1)).toBe(1);
189
+ });
190
+ });
191
+ describe('lerpSamples', () => {
192
+ test('interpolates linearly between samples and clamps', () => {
193
+ const samples = [0, 1, 0.5];
194
+ expect(lerpSamples(samples, 0)).toBe(0);
195
+ expect(lerpSamples(samples, 0.25)).toBe(0.5);
196
+ expect(lerpSamples(samples, 1)).toBe(0.5);
197
+ expect(lerpSamples(samples, -1)).toBe(0);
198
+ expect(lerpSamples(samples, 2)).toBe(0.5);
199
+ });
200
+ });
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Client wrappers for server-generated media components.
3
+ *
4
+ * Each wrapper receives a `srcPromise: Promise<string>` from the server
5
+ * component (streamed through RSC flight) and a `fallbackSrc` for the
6
+ * stale file to show while generation is in progress. React 19's `use()`
7
+ * suspends until the promise resolves, then renders the actual media
8
+ * component. While suspended, the fallback (stale generation) renders if
9
+ * available; otherwise nothing renders.
10
+ *
11
+ * Passthrough props are forwarded to the underlying media component so
12
+ * users can set style, className, trimBefore, trimAfter, playbackRate, etc.
13
+ *
14
+ * Generation tracking: handled server-side via the /api/generation-progress
15
+ * SSE stream. The server tracks all active generations across all scenes
16
+ * and the client fetches progress updates to show in the toolbar.
17
+ * The Suspense fallback only handles delayRender for export mode.
18
+ */
19
+ import { type ComponentProps } from 'react';
20
+ import { Img, Audio, Video } from './mdx-video.tsx';
21
+ import { useGenerationStatus, type GenerationStatus } from './store-hooks.ts';
22
+ export { useGenerationStatus, type GenerationStatus };
23
+ export declare function GeneratedImageClient({ srcPromise, fallbackSrc, ...rest }: {
24
+ srcPromise: Promise<string>;
25
+ fallbackSrc?: string;
26
+ } & ComponentProps<typeof Img>): import("react").JSX.Element;
27
+ export declare function GeneratedVideoClient({ srcPromise, fallbackSrc, ...rest }: {
28
+ srcPromise: Promise<string>;
29
+ fallbackSrc?: string;
30
+ } & ComponentProps<typeof Video>): import("react").JSX.Element;
31
+ export declare function GeneratedSpeechClient({ srcPromise, fallbackSrc, ...rest }: {
32
+ srcPromise: Promise<string>;
33
+ fallbackSrc?: string;
34
+ } & ComponentProps<typeof Audio>): import("react").JSX.Element;
35
+ //# sourceMappingURL=generated-media-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generated-media-client.d.ts","sourceRoot":"","sources":["../../src/vite/generated-media-client.tsx"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAkC,KAAK,cAAc,EAAkB,MAAM,OAAO,CAAA;AAE3F,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,KAAK,EAAkB,MAAM,iBAAiB,CAAA;AACnE,OAAO,EAAE,mBAAmB,EAAE,KAAK,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AAE7E,OAAO,EAAE,mBAAmB,EAAE,KAAK,gBAAgB,EAAE,CAAA;AAmDrD,wBAAgB,oBAAoB,CAAC,EACnC,UAAU,EACV,WAAW,EACX,GAAG,IAAI,EACR,EAAE;IACD,UAAU,EAAE,OAAO,CAAC,MAAM,CAAC,CAAA;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,GAAG,cAAc,CAAC,OAAO,GAAG,CAAC,+BAM7B;AAED,wBAAgB,oBAAoB,CAAC,EACnC,UAAU,EACV,WAAW,EACX,GAAG,IAAI,EACR,EAAE;IACD,UAAU,EAAE,OAAO,CAAC,MAAM,CAAC,CAAA;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,GAAG,cAAc,CAAC,OAAO,KAAK,CAAC,+BAM/B;AAED,wBAAgB,qBAAqB,CAAC,EACpC,UAAU,EACV,WAAW,EACX,GAAG,IAAI,EACR,EAAE;IACD,UAAU,EAAE,OAAO,CAAC,MAAM,CAAC,CAAA;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,GAAG,cAAc,CAAC,OAAO,KAAK,CAAC,+BAM/B"}
@@ -0,0 +1,76 @@
1
+ 'use client';
2
+ import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
3
+ /**
4
+ * Client wrappers for server-generated media components.
5
+ *
6
+ * Each wrapper receives a `srcPromise: Promise<string>` from the server
7
+ * component (streamed through RSC flight) and a `fallbackSrc` for the
8
+ * stale file to show while generation is in progress. React 19's `use()`
9
+ * suspends until the promise resolves, then renders the actual media
10
+ * component. While suspended, the fallback (stale generation) renders if
11
+ * available; otherwise nothing renders.
12
+ *
13
+ * Passthrough props are forwarded to the underlying media component so
14
+ * users can set style, className, trimBefore, trimAfter, playbackRate, etc.
15
+ *
16
+ * Generation tracking: handled server-side via the /api/generation-progress
17
+ * SSE stream. The server tracks all active generations across all scenes
18
+ * and the client fetches progress updates to show in the toolbar.
19
+ * The Suspense fallback only handles delayRender for export mode.
20
+ */
21
+ import { Suspense, use, useLayoutEffect } from 'react';
22
+ import { useDelayRender } from 'remotion';
23
+ import { Img, Audio, Video, useIsExporting } from "./mdx-video.js";
24
+ import { useGenerationStatus } from "./store-hooks.js";
25
+ export { useGenerationStatus };
26
+ // ---------------------------------------------------------------------------
27
+ // Export-aware Suspense fallback — blocks Remotion frame capture while
28
+ // a generated media promise is still pending. Also registers/unregisters
29
+ // the generation in the tracker so the toolbar can show status.
30
+ // ---------------------------------------------------------------------------
31
+ /** Export-aware Suspense fallback — blocks Remotion frame capture while
32
+ * a generated media promise is still pending. Generation progress tracking
33
+ * is now handled server-side via the /api/generation-progress SSE stream,
34
+ * so this component only needs to handle delayRender for exports. */
35
+ function GeneratedMediaFallback({ children }) {
36
+ const isExporting = useIsExporting();
37
+ const { delayRender, continueRender } = useDelayRender();
38
+ // useLayoutEffect prevents a first-frame capture race: the delay handle
39
+ // is registered before the browser paints, matching Remotion's own pattern.
40
+ useLayoutEffect(() => {
41
+ if (!isExporting)
42
+ return;
43
+ const handle = delayRender('Waiting for generated media', {
44
+ timeoutInMilliseconds: 10 * 60 * 1000,
45
+ });
46
+ return () => continueRender(handle);
47
+ }, [isExporting, delayRender, continueRender]);
48
+ return _jsx(_Fragment, { children: children });
49
+ }
50
+ // ---------------------------------------------------------------------------
51
+ // Inner components that call use() — must be inside <Suspense>
52
+ // ---------------------------------------------------------------------------
53
+ function ResolvedImage({ srcPromise, ...rest }) {
54
+ const src = use(srcPromise);
55
+ return _jsx(Img, { src: src, ...rest });
56
+ }
57
+ function ResolvedVideo({ srcPromise, ...rest }) {
58
+ const src = use(srcPromise);
59
+ return _jsx(Video, { src: src, ...rest });
60
+ }
61
+ function ResolvedAudio({ srcPromise, ...rest }) {
62
+ const src = use(srcPromise);
63
+ return _jsx(Audio, { src: src, ...rest });
64
+ }
65
+ // ---------------------------------------------------------------------------
66
+ // Exported client wrappers — render fallback while promise is pending
67
+ // ---------------------------------------------------------------------------
68
+ export function GeneratedImageClient({ srcPromise, fallbackSrc, ...rest }) {
69
+ return (_jsx(Suspense, { fallback: _jsx(GeneratedMediaFallback, { children: fallbackSrc ? _jsx(Img, { src: fallbackSrc, ...rest }) : null }), children: _jsx(ResolvedImage, { srcPromise: srcPromise, ...rest }) }));
70
+ }
71
+ export function GeneratedVideoClient({ srcPromise, fallbackSrc, ...rest }) {
72
+ return (_jsx(Suspense, { fallback: _jsx(GeneratedMediaFallback, { children: fallbackSrc ? _jsx(Video, { src: fallbackSrc, ...rest }) : null }), children: _jsx(ResolvedVideo, { srcPromise: srcPromise, ...rest }) }));
73
+ }
74
+ export function GeneratedSpeechClient({ srcPromise, fallbackSrc, ...rest }) {
75
+ return (_jsx(Suspense, { fallback: _jsx(GeneratedMediaFallback, { children: fallbackSrc ? _jsx(Audio, { src: fallbackSrc, ...rest }) : null }), children: _jsx(ResolvedAudio, { srcPromise: srcPromise, ...rest }) }));
76
+ }
@@ -0,0 +1,129 @@
1
+ /**
2
+ * keyframes() — evaluate a keyframed animation at a given frame.
3
+ *
4
+ * Accepts an array of typed keyframe descriptors with bezier easing, hold,
5
+ * and per-dimension control. Wraps Remotion's interpolate() + cubicBezier()
6
+ * so you get the full Lottie/After Effects easing model with clean parameters.
7
+ *
8
+ * Also includes fromLottieProperty() for converting raw Lottie animated
9
+ * properties to the Keyframe[] format, and extractLottieDimensionEasing()
10
+ * for per-dimension easing overrides.
11
+ *
12
+ * See docs/lottie-to-remotion.md for the Lottie field mapping.
13
+ */
14
+ /**
15
+ * Cubic bezier control points: [x1, y1, x2, y2].
16
+ * Same as CSS `cubic-bezier(x1, y1, x2, y2)`.
17
+ * x values must be in [0, 1]. y values can overshoot (< 0 or > 1).
18
+ */
19
+ export type BezierCurve = [x1: number, y1: number, x2: number, y2: number];
20
+ /** A single keyframe in a `keyframes()` animation. */
21
+ export interface Keyframe<T extends number | number[] = number> {
22
+ /** Frame number where this keyframe occurs. */
23
+ time: number;
24
+ /** Value at this keyframe. Scalar or vector (e.g. [x, y] for position). */
25
+ value: T;
26
+ /**
27
+ * Bezier easing curve for the transition FROM this keyframe TO the next.
28
+ * Four control points [x1, y1, x2, y2], same as CSS cubic-bezier().
29
+ * Omit for linear interpolation. Ignored on the last keyframe.
30
+ */
31
+ easing?: BezierCurve;
32
+ /**
33
+ * If true, value holds constant until the next keyframe (step function).
34
+ * No interpolation occurs. Overrides `easing`.
35
+ */
36
+ hold?: boolean;
37
+ }
38
+ /** Options for per-dimension easing on vector keyframes. */
39
+ export interface KeyframesDimensionOptions {
40
+ /**
41
+ * Per-dimension bezier easing overrides.
42
+ * Index matches the dimension index in the value array.
43
+ * When set, overrides the keyframe-level `easing` for that dimension.
44
+ * Each entry is a [x1, y1, x2, y2] bezier curve or undefined to use the keyframe's easing.
45
+ */
46
+ dimensionEasing?: (BezierCurve | undefined)[];
47
+ }
48
+ /**
49
+ * Evaluate a keyframed animation at the given frame.
50
+ *
51
+ * Scalar version: each keyframe has a numeric `value`, returns a number.
52
+ *
53
+ * ```ts
54
+ * const opacity = keyframes(frame, [
55
+ * { time: 0, value: 0, easing: [0.33, 0, 0.67, 1] },
56
+ * { time: 30, value: 1 },
57
+ * ])
58
+ * ```
59
+ */
60
+ export declare function keyframes(frame: number, kfs: Keyframe<number>[], options?: KeyframesDimensionOptions): number;
61
+ /**
62
+ * Vector version: each keyframe has an array `value`, returns an array
63
+ * of the same length. Supports per-dimension easing via options.
64
+ *
65
+ * ```ts
66
+ * const [x, y] = keyframes(frame, [
67
+ * { time: 0, value: [0, 0], easing: [0.33, 0, 0.67, 1] },
68
+ * { time: 30, value: [200, 400] },
69
+ * ])
70
+ * ```
71
+ */
72
+ export declare function keyframes<N extends number>(frame: number, kfs: Keyframe<number[] & {
73
+ length: N;
74
+ }>[], options?: KeyframesDimensionOptions): number[];
75
+ /** Raw Lottie easing handle shape. */
76
+ export interface LottieEasingHandle {
77
+ x: number | number[];
78
+ y: number | number[];
79
+ }
80
+ /** Raw Lottie keyframe as found in a .json file. */
81
+ export interface LottieKeyframe {
82
+ /** Frame number */
83
+ t: number;
84
+ /** Value at this keyframe */
85
+ s?: number[];
86
+ /** Hold flag */
87
+ h?: 0 | 1;
88
+ /** In tangent (easing into next keyframe) */
89
+ i?: LottieEasingHandle;
90
+ /** Out tangent (easing leaving this keyframe) */
91
+ o?: LottieEasingHandle;
92
+ }
93
+ /** Raw Lottie animated property: { a: 0|1, k: value | keyframes }. */
94
+ export interface LottieAnimatedProperty {
95
+ /** 1 if animated, 0 if static */
96
+ a: 0 | 1;
97
+ /** Static value (when a=0) or array of keyframes (when a=1) */
98
+ k: number | number[] | LottieKeyframe[];
99
+ }
100
+ /**
101
+ * Convert a raw Lottie animated property into a `Keyframe[]` array
102
+ * that can be passed directly to `keyframes()`.
103
+ *
104
+ * ```ts
105
+ * import lottieJson from './animation.json'
106
+ *
107
+ * // Get the opacity property from layer 0
108
+ * const opacityKfs = fromLottieProperty(lottieJson.layers[0].ks.o)
109
+ * const opacity = keyframes(frame, opacityKfs)
110
+ * ```
111
+ *
112
+ * For static properties (a=0), returns a single keyframe at time 0.
113
+ * For vector properties, values are preserved as arrays.
114
+ */
115
+ export declare function fromLottieProperty(property: LottieAnimatedProperty): Keyframe<number>[] | Keyframe<number[]>[];
116
+ /**
117
+ * Extract per-dimension easing overrides from a Lottie keyframe sequence.
118
+ * Returns a `dimensionEasing` array suitable for the `keyframes()` options.
119
+ * Only needed when the Lottie property has different easing per dimension
120
+ * (e.g. position with independent X/Y curves).
121
+ *
122
+ * ```ts
123
+ * const posKfs = fromLottieProperty(lottieJson.layers[0].ks.p)
124
+ * const dimEasing = extractLottieDimensionEasing(lottieJson.layers[0].ks.p, segmentIndex)
125
+ * const [x, y] = keyframes(frame, posKfs, { dimensionEasing: dimEasing })
126
+ * ```
127
+ */
128
+ export declare function extractLottieDimensionEasing(property: LottieAnimatedProperty, segmentIndex: number): (BezierCurve | undefined)[] | undefined;
129
+ //# sourceMappingURL=keyframes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keyframes.d.ts","sourceRoot":"","sources":["../../src/vite/keyframes.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AASH;;;;GAIG;AACH,MAAM,MAAM,WAAW,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,CAAC,CAAA;AAE1E,sDAAsD;AACtD,MAAM,WAAW,QAAQ,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,EAAE,GAAG,MAAM;IAC5D,+CAA+C;IAC/C,IAAI,EAAE,MAAM,CAAA;IACZ,2EAA2E;IAC3E,KAAK,EAAE,CAAC,CAAA;IACR;;;;OAIG;IACH,MAAM,CAAC,EAAE,WAAW,CAAA;IACpB;;;OAGG;IACH,IAAI,CAAC,EAAE,OAAO,CAAA;CACf;AAED,4DAA4D;AAC5D,MAAM,WAAW,yBAAyB;IACxC;;;;;OAKG;IACH,eAAe,CAAC,EAAE,CAAC,WAAW,GAAG,SAAS,CAAC,EAAE,CAAA;CAC9C;AAoBD;;;;;;;;;;;GAWG;AACH,wBAAgB,SAAS,CACvB,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,EACvB,OAAO,CAAC,EAAE,yBAAyB,GAClC,MAAM,CAAA;AAET;;;;;;;;;;GAUG;AACH,wBAAgB,SAAS,CAAC,CAAC,SAAS,MAAM,EACxC,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,QAAQ,CAAC,MAAM,EAAE,GAAG;IAAE,MAAM,EAAE,CAAC,CAAA;CAAE,CAAC,EAAE,EACzC,OAAO,CAAC,EAAE,yBAAyB,GAClC,MAAM,EAAE,CAAA;AAwFX,sCAAsC;AACtC,MAAM,WAAW,kBAAkB;IACjC,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;IACpB,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;CACrB;AAED,oDAAoD;AACpD,MAAM,WAAW,cAAc;IAC7B,mBAAmB;IACnB,CAAC,EAAE,MAAM,CAAA;IACT,6BAA6B;IAC7B,CAAC,CAAC,EAAE,MAAM,EAAE,CAAA;IACZ,gBAAgB;IAChB,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAA;IACT,6CAA6C;IAC7C,CAAC,CAAC,EAAE,kBAAkB,CAAA;IACtB,iDAAiD;IACjD,CAAC,CAAC,EAAE,kBAAkB,CAAA;CACvB;AAED,sEAAsE;AACtE,MAAM,WAAW,sBAAsB;IACrC,iCAAiC;IACjC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAA;IACR,+DAA+D;IAC/D,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,cAAc,EAAE,CAAA;CACxC;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,sBAAsB,GAC/B,QAAQ,CAAC,MAAM,CAAC,EAAE,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,CAiD3C;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,4BAA4B,CAC1C,QAAQ,EAAE,sBAAsB,EAChC,YAAY,EAAE,MAAM,GACnB,CAAC,WAAW,GAAG,SAAS,CAAC,EAAE,GAAG,SAAS,CA0BzC"}
@@ -0,0 +1,194 @@
1
+ /**
2
+ * keyframes() — evaluate a keyframed animation at a given frame.
3
+ *
4
+ * Accepts an array of typed keyframe descriptors with bezier easing, hold,
5
+ * and per-dimension control. Wraps Remotion's interpolate() + cubicBezier()
6
+ * so you get the full Lottie/After Effects easing model with clean parameters.
7
+ *
8
+ * Also includes fromLottieProperty() for converting raw Lottie animated
9
+ * properties to the Keyframe[] format, and extractLottieDimensionEasing()
10
+ * for per-dimension easing overrides.
11
+ *
12
+ * See docs/lottie-to-remotion.md for the Lottie field mapping.
13
+ */
14
+ import { interpolate } from 'remotion';
15
+ import { cubicBezier } from "./easing-curves.js";
16
+ // ---------------------------------------------------------------------------
17
+ // Internal helpers
18
+ // ---------------------------------------------------------------------------
19
+ // Step easing: holds at 0 until t=1, then jumps to 1
20
+ function stepEasing(t) {
21
+ return t < 1 ? 0 : 1;
22
+ }
23
+ function buildEasingFn(curve) {
24
+ if (!curve)
25
+ return (t) => t; // linear
26
+ return cubicBezier(curve[0], curve[1], curve[2], curve[3]);
27
+ }
28
+ export function keyframes(frame, kfs, options) {
29
+ if (kfs.length === 0) {
30
+ throw new Error('keyframes() requires at least one keyframe');
31
+ }
32
+ if (kfs.length === 1) {
33
+ return kfs[0].value;
34
+ }
35
+ const first = kfs[0].value;
36
+ const isVector = Array.isArray(first);
37
+ if (isVector) {
38
+ return evaluateVector(frame, kfs, options);
39
+ }
40
+ return evaluateScalar(frame, kfs, options);
41
+ }
42
+ function evaluateScalar(frame, kfs, options) {
43
+ const inputRange = kfs.map((kf) => kf.time);
44
+ const outputRange = kfs.map((kf) => kf.value);
45
+ const dimEasing = options?.dimensionEasing?.[0];
46
+ const easings = [];
47
+ for (let i = 0; i < kfs.length - 1; i++) {
48
+ const kf = kfs[i];
49
+ if (kf.hold) {
50
+ easings.push(stepEasing);
51
+ }
52
+ else {
53
+ easings.push(buildEasingFn(dimEasing ?? kf.easing));
54
+ }
55
+ }
56
+ return interpolate(frame, inputRange, outputRange, {
57
+ easing: easings,
58
+ extrapolateLeft: 'clamp',
59
+ extrapolateRight: 'clamp',
60
+ });
61
+ }
62
+ function evaluateVector(frame, kfs, options) {
63
+ const dimensions = kfs[0].value.length;
64
+ const result = new Array(dimensions);
65
+ for (let dim = 0; dim < dimensions; dim++) {
66
+ const inputRange = kfs.map((kf) => kf.time);
67
+ const outputRange = kfs.map((kf) => kf.value[dim]);
68
+ const dimEasing = options?.dimensionEasing?.[dim];
69
+ const easings = [];
70
+ for (let i = 0; i < kfs.length - 1; i++) {
71
+ const kf = kfs[i];
72
+ if (kf.hold) {
73
+ easings.push(stepEasing);
74
+ }
75
+ else {
76
+ easings.push(buildEasingFn(dimEasing ?? kf.easing));
77
+ }
78
+ }
79
+ result[dim] = interpolate(frame, inputRange, outputRange, {
80
+ easing: easings,
81
+ extrapolateLeft: 'clamp',
82
+ extrapolateRight: 'clamp',
83
+ });
84
+ }
85
+ return result;
86
+ }
87
+ /**
88
+ * Convert a raw Lottie animated property into a `Keyframe[]` array
89
+ * that can be passed directly to `keyframes()`.
90
+ *
91
+ * ```ts
92
+ * import lottieJson from './animation.json'
93
+ *
94
+ * // Get the opacity property from layer 0
95
+ * const opacityKfs = fromLottieProperty(lottieJson.layers[0].ks.o)
96
+ * const opacity = keyframes(frame, opacityKfs)
97
+ * ```
98
+ *
99
+ * For static properties (a=0), returns a single keyframe at time 0.
100
+ * For vector properties, values are preserved as arrays.
101
+ */
102
+ export function fromLottieProperty(property) {
103
+ // Static property
104
+ if (!property.a || !Array.isArray(property.k) || property.k.length === 0) {
105
+ const val = property.k;
106
+ if (Array.isArray(val)) {
107
+ return [{ time: 0, value: val }];
108
+ }
109
+ return [{ time: 0, value: val }];
110
+ }
111
+ const lottieKfs = property.k;
112
+ // Detect if this is a scalar or vector property from the first keyframe's value
113
+ const firstValue = lottieKfs[0].s;
114
+ if (!firstValue || firstValue.length === 0) {
115
+ return [{ time: 0, value: 0 }];
116
+ }
117
+ const isScalar = firstValue.length === 1;
118
+ if (isScalar) {
119
+ return lottieKfs.map((lkf, i) => {
120
+ const kf = {
121
+ time: lkf.t,
122
+ value: lkf.s?.[0] ?? 0,
123
+ };
124
+ if (lkf.h === 1) {
125
+ kf.hold = true;
126
+ }
127
+ else if (lkf.o && lkf.i && i < lottieKfs.length - 1) {
128
+ kf.easing = extractBezier(lkf.o, lkf.i, 0);
129
+ }
130
+ return kf;
131
+ });
132
+ }
133
+ // Vector property
134
+ return lottieKfs.map((lkf, i) => {
135
+ const kf = {
136
+ time: lkf.t,
137
+ value: lkf.s ? [...lkf.s] : [],
138
+ };
139
+ if (lkf.h === 1) {
140
+ kf.hold = true;
141
+ }
142
+ else if (lkf.o && lkf.i && i < lottieKfs.length - 1) {
143
+ // Use dimension 0 for the keyframe-level easing
144
+ kf.easing = extractBezier(lkf.o, lkf.i, 0);
145
+ }
146
+ return kf;
147
+ });
148
+ }
149
+ /**
150
+ * Extract per-dimension easing overrides from a Lottie keyframe sequence.
151
+ * Returns a `dimensionEasing` array suitable for the `keyframes()` options.
152
+ * Only needed when the Lottie property has different easing per dimension
153
+ * (e.g. position with independent X/Y curves).
154
+ *
155
+ * ```ts
156
+ * const posKfs = fromLottieProperty(lottieJson.layers[0].ks.p)
157
+ * const dimEasing = extractLottieDimensionEasing(lottieJson.layers[0].ks.p, segmentIndex)
158
+ * const [x, y] = keyframes(frame, posKfs, { dimensionEasing: dimEasing })
159
+ * ```
160
+ */
161
+ export function extractLottieDimensionEasing(property, segmentIndex) {
162
+ if (!property.a || !Array.isArray(property.k))
163
+ return undefined;
164
+ const lottieKfs = property.k;
165
+ const lkf = lottieKfs[segmentIndex];
166
+ if (!lkf?.o || !lkf?.i || !lkf.s)
167
+ return undefined;
168
+ const dimensions = lkf.s.length;
169
+ if (dimensions <= 1)
170
+ return undefined;
171
+ // Check if all dimensions have the same easing — if so, no overrides needed
172
+ const ox = lkf.o.x;
173
+ const oy = lkf.o.y;
174
+ const ix = lkf.i.x;
175
+ const iy = lkf.i.y;
176
+ if (!Array.isArray(ox) || !Array.isArray(oy) || !Array.isArray(ix) || !Array.isArray(iy)) {
177
+ return undefined;
178
+ }
179
+ if (ox.length <= 1 && oy.length <= 1 && ix.length <= 1 && iy.length <= 1) {
180
+ return undefined;
181
+ }
182
+ const result = [];
183
+ for (let dim = 0; dim < dimensions; dim++) {
184
+ result.push(extractBezier(lkf.o, lkf.i, dim));
185
+ }
186
+ return result;
187
+ }
188
+ function extractBezier(out, into, dimension) {
189
+ const ox = Array.isArray(out.x) ? (out.x[dimension] ?? out.x[0]) : out.x;
190
+ const oy = Array.isArray(out.y) ? (out.y[dimension] ?? out.y[0]) : out.y;
191
+ const ix = Array.isArray(into.x) ? (into.x[dimension] ?? into.x[0]) : into.x;
192
+ const iy = Array.isArray(into.y) ? (into.y[dimension] ?? into.y[0]) : into.y;
193
+ return [ox, oy, ix, iy];
194
+ }