@vibecuting/video-project-core 0.1.26 → 0.1.28

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 (266) hide show
  1. package/package.json +4 -4
  2. package/src/base/BaseRemotionScene.tsx +4 -3
  3. package/src/core/index.test.ts +40 -0
  4. package/src/core/intro/_shared/intro-layout.test.ts +18 -0
  5. package/src/core/intro/_shared/intro-layout.ts +50 -0
  6. package/src/core/intro/cyberpunk-intro-holo/default-cyberpunk-intro-bumper-Horizontal.tsx +25 -0
  7. package/src/core/intro/cyberpunk-intro-holo/default-cyberpunk-intro-bumper-Landscape.tsx +25 -0
  8. package/src/core/intro/cyberpunk-intro-holo/default-cyberpunk-intro-bumper.stories.tsx +31 -0
  9. package/src/core/intro/cyberpunk-intro-holo/default-cyberpunk-intro-bumper.tsx +118 -0
  10. package/src/core/intro/cyberpunk-intro-holo/index.ts +11 -0
  11. package/src/core/intro/cyberpunk-intro-neon/default-cyberpunk-intro-bumper-Horizontal.tsx +24 -0
  12. package/src/core/intro/cyberpunk-intro-neon/default-cyberpunk-intro-bumper-Landscape.tsx +24 -0
  13. package/src/core/intro/cyberpunk-intro-neon/default-cyberpunk-intro-bumper.stories.tsx +30 -0
  14. package/src/core/intro/cyberpunk-intro-neon/default-cyberpunk-intro-bumper.tsx +108 -0
  15. package/src/core/intro/cyberpunk-intro-neon/index.ts +10 -0
  16. package/src/core/intro/default-cinematic-intro-bumper/default-cinematic-intro-bumper-Horizontal.tsx +24 -0
  17. package/src/core/intro/default-cinematic-intro-bumper/default-cinematic-intro-bumper-Landscape.tsx +24 -0
  18. package/src/core/intro/default-cinematic-intro-bumper/default-cinematic-intro-bumper.stories.tsx +29 -0
  19. package/src/core/intro/default-cinematic-intro-bumper/default-cinematic-intro-bumper.tsx +234 -0
  20. package/src/core/intro/default-cinematic-intro-bumper/index.ts +11 -0
  21. package/src/core/intro/default-festival-intro-bumper/default-festival-intro-bumper-Horizontal.tsx +24 -0
  22. package/src/core/intro/default-festival-intro-bumper/default-festival-intro-bumper-Landscape.tsx +24 -0
  23. package/src/core/intro/default-festival-intro-bumper/default-festival-intro-bumper.stories.tsx +29 -0
  24. package/src/core/intro/default-festival-intro-bumper/default-festival-intro-bumper.tsx +187 -0
  25. package/src/core/intro/default-festival-intro-bumper/index.ts +11 -0
  26. package/src/core/intro/default-intro-bumper/default-intro-bumper-Horizontal.tsx +24 -0
  27. package/src/core/intro/default-intro-bumper/default-intro-bumper-Landscape.tsx +24 -0
  28. package/src/core/intro/default-intro-bumper/default-intro-bumper.stories.tsx +41 -0
  29. package/src/core/intro/default-intro-bumper/default-intro-bumper.tsx +256 -0
  30. package/src/core/intro/default-intro-bumper/index.ts +11 -0
  31. package/src/core/intro/default-noir-intro-bumper/default-noir-intro-bumper-Horizontal.tsx +24 -0
  32. package/src/core/intro/default-noir-intro-bumper/default-noir-intro-bumper-Landscape.tsx +24 -0
  33. package/src/core/intro/default-noir-intro-bumper/default-noir-intro-bumper.stories.tsx +29 -0
  34. package/src/core/intro/default-noir-intro-bumper/default-noir-intro-bumper.tsx +122 -0
  35. package/src/core/intro/default-noir-intro-bumper/index.ts +11 -0
  36. package/src/core/intro/default-trailer-intro-bumper/default-trailer-intro-bumper-Horizontal.tsx +24 -0
  37. package/src/core/intro/default-trailer-intro-bumper/default-trailer-intro-bumper-Landscape.tsx +24 -0
  38. package/src/core/intro/default-trailer-intro-bumper/default-trailer-intro-bumper.stories.tsx +29 -0
  39. package/src/core/intro/default-trailer-intro-bumper/default-trailer-intro-bumper.tsx +181 -0
  40. package/src/core/intro/default-trailer-intro-bumper/index.ts +11 -0
  41. package/src/core/intro/documentary-intro-observation/default-documentary-intro-bumper-Horizontal.tsx +18 -0
  42. package/src/core/intro/documentary-intro-observation/default-documentary-intro-bumper-Landscape.tsx +18 -0
  43. package/src/core/intro/documentary-intro-observation/default-documentary-intro-bumper.stories.tsx +31 -0
  44. package/src/core/intro/documentary-intro-observation/default-documentary-intro-bumper.tsx +158 -0
  45. package/src/core/intro/documentary-intro-observation/index.ts +10 -0
  46. package/src/core/intro/family-intro-reunion/default-family-intro-bumper-Horizontal.tsx +18 -0
  47. package/src/core/intro/family-intro-reunion/default-family-intro-bumper-Landscape.tsx +18 -0
  48. package/src/core/intro/family-intro-reunion/default-family-intro-bumper.stories.tsx +43 -0
  49. package/src/core/intro/family-intro-reunion/default-family-intro-bumper.tsx +165 -0
  50. package/src/core/intro/family-intro-reunion/index.ts +10 -0
  51. package/src/core/intro/festival-intro-spotlight/default-festival-intro-bumper-Horizontal.tsx +1 -0
  52. package/src/core/intro/festival-intro-spotlight/default-festival-intro-bumper-Landscape.tsx +1 -0
  53. package/src/core/intro/festival-intro-spotlight/default-festival-intro-bumper.stories.tsx +30 -0
  54. package/src/core/intro/festival-intro-spotlight/default-festival-intro-bumper.tsx +105 -0
  55. package/src/core/intro/festival-intro-spotlight/index.ts +10 -0
  56. package/src/core/intro/index.test.ts +45 -0
  57. package/src/core/intro/index.ts +17 -0
  58. package/src/core/intro/noir-intro-city/default-noir-intro-bumper-Horizontal.tsx +24 -0
  59. package/src/core/intro/noir-intro-city/default-noir-intro-bumper-Landscape.tsx +24 -0
  60. package/src/core/intro/noir-intro-city/default-noir-intro-bumper.stories.tsx +31 -0
  61. package/src/core/intro/noir-intro-city/default-noir-intro-bumper.tsx +96 -0
  62. package/src/core/intro/noir-intro-city/index.ts +10 -0
  63. package/src/core/intro/noir-intro-deluxe/default-noir-intro-bumper-Horizontal.tsx +1 -0
  64. package/src/core/intro/noir-intro-deluxe/default-noir-intro-bumper-Landscape.tsx +1 -0
  65. package/src/core/intro/noir-intro-deluxe/default-noir-intro-bumper.stories.tsx +31 -0
  66. package/src/core/intro/noir-intro-deluxe/default-noir-intro-bumper.tsx +117 -0
  67. package/src/core/intro/noir-intro-deluxe/index.ts +10 -0
  68. package/src/core/intro/sci-fi-intro/default-sci-fi-intro-bumper-Horizontal.tsx +1 -0
  69. package/src/core/intro/sci-fi-intro/default-sci-fi-intro-bumper-Landscape.tsx +1 -0
  70. package/src/core/intro/sci-fi-intro/default-sci-fi-intro-bumper.stories.tsx +48 -0
  71. package/src/core/intro/sci-fi-intro/default-sci-fi-intro-bumper.tsx +105 -0
  72. package/src/core/intro/sci-fi-intro/index.ts +10 -0
  73. package/src/core/intro/thriller-intro-suspense/default-thriller-intro-bumper-Horizontal.tsx +18 -0
  74. package/src/core/intro/thriller-intro-suspense/default-thriller-intro-bumper-Landscape.tsx +18 -0
  75. package/src/core/intro/thriller-intro-suspense/default-thriller-intro-bumper.stories.tsx +31 -0
  76. package/src/core/intro/thriller-intro-suspense/default-thriller-intro-bumper.tsx +155 -0
  77. package/src/core/intro/thriller-intro-suspense/index.ts +10 -0
  78. package/src/core/intro/trailer-intro-premiere/default-trailer-intro-bumper-Horizontal.tsx +1 -0
  79. package/src/core/intro/trailer-intro-premiere/default-trailer-intro-bumper-Landscape.tsx +1 -0
  80. package/src/core/intro/trailer-intro-premiere/default-trailer-intro-bumper.stories.tsx +30 -0
  81. package/src/core/intro/trailer-intro-premiere/default-trailer-intro-bumper.tsx +104 -0
  82. package/src/core/intro/trailer-intro-premiere/index.ts +10 -0
  83. package/src/core/intro/travel-intro-journey/default-travel-intro-bumper-Horizontal.tsx +18 -0
  84. package/src/core/intro/travel-intro-journey/default-travel-intro-bumper-Landscape.tsx +18 -0
  85. package/src/core/intro/travel-intro-journey/default-travel-intro-bumper.stories.tsx +43 -0
  86. package/src/core/intro/travel-intro-journey/default-travel-intro-bumper.tsx +158 -0
  87. package/src/core/intro/travel-intro-journey/index.ts +10 -0
  88. package/src/core/intro/western-intro/default-western-intro-bumper-Horizontal.tsx +24 -0
  89. package/src/core/intro/western-intro/default-western-intro-bumper-Landscape.tsx +24 -0
  90. package/src/core/intro/western-intro/default-western-intro-bumper.stories.tsx +29 -0
  91. package/src/core/intro/western-intro/default-western-intro-bumper.tsx +146 -0
  92. package/src/core/intro/western-intro/index.ts +4 -0
  93. package/src/core/intro/western-intro-gangster/default-western-intro-bumper-Horizontal.tsx +25 -0
  94. package/src/core/intro/western-intro-gangster/default-western-intro-bumper-Landscape.tsx +25 -0
  95. package/src/core/intro/western-intro-gangster/default-western-intro-bumper.stories.tsx +31 -0
  96. package/src/core/intro/western-intro-gangster/default-western-intro-bumper.tsx +105 -0
  97. package/src/core/intro/western-intro-gangster/index.ts +11 -0
  98. package/src/core/outro/_shared/outro-layout.test.ts +32 -0
  99. package/src/core/outro/_shared/outro-layout.ts +72 -0
  100. package/src/core/outro/award-outro-celebration/default-award-outro-bumper-Horizontal.tsx +18 -0
  101. package/src/core/outro/award-outro-celebration/default-award-outro-bumper-Landscape.tsx +18 -0
  102. package/src/core/outro/award-outro-celebration/default-award-outro-bumper.stories.tsx +42 -0
  103. package/src/core/outro/award-outro-celebration/default-award-outro-bumper.tsx +152 -0
  104. package/src/core/outro/award-outro-celebration/index.ts +10 -0
  105. package/src/core/outro/blackout-outro-finale/default-blackout-outro-bumper-Horizontal.tsx +1 -0
  106. package/src/core/outro/blackout-outro-finale/default-blackout-outro-bumper-Landscape.tsx +1 -0
  107. package/src/core/outro/blackout-outro-finale/default-blackout-outro-bumper.stories.tsx +28 -0
  108. package/src/core/outro/blackout-outro-finale/default-blackout-outro-bumper.tsx +71 -0
  109. package/src/core/outro/blackout-outro-finale/index.ts +10 -0
  110. package/src/core/outro/credits-roll-outro-epic/default-credits-roll-outro-Horizontal.tsx +24 -0
  111. package/src/core/outro/credits-roll-outro-epic/default-credits-roll-outro-Landscape.tsx +24 -0
  112. package/src/core/outro/credits-roll-outro-epic/default-credits-roll-outro.stories.tsx +31 -0
  113. package/src/core/outro/credits-roll-outro-epic/default-credits-roll-outro.tsx +106 -0
  114. package/src/core/outro/credits-roll-outro-epic/index.ts +10 -0
  115. package/src/core/outro/credits-roll-outro-premium/default-credits-roll-outro-Horizontal.tsx +1 -0
  116. package/src/core/outro/credits-roll-outro-premium/default-credits-roll-outro-Landscape.tsx +1 -0
  117. package/src/core/outro/credits-roll-outro-premium/default-credits-roll-outro.stories.tsx +30 -0
  118. package/src/core/outro/credits-roll-outro-premium/default-credits-roll-outro.tsx +88 -0
  119. package/src/core/outro/credits-roll-outro-premium/index.ts +10 -0
  120. package/src/core/outro/credits-roll-outro-royal/default-credits-roll-outro-Horizontal.tsx +25 -0
  121. package/src/core/outro/credits-roll-outro-royal/default-credits-roll-outro-Landscape.tsx +25 -0
  122. package/src/core/outro/credits-roll-outro-royal/default-credits-roll-outro.stories.tsx +32 -0
  123. package/src/core/outro/credits-roll-outro-royal/default-credits-roll-outro.tsx +110 -0
  124. package/src/core/outro/credits-roll-outro-royal/index.ts +11 -0
  125. package/src/core/outro/default-blackout-outro-bumper/default-blackout-outro-bumper-Horizontal.tsx +22 -0
  126. package/src/core/outro/default-blackout-outro-bumper/default-blackout-outro-bumper-Landscape.tsx +22 -0
  127. package/src/core/outro/default-blackout-outro-bumper/default-blackout-outro-bumper.stories.tsx +48 -0
  128. package/src/core/outro/default-blackout-outro-bumper/default-blackout-outro-bumper.tsx +124 -0
  129. package/src/core/outro/default-blackout-outro-bumper/index.ts +11 -0
  130. package/src/core/outro/default-credits-roll-outro/default-credits-roll-outro-Horizontal.tsx +22 -0
  131. package/src/core/outro/default-credits-roll-outro/default-credits-roll-outro-Landscape.tsx +22 -0
  132. package/src/core/outro/default-credits-roll-outro/default-credits-roll-outro.stories.tsx +48 -0
  133. package/src/core/outro/default-credits-roll-outro/default-credits-roll-outro.tsx +208 -0
  134. package/src/core/outro/default-credits-roll-outro/index.ts +11 -0
  135. package/src/core/outro/default-epilogue-outro/default-epilogue-outro-Horizontal.tsx +22 -0
  136. package/src/core/outro/default-epilogue-outro/default-epilogue-outro-Landscape.tsx +22 -0
  137. package/src/core/outro/default-epilogue-outro/default-epilogue-outro.stories.tsx +48 -0
  138. package/src/core/outro/default-epilogue-outro/default-epilogue-outro.tsx +115 -0
  139. package/src/core/outro/default-epilogue-outro/index.ts +11 -0
  140. package/src/core/outro/default-outro-bumper/default-outro-bumper-Horizontal.tsx +22 -0
  141. package/src/core/outro/default-outro-bumper/default-outro-bumper-Landscape.tsx +22 -0
  142. package/src/core/outro/default-outro-bumper/default-outro-bumper.stories.tsx +48 -0
  143. package/src/core/outro/default-outro-bumper/default-outro-bumper.tsx +159 -0
  144. package/src/core/outro/default-outro-bumper/index.ts +11 -0
  145. package/src/core/outro/default-sunset-outro-bumper/default-sunset-outro-bumper-Horizontal.tsx +22 -0
  146. package/src/core/outro/default-sunset-outro-bumper/default-sunset-outro-bumper-Landscape.tsx +22 -0
  147. package/src/core/outro/default-sunset-outro-bumper/default-sunset-outro-bumper.stories.tsx +48 -0
  148. package/src/core/outro/default-sunset-outro-bumper/default-sunset-outro-bumper.tsx +183 -0
  149. package/src/core/outro/default-sunset-outro-bumper/index.ts +11 -0
  150. package/src/core/outro/festival-outro-encore/default-festival-outro-bumper-Horizontal.tsx +18 -0
  151. package/src/core/outro/festival-outro-encore/default-festival-outro-bumper-Landscape.tsx +18 -0
  152. package/src/core/outro/festival-outro-encore/default-festival-outro-bumper.stories.tsx +31 -0
  153. package/src/core/outro/festival-outro-encore/default-festival-outro-bumper.tsx +130 -0
  154. package/src/core/outro/festival-outro-encore/index.ts +10 -0
  155. package/src/core/outro/heist-outro/default-heist-outro-bumper-Horizontal.tsx +24 -0
  156. package/src/core/outro/heist-outro/default-heist-outro-bumper-Landscape.tsx +24 -0
  157. package/src/core/outro/heist-outro/default-heist-outro-bumper.stories.tsx +29 -0
  158. package/src/core/outro/heist-outro/default-heist-outro-bumper.tsx +160 -0
  159. package/src/core/outro/heist-outro/index.ts +4 -0
  160. package/src/core/outro/index.test.ts +88 -0
  161. package/src/core/outro/index.ts +73 -0
  162. package/src/core/outro/memoir-outro-reflection/default-memoir-outro-bumper-Horizontal.tsx +18 -0
  163. package/src/core/outro/memoir-outro-reflection/default-memoir-outro-bumper-Landscape.tsx +18 -0
  164. package/src/core/outro/memoir-outro-reflection/default-memoir-outro-bumper.stories.tsx +42 -0
  165. package/src/core/outro/memoir-outro-reflection/default-memoir-outro-bumper.tsx +158 -0
  166. package/src/core/outro/memoir-outro-reflection/index.ts +10 -0
  167. package/src/core/outro/romance-outro/default-romance-outro-bumper-Horizontal.tsx +1 -0
  168. package/src/core/outro/romance-outro/default-romance-outro-bumper-Landscape.tsx +1 -0
  169. package/src/core/outro/romance-outro/default-romance-outro-bumper.stories.tsx +48 -0
  170. package/src/core/outro/romance-outro/default-romance-outro-bumper.tsx +123 -0
  171. package/src/core/outro/romance-outro/index.ts +10 -0
  172. package/src/core/outro/sunset-outro-coda/default-sunset-outro-bumper-Horizontal.tsx +1 -0
  173. package/src/core/outro/sunset-outro-coda/default-sunset-outro-bumper-Landscape.tsx +1 -0
  174. package/src/core/outro/sunset-outro-coda/default-sunset-outro-bumper.stories.tsx +30 -0
  175. package/src/core/outro/sunset-outro-coda/default-sunset-outro-bumper.tsx +75 -0
  176. package/src/core/outro/sunset-outro-coda/index.ts +10 -0
  177. package/src/core/scene/2dscene/default-2d-scene-Horizontal.stories.tsx +1 -1
  178. package/src/core/scene/2dscene/default-2d-scene.stories.tsx +1 -1
  179. package/src/core/scene/3dscene/default-3d-scene-Horizontal.stories.tsx +1 -1
  180. package/src/core/scene/3dscene/default-3d-scene.stories.tsx +1 -1
  181. package/src/core/scene/index.ts +3 -0
  182. package/src/core/scene/photo/3dvr-photo/default-3dvr-photo-scene-Horizontal.stories.tsx +46 -0
  183. package/src/core/scene/photo/3dvr-photo/default-3dvr-photo-scene-Horizontal.tsx +20 -0
  184. package/src/core/scene/photo/3dvr-photo/default-3dvr-photo-scene-Landscape.tsx +20 -0
  185. package/src/core/scene/photo/3dvr-photo/default-3dvr-photo-scene.stories.tsx +46 -0
  186. package/src/core/scene/photo/3dvr-photo/default-3dvr-photo-scene.tsx +255 -0
  187. package/src/core/scene/photo/3dvr-photo/index.ts +3 -0
  188. package/src/core/scene/photo/default-live-photo-scene-Horizontal.stories.tsx +33 -0
  189. package/src/core/scene/photo/default-live-photo-scene-Horizontal.tsx +20 -0
  190. package/src/core/scene/photo/default-live-photo-scene-Landscape.tsx +20 -0
  191. package/src/core/scene/photo/default-live-photo-scene.stories.tsx +33 -0
  192. package/src/core/scene/photo/default-live-photo-scene.tsx +432 -0
  193. package/src/core/scene/photo/default-photo-strip-scene-Horizontal.tsx +20 -0
  194. package/src/core/scene/photo/default-photo-strip-scene-Landscape.tsx +20 -0
  195. package/src/core/scene/photo/default-photo-strip-scene.stories.tsx +38 -0
  196. package/src/core/scene/photo/default-photo-strip-scene.tsx +19 -0
  197. package/src/core/scene/photo/default-photo-wall-scene-Horizontal.tsx +20 -0
  198. package/src/core/scene/photo/default-photo-wall-scene-Landscape.tsx +20 -0
  199. package/src/core/scene/photo/default-photo-wall-scene.stories.tsx +38 -0
  200. package/src/core/scene/photo/default-photo-wall-scene.tsx +19 -0
  201. package/src/core/scene/photo/effects-photo/default-effects-photo-scene-Horizontal.stories.tsx +44 -0
  202. package/src/core/scene/photo/effects-photo/default-effects-photo-scene-Horizontal.tsx +20 -0
  203. package/src/core/scene/photo/effects-photo/default-effects-photo-scene-Landscape.tsx +20 -0
  204. package/src/core/scene/photo/effects-photo/default-effects-photo-scene.stories.tsx +44 -0
  205. package/src/core/scene/photo/effects-photo/default-effects-photo-scene.tsx +352 -0
  206. package/src/core/scene/photo/effects-photo/index.ts +3 -0
  207. package/src/core/scene/photo/index.ts +25 -0
  208. package/src/core/scene/photo/photo-storybook.test.tsx +112 -0
  209. package/src/core/scene/slide/_shared/index.ts +27 -0
  210. package/src/core/scene/slide/_shared/media-templates.test.ts +47 -0
  211. package/src/core/scene/slide/_shared/media-templates.tsx +324 -0
  212. package/src/core/scene/slide/default-slide-scene-Horizontal.animated.stories.tsx +1 -1
  213. package/src/core/scene/slide/default-slide-scene-Horizontal.stories.tsx +1 -1
  214. package/src/core/scene/slide/default-slide-scene.animated.stories.tsx +1 -1
  215. package/src/core/scene/slide/default-slide-scene.stories.tsx +1 -1
  216. package/src/core/scene/slide/index.test.ts +28 -0
  217. package/src/core/scene/slide/index.ts +14 -0
  218. package/src/core/scene/slide/person-intro/default-person-intro-duo-slide.tsx +19 -0
  219. package/src/core/scene/slide/person-intro/default-person-intro-group-slide.tsx +168 -0
  220. package/src/core/scene/slide/person-intro/default-person-intro-quad-slide.tsx +19 -0
  221. package/src/core/scene/slide/person-intro/default-person-intro-slide-Horizontal.animated.stories.tsx +47 -0
  222. package/src/core/scene/slide/person-intro/default-person-intro-slide-Horizontal.stories.tsx +46 -0
  223. package/src/core/scene/slide/person-intro/default-person-intro-slide-Horizontal.tsx +302 -0
  224. package/src/core/scene/slide/person-intro/default-person-intro-slide-Landscape.tsx +20 -0
  225. package/src/core/scene/slide/person-intro/default-person-intro-slide.animated.stories.tsx +126 -0
  226. package/src/core/scene/slide/person-intro/default-person-intro-slide.stories.tsx +119 -0
  227. package/src/core/scene/slide/person-intro/default-person-intro-slide.tsx +363 -0
  228. package/src/core/scene/slide/person-intro/default-person-intro-trio-slide.tsx +19 -0
  229. package/src/core/scene/slide/person-intro/index.ts +8 -0
  230. package/src/core/scene/slide/photo-album/default-photo-album-multi-slide.tsx +19 -0
  231. package/src/core/scene/slide/photo-album/default-photo-album-pair-slide.tsx +19 -0
  232. package/src/core/scene/slide/photo-album/default-photo-album-single-slide.tsx +19 -0
  233. package/src/core/scene/slide/photo-album/default-photo-album-slide-Horizontal.animated.stories.tsx +26 -0
  234. package/src/core/scene/slide/photo-album/default-photo-album-slide-Horizontal.stories.tsx +25 -0
  235. package/src/core/scene/slide/photo-album/default-photo-album-slide-Horizontal.tsx +20 -0
  236. package/src/core/scene/slide/photo-album/default-photo-album-slide-Landscape.tsx +20 -0
  237. package/src/core/scene/slide/photo-album/default-photo-album-slide.animated.stories.tsx +94 -0
  238. package/src/core/scene/slide/photo-album/default-photo-album-slide.stories.tsx +87 -0
  239. package/src/core/scene/slide/photo-album/default-photo-album-slide.tsx +414 -0
  240. package/src/core/scene/slide/photo-album/index.ts +7 -0
  241. package/src/core/scene/slide/video-showcase/default-video-showcase-multi-slide.tsx +195 -0
  242. package/src/core/scene/slide/video-showcase/default-video-showcase-slide-Horizontal.tsx +212 -0
  243. package/src/core/scene/slide/video-showcase/default-video-showcase-slide-Landscape.tsx +20 -0
  244. package/src/core/scene/slide/video-showcase/default-video-showcase-slide.animated.stories.tsx +78 -0
  245. package/src/core/scene/slide/video-showcase/default-video-showcase-slide.stories.tsx +74 -0
  246. package/src/core/scene/slide/video-showcase/default-video-showcase-slide.tsx +365 -0
  247. package/src/core/scene/slide/video-showcase/index.ts +5 -0
  248. package/src/core/scene/video/default-video-scene-Horizontal.stories.tsx +26 -0
  249. package/src/core/scene/video/default-video-scene-Horizontal.tsx +20 -0
  250. package/src/core/scene/video/default-video-scene-Landscape.tsx +20 -0
  251. package/src/core/scene/video/default-video-scene.stories.tsx +26 -0
  252. package/src/core/scene/video/default-video-scene.tsx +283 -0
  253. package/src/core/scene/video/default-video-split-scene-Horizontal.tsx +20 -0
  254. package/src/core/scene/video/default-video-split-scene-Landscape.tsx +20 -0
  255. package/src/core/scene/video/default-video-split-scene.stories.tsx +41 -0
  256. package/src/core/scene/video/default-video-split-scene.tsx +19 -0
  257. package/src/core/scene/video/default-video-wall-scene-Horizontal.tsx +20 -0
  258. package/src/core/scene/video/default-video-wall-scene-Landscape.tsx +20 -0
  259. package/src/core/scene/video/default-video-wall-scene.stories.tsx +40 -0
  260. package/src/core/scene/video/default-video-wall-scene.tsx +19 -0
  261. package/src/core/scene/video/index.ts +9 -0
  262. package/src/storybook/remotion-preview.tsx +112 -6
  263. package/src/core/intro/default-intro-bumper.stories.tsx +0 -19
  264. package/src/core/intro/default-intro-bumper.tsx +0 -218
  265. package/src/core/outro/default-outro-bumper.stories.tsx +0 -19
  266. package/src/core/outro/default-outro-bumper.tsx +0 -218
@@ -0,0 +1,283 @@
1
+ import type { ReactNode } from 'react'
2
+
3
+ import { z } from 'zod'
4
+
5
+ import { VideoComponent, defineScenePluginMetadata } from '@vibecuting/component-project-helper'
6
+ import { cloneElement, isValidElement } from 'react'
7
+ import { spring, useCurrentFrame, useVideoConfig } from 'remotion'
8
+
9
+ import { BaseRemotionScene, SceneMotionLayer, type BaseRemotionSceneProps, useRemotionSceneRuntime, useSceneConfig } from '../../../base'
10
+ import { defineSceneComponent } from '../../../plugins/scene-component'
11
+
12
+ export interface DefaultVideoSceneProps extends BaseRemotionSceneProps {
13
+ sceneId?: string
14
+ sceneName?: string
15
+ title?: string
16
+ subtitle?: string
17
+ badge?: string
18
+ runtimeLabel?: string
19
+ video: ReactNode
20
+ videos?: ReactNode[]
21
+ poster?: ReactNode
22
+ variant?: 'player' | 'split' | 'wall'
23
+ accent?: string
24
+ secondaryAccent?: string
25
+ textColor?: string
26
+ }
27
+
28
+ export const componentMetadata = defineScenePluginMetadata({
29
+ resourceKind: 'scene',
30
+ name: 'DefaultVideoScene',
31
+ description: 'Video-first scene with poster-led motion and editorial framing',
32
+ sourceFile: 'src/core/scene/video/default-video-scene.tsx',
33
+ pluginKey: 'core.video.preview',
34
+ tags: ['scene', 'video', 'preview', 'player'],
35
+ aspectRatio: '16:9',
36
+ sceneType: 'scene',
37
+ sceneFamily: 'custom',
38
+ rootLayout: 'absolute-fill',
39
+ propsTypeName: 'DefaultVideoSceneProps',
40
+ })
41
+
42
+ function VideoFrame({
43
+ node,
44
+ isPortrait,
45
+ animationProgress,
46
+ }: {
47
+ node: ReactNode
48
+ isPortrait: boolean
49
+ animationProgress: number
50
+ }) {
51
+ return (
52
+ <div
53
+ style={{
54
+ width: '100%',
55
+ height: '100%',
56
+ overflow: 'hidden',
57
+ border: '1px solid rgba(255,255,255,0.14)',
58
+ background: 'rgba(2,6,23,0.86)',
59
+ transform: `scale(${1 + (1 - animationProgress) * 0.012})`,
60
+ }}
61
+ >
62
+ {node}
63
+ </div>
64
+ )
65
+ }
66
+
67
+ function renderCoverMedia(node: ReactNode) {
68
+ if (isValidElement(node)) {
69
+ const existingStyle = (node.props as { style?: Record<string, unknown> }).style ?? {}
70
+ return cloneElement(node, {
71
+ ...(node.props as Record<string, unknown>),
72
+ style: {
73
+ ...existingStyle,
74
+ width: '100%',
75
+ height: '100%',
76
+ objectFit: 'cover',
77
+ display: 'block',
78
+ minWidth: 0,
79
+ minHeight: 0,
80
+ },
81
+ })
82
+ }
83
+
84
+ return <div style={{ width: '100%', height: '100%', minWidth: 0, minHeight: 0 }}>{node}</div>
85
+ }
86
+
87
+ export const DefaultVideoScene = VideoComponent(componentMetadata)(
88
+ defineSceneComponent({
89
+ family: 'custom',
90
+ propsSchema: z.object({
91
+ sceneId: z.string().optional(),
92
+ sceneName: z.string().optional(),
93
+ title: z.string().optional(),
94
+ subtitle: z.string().optional(),
95
+ badge: z.string().optional(),
96
+ runtimeLabel: z.string().optional(),
97
+ video: z.any(),
98
+ videos: z.array(z.any()).optional(),
99
+ poster: z.any().optional(),
100
+ variant: z.enum(['player', 'split', 'wall']).optional(),
101
+ accent: z.string().optional(),
102
+ secondaryAccent: z.string().optional(),
103
+ textColor: z.string().optional(),
104
+ }),
105
+ component: function DefaultVideoScene({
106
+ id,
107
+ name,
108
+ sceneId,
109
+ sceneName,
110
+ title,
111
+ subtitle,
112
+ badge,
113
+ runtimeLabel,
114
+ video,
115
+ videos,
116
+ poster,
117
+ variant = 'player',
118
+ accent,
119
+ secondaryAccent,
120
+ textColor,
121
+ }: DefaultVideoSceneProps) {
122
+ const runtime = useRemotionSceneRuntime()
123
+ const sceneConfig = useSceneConfig()
124
+ const frame = useCurrentFrame()
125
+ const { fps } = useVideoConfig()
126
+ const isPortrait = runtime.height > runtime.width
127
+ const animationProgress =
128
+ sceneConfig.sceneType === 'animation'
129
+ ? spring({
130
+ frame,
131
+ fps,
132
+ config: {
133
+ damping: 18,
134
+ mass: 0.8,
135
+ stiffness: 110,
136
+ },
137
+ })
138
+ : 1
139
+ const titleSize = Math.round(runtime.height * (isPortrait ? 0.032 : 0.038))
140
+ const subtitleSize = Math.round(runtime.height * 0.017)
141
+ const frames = (videos?.length ? videos : [video]).slice(0, 4)
142
+
143
+ return (
144
+ <BaseRemotionScene
145
+ id={id ?? sceneId}
146
+ name={name ?? sceneName ?? title}
147
+ style={{
148
+ background: isPortrait
149
+ ? `linear-gradient(180deg, ${accent ?? '#020617'} 0%, #0f172a 55%, #000000 100%)`
150
+ : `radial-gradient(circle at 50% 24%, ${secondaryAccent ?? 'rgba(255,255,255,0.08)'} 0%, ${accent ?? '#020617'} 48%, #000000 100%)`,
151
+ color: textColor ?? '#f8fafc',
152
+ padding: Math.round(runtime.height * (isPortrait ? 0.02 : 0.03)),
153
+ }}
154
+ >
155
+ <section
156
+ style={{
157
+ width: '100%',
158
+ height: '100%',
159
+ display: 'grid',
160
+ gridTemplateRows: 'minmax(0, 1fr) auto',
161
+ gap: 16,
162
+ minWidth: 0,
163
+ minHeight: 0,
164
+ }}
165
+ >
166
+ {variant === 'wall' ? (
167
+ <div
168
+ style={{
169
+ display: 'grid',
170
+ gridTemplateColumns: isPortrait ? '1fr 1fr' : 'repeat(2, minmax(0, 1fr))',
171
+ gridTemplateRows: isPortrait ? 'repeat(2, minmax(0, 1fr))' : 'repeat(2, minmax(0, 1fr))',
172
+ gap: 12,
173
+ minWidth: 0,
174
+ minHeight: 0,
175
+ }}
176
+ >
177
+ {frames.map((item, index) => (
178
+ <SceneMotionLayer key={`video-wall-${index}`} variant="media" delayIndex={index}>
179
+ <VideoFrame node={item} isPortrait={isPortrait} animationProgress={animationProgress} />
180
+ </SceneMotionLayer>
181
+ ))}
182
+ </div>
183
+ ) : variant === 'split' ? (
184
+ <div
185
+ style={{
186
+ display: 'grid',
187
+ gridTemplateColumns: isPortrait ? '1fr' : 'minmax(0, 1.18fr) minmax(250px, 0.82fr)',
188
+ gap: 16,
189
+ minWidth: 0,
190
+ minHeight: 0,
191
+ }}
192
+ >
193
+ <SceneMotionLayer variant="panel">
194
+ <VideoFrame node={video} isPortrait={isPortrait} animationProgress={animationProgress} />
195
+ </SceneMotionLayer>
196
+ <div
197
+ style={{
198
+ display: 'grid',
199
+ gap: 12,
200
+ alignContent: 'start',
201
+ padding: isPortrait ? '0' : '8px 0',
202
+ minWidth: 0,
203
+ }}
204
+ >
205
+ <div style={{ display: 'flex', justifyContent: 'space-between', gap: 12, alignItems: 'center' }}>
206
+ <div style={{ fontSize: Math.round(runtime.height * 0.014), letterSpacing: '0.24em', textTransform: 'uppercase', opacity: 0.58 }}>
207
+ {badge ?? 'Video'}
208
+ </div>
209
+ {runtimeLabel ? (
210
+ <div style={{ fontSize: Math.round(runtime.height * 0.014), letterSpacing: '0.18em', textTransform: 'uppercase', opacity: 0.58 }}>
211
+ {runtimeLabel}
212
+ </div>
213
+ ) : null}
214
+ </div>
215
+ {title ? (
216
+ <SceneMotionLayer variant="hero-title">
217
+ <div style={{ fontSize: titleSize, lineHeight: 0.96, letterSpacing: '-0.06em', fontWeight: 800 }}>{title}</div>
218
+ </SceneMotionLayer>
219
+ ) : null}
220
+ {subtitle ? <div style={{ fontSize: subtitleSize, lineHeight: 1.45, opacity: 0.84 }}>{subtitle}</div> : null}
221
+ <div style={{ border: '1px solid rgba(255,255,255,0.12)', background: 'rgba(2,6,23,0.56)', padding: 14, display: 'grid', gap: 10 }}>
222
+ <div style={{ fontSize: Math.round(runtime.height * 0.013), letterSpacing: '0.22em', textTransform: 'uppercase', opacity: 0.56 }}>Editorial Notes</div>
223
+ <div style={{ fontSize: Math.round(runtime.height * 0.018), lineHeight: 1.45, opacity: 0.88 }}>
224
+ Use this layout for review notes, chapter context, or a companion still beside the clip.
225
+ </div>
226
+ </div>
227
+ </div>
228
+ </div>
229
+ ) : (
230
+ <div
231
+ style={{
232
+ position: 'relative',
233
+ width: '100%',
234
+ height: '100%',
235
+ aspectRatio: isPortrait ? '9 / 16' : '16 / 9',
236
+ minWidth: 0,
237
+ minHeight: 0,
238
+ overflow: 'hidden',
239
+ border: '1px solid rgba(255,255,255,0.14)',
240
+ background: 'rgba(2,6,23,0.84)',
241
+ }}
242
+ >
243
+ <SceneMotionLayer
244
+ variant="media"
245
+ style={{
246
+ position: 'absolute',
247
+ inset: '-8%',
248
+ opacity: 0.26,
249
+ filter: 'blur(22px) saturate(1.06)',
250
+ transform: `scale(${1.12 + (1 - animationProgress) * 0.02})`,
251
+ }}
252
+ >
253
+ {renderCoverMedia(poster ?? video)}
254
+ </SceneMotionLayer>
255
+ <SceneMotionLayer variant="media" style={{ position: 'absolute', inset: 0 }}>
256
+ {renderCoverMedia(poster ?? video)}
257
+ </SceneMotionLayer>
258
+ <div
259
+ aria-hidden="true"
260
+ style={{
261
+ position: 'absolute',
262
+ inset: 0,
263
+ background: 'linear-gradient(180deg, rgba(2,6,23,0.1) 0%, rgba(2,6,23,0.2) 42%, rgba(2,6,23,0.72) 100%)',
264
+ }}
265
+ />
266
+ <div style={{ position: 'absolute', left: 16, top: 16, display: 'flex', gap: 10, alignItems: 'center' }}>
267
+ <div style={{ width: 10, height: 10, borderRadius: 9999, background: 'rgba(239,68,68,0.95)', boxShadow: '0 0 0 4px rgba(239,68,68,0.16)' }} />
268
+ <div style={{ fontSize: Math.round(runtime.height * 0.013), letterSpacing: '0.24em', textTransform: 'uppercase', opacity: 0.72 }}>
269
+ {badge ?? 'Video Preview'}
270
+ </div>
271
+ </div>
272
+ <div style={{ position: 'absolute', left: 16, right: 16, bottom: 16, display: 'grid', gap: 8 }}>
273
+ {title ? <div style={{ fontSize: titleSize, fontWeight: 800, letterSpacing: '-0.06em', lineHeight: 0.95 }}>{title}</div> : null}
274
+ {subtitle ? <div style={{ fontSize: subtitleSize, lineHeight: 1.45, opacity: 0.86, maxWidth: isPortrait ? '88%' : '60%' }}>{subtitle}</div> : null}
275
+ </div>
276
+ </div>
277
+ )}
278
+ </section>
279
+ </BaseRemotionScene>
280
+ )
281
+ },
282
+ }),
283
+ )
@@ -0,0 +1,20 @@
1
+ import type { ComponentProps } from 'react'
2
+
3
+ import { VideoComponent, type ScenePluginMetadata } from '@vibecuting/component-project-helper'
4
+
5
+ import { DefaultVideoSplitScene, componentMetadata as baseComponentMetadata } from './default-video-split-scene'
6
+
7
+ export const componentMetadata: ScenePluginMetadata = {
8
+ ...baseComponentMetadata,
9
+ name: 'DefaultVideoSplitSceneHorizontal',
10
+ description: 'Video split preview scene (Portrait 9:16 variant)',
11
+ sourceFile: 'src/core/scene/video/default-video-split-scene-Horizontal.tsx',
12
+ aspectRatio: '9:16',
13
+ tags: Array.from(new Set([...(baseComponentMetadata.tags ?? []), 'horizontal'])),
14
+ }
15
+
16
+ export const DefaultVideoSplitSceneHorizontal = VideoComponent(componentMetadata)(function DefaultVideoSplitSceneHorizontal(
17
+ props: ComponentProps<typeof DefaultVideoSplitScene>,
18
+ ) {
19
+ return <DefaultVideoSplitScene {...props} />
20
+ })
@@ -0,0 +1,20 @@
1
+ import type { ComponentProps } from 'react'
2
+
3
+ import { VideoComponent, type ScenePluginMetadata } from '@vibecuting/component-project-helper'
4
+
5
+ import { DefaultVideoSplitScene, componentMetadata as baseComponentMetadata } from './default-video-split-scene'
6
+
7
+ export const componentMetadata: ScenePluginMetadata = {
8
+ ...baseComponentMetadata,
9
+ name: 'DefaultVideoSplitSceneLandscape',
10
+ description: 'Video split preview scene (Landscape 16:9 variant)',
11
+ sourceFile: 'src/core/scene/video/default-video-split-scene-Landscape.tsx',
12
+ aspectRatio: '16:9',
13
+ tags: Array.from(new Set([...(baseComponentMetadata.tags ?? []), 'landscape'])),
14
+ }
15
+
16
+ export const DefaultVideoSplitSceneLandscape = VideoComponent(componentMetadata)(function DefaultVideoSplitSceneLandscape(
17
+ props: ComponentProps<typeof DefaultVideoSplitScene>,
18
+ ) {
19
+ return <DefaultVideoSplitScene {...props} />
20
+ })
@@ -0,0 +1,41 @@
1
+ import { DefaultVideoSplitSceneLandscape } from './default-video-split-scene-Landscape'
2
+ import { DefaultVideoSplitSceneHorizontal } from './default-video-split-scene-Horizontal'
3
+
4
+ const frame = (
5
+ <div
6
+ style={{
7
+ width: '100%',
8
+ height: '100%',
9
+ background:
10
+ 'linear-gradient(180deg, rgba(255,255,255,0.18), rgba(2,6,23,0.84)), linear-gradient(135deg, #0f766e 0%, #1d4ed8 52%, #020617 100%)',
11
+ }}
12
+ />
13
+ )
14
+
15
+ const args = {
16
+ title: 'Editorial Split',
17
+ subtitle: 'Use this when the clip needs a companion still, notes, or a second framing column.',
18
+ badge: 'Split',
19
+ runtimeLabel: '02:24',
20
+ video: frame,
21
+ poster: frame,
22
+ }
23
+
24
+ const meta = {
25
+ title: 'core/scene/video/DefaultVideoSplitSceneLandscape',
26
+ component: DefaultVideoSplitSceneLandscape,
27
+ args,
28
+ }
29
+
30
+ export default meta
31
+
32
+ export const Default = { parameters: { scenePreviewAspectRatio: '16:9' } }
33
+ export const Animated = { parameters: { scenePreviewAspectRatio: '16:9', scenePreviewMode: 'animation' } }
34
+ export const Horizontal = {
35
+ render: (storyArgs: typeof args) => <DefaultVideoSplitSceneHorizontal {...storyArgs} />,
36
+ parameters: { scenePreviewAspectRatio: '9:16' },
37
+ }
38
+ export const HorizontalAnimated = {
39
+ render: (storyArgs: typeof args) => <DefaultVideoSplitSceneHorizontal {...storyArgs} />,
40
+ parameters: { scenePreviewAspectRatio: '9:16', scenePreviewMode: 'animation' },
41
+ }
@@ -0,0 +1,19 @@
1
+ import type { ComponentProps } from 'react'
2
+
3
+ import { VideoComponent, type ScenePluginMetadata } from '@vibecuting/component-project-helper'
4
+
5
+ import { DefaultVideoScene, componentMetadata as baseComponentMetadata } from './default-video-scene'
6
+
7
+ export const componentMetadata: ScenePluginMetadata = {
8
+ ...baseComponentMetadata,
9
+ name: 'DefaultVideoSplitScene',
10
+ description: 'Video split preview scene',
11
+ sourceFile: 'src/core/scene/video/default-video-split-scene.tsx',
12
+ tags: Array.from(new Set([...(baseComponentMetadata.tags ?? []), 'split'])),
13
+ }
14
+
15
+ export const DefaultVideoSplitScene = VideoComponent(componentMetadata)(function DefaultVideoSplitScene(
16
+ props: ComponentProps<typeof DefaultVideoScene>,
17
+ ) {
18
+ return <DefaultVideoScene {...props} variant="split" />
19
+ })
@@ -0,0 +1,20 @@
1
+ import type { ComponentProps } from 'react'
2
+
3
+ import { VideoComponent, type ScenePluginMetadata } from '@vibecuting/component-project-helper'
4
+
5
+ import { DefaultVideoWallScene, componentMetadata as baseComponentMetadata } from './default-video-wall-scene'
6
+
7
+ export const componentMetadata: ScenePluginMetadata = {
8
+ ...baseComponentMetadata,
9
+ name: 'DefaultVideoWallSceneHorizontal',
10
+ description: 'Video wall preview scene (Portrait 9:16 variant)',
11
+ sourceFile: 'src/core/scene/video/default-video-wall-scene-Horizontal.tsx',
12
+ aspectRatio: '9:16',
13
+ tags: Array.from(new Set([...(baseComponentMetadata.tags ?? []), 'horizontal'])),
14
+ }
15
+
16
+ export const DefaultVideoWallSceneHorizontal = VideoComponent(componentMetadata)(function DefaultVideoWallSceneHorizontal(
17
+ props: ComponentProps<typeof DefaultVideoWallScene>,
18
+ ) {
19
+ return <DefaultVideoWallScene {...props} />
20
+ })
@@ -0,0 +1,20 @@
1
+ import type { ComponentProps } from 'react'
2
+
3
+ import { VideoComponent, type ScenePluginMetadata } from '@vibecuting/component-project-helper'
4
+
5
+ import { DefaultVideoWallScene, componentMetadata as baseComponentMetadata } from './default-video-wall-scene'
6
+
7
+ export const componentMetadata: ScenePluginMetadata = {
8
+ ...baseComponentMetadata,
9
+ name: 'DefaultVideoWallSceneLandscape',
10
+ description: 'Video wall preview scene (Landscape 16:9 variant)',
11
+ sourceFile: 'src/core/scene/video/default-video-wall-scene-Landscape.tsx',
12
+ aspectRatio: '16:9',
13
+ tags: Array.from(new Set([...(baseComponentMetadata.tags ?? []), 'landscape'])),
14
+ }
15
+
16
+ export const DefaultVideoWallSceneLandscape = VideoComponent(componentMetadata)(function DefaultVideoWallSceneLandscape(
17
+ props: ComponentProps<typeof DefaultVideoWallScene>,
18
+ ) {
19
+ return <DefaultVideoWallScene {...props} />
20
+ })
@@ -0,0 +1,40 @@
1
+ import { DefaultVideoWallSceneHorizontal } from './default-video-wall-scene-Horizontal'
2
+ import { DefaultVideoWallSceneLandscape } from './default-video-wall-scene-Landscape'
3
+
4
+ const frame = (
5
+ <div
6
+ style={{
7
+ width: '100%',
8
+ height: '100%',
9
+ background:
10
+ 'linear-gradient(180deg, rgba(255,255,255,0.16), rgba(2,6,23,0.84)), linear-gradient(135deg, #7c3aed 0%, #1d4ed8 42%, #020617 100%)',
11
+ }}
12
+ />
13
+ )
14
+
15
+ const args = {
16
+ title: 'Clip Wall',
17
+ subtitle: 'Four clips arranged like a screening board or trailer review wall.',
18
+ badge: 'Wall',
19
+ video: frame,
20
+ videos: [frame, frame, frame, frame],
21
+ }
22
+
23
+ const meta = {
24
+ title: 'core/scene/video/DefaultVideoWallSceneLandscape',
25
+ component: DefaultVideoWallSceneLandscape,
26
+ args,
27
+ }
28
+
29
+ export default meta
30
+
31
+ export const Default = { parameters: { scenePreviewAspectRatio: '16:9' } }
32
+ export const Animated = { parameters: { scenePreviewAspectRatio: '16:9', scenePreviewMode: 'animation' } }
33
+ export const Horizontal = {
34
+ render: (storyArgs: typeof args) => <DefaultVideoWallSceneHorizontal {...storyArgs} />,
35
+ parameters: { scenePreviewAspectRatio: '9:16' },
36
+ }
37
+ export const HorizontalAnimated = {
38
+ render: (storyArgs: typeof args) => <DefaultVideoWallSceneHorizontal {...storyArgs} />,
39
+ parameters: { scenePreviewAspectRatio: '9:16', scenePreviewMode: 'animation' },
40
+ }
@@ -0,0 +1,19 @@
1
+ import type { ComponentProps } from 'react'
2
+
3
+ import { VideoComponent, type ScenePluginMetadata } from '@vibecuting/component-project-helper'
4
+
5
+ import { DefaultVideoScene, componentMetadata as baseComponentMetadata } from './default-video-scene'
6
+
7
+ export const componentMetadata: ScenePluginMetadata = {
8
+ ...baseComponentMetadata,
9
+ name: 'DefaultVideoWallScene',
10
+ description: 'Video wall preview scene',
11
+ sourceFile: 'src/core/scene/video/default-video-wall-scene.tsx',
12
+ tags: Array.from(new Set([...(baseComponentMetadata.tags ?? []), 'wall', 'multi'])),
13
+ }
14
+
15
+ export const DefaultVideoWallScene = VideoComponent(componentMetadata)(function DefaultVideoWallScene(
16
+ props: ComponentProps<typeof DefaultVideoScene>,
17
+ ) {
18
+ return <DefaultVideoScene {...props} variant="wall" />
19
+ })
@@ -0,0 +1,9 @@
1
+ export { DefaultVideoScene, componentMetadata as DefaultVideoSceneMetadata } from './default-video-scene'
2
+ export { DefaultVideoSceneLandscape, componentMetadata as DefaultVideoSceneLandscapeMetadata } from './default-video-scene-Landscape'
3
+ export { DefaultVideoSceneHorizontal, componentMetadata as DefaultVideoSceneHorizontalMetadata } from './default-video-scene-Horizontal'
4
+ export { DefaultVideoSplitScene, componentMetadata as DefaultVideoSplitSceneMetadata } from './default-video-split-scene'
5
+ export { DefaultVideoSplitSceneLandscape, componentMetadata as DefaultVideoSplitSceneLandscapeMetadata } from './default-video-split-scene-Landscape'
6
+ export { DefaultVideoSplitSceneHorizontal, componentMetadata as DefaultVideoSplitSceneHorizontalMetadata } from './default-video-split-scene-Horizontal'
7
+ export { DefaultVideoWallScene, componentMetadata as DefaultVideoWallSceneMetadata } from './default-video-wall-scene'
8
+ export { DefaultVideoWallSceneLandscape, componentMetadata as DefaultVideoWallSceneLandscapeMetadata } from './default-video-wall-scene-Landscape'
9
+ export { DefaultVideoWallSceneHorizontal, componentMetadata as DefaultVideoWallSceneHorizontalMetadata } from './default-video-wall-scene-Horizontal'
@@ -61,12 +61,8 @@ type SpringConfig = {
61
61
  }
62
62
 
63
63
  function clamp01(value: number) {
64
- if (value < 0) {
65
- return 0
66
- }
67
- if (value > 1) {
68
- return 1
69
- }
64
+ if (value < 0) return 0
65
+ if (value > 1) return 1
70
66
  return value
71
67
  }
72
68
 
@@ -91,6 +87,116 @@ export function spring({
91
87
  return clamp01(eased + wobble)
92
88
  }
93
89
 
90
+ type Extrapolate = 'clamp' | 'extend' | 'identity'
91
+
92
+ type EasingFunction = (value: number) => number
93
+
94
+ function clamp(value: number, min: number, max: number) {
95
+ if (value < min) return min
96
+ if (value > max) return max
97
+ return value
98
+ }
99
+
100
+ function wrapInOut(easing: EasingFunction): EasingFunction {
101
+ return (value) => {
102
+ if (value <= 0.5) {
103
+ return easing(value * 2) / 2
104
+ }
105
+ return 1 - easing((1 - value) * 2) / 2
106
+ }
107
+ }
108
+
109
+ function wrapOut(easing: EasingFunction): EasingFunction {
110
+ return (value) => 1 - easing(1 - value)
111
+ }
112
+
113
+ function wrapIn(easing: EasingFunction): EasingFunction {
114
+ return (value) => easing(value)
115
+ }
116
+
117
+ export const Easing = {
118
+ linear: (value: number) => value,
119
+ quad: (value: number) => value * value,
120
+ cubic: (value: number) => value * value * value,
121
+ quart: (value: number) => value * value * value * value,
122
+ quint: (value: number) => value * value * value * value * value,
123
+ sin: (value: number) => 1 - Math.cos((value * Math.PI) / 2),
124
+ exp: (value: number) => (value === 0 ? 0 : 2 ** (10 * (value - 1))),
125
+ circle: (value: number) => 1 - Math.sqrt(1 - value * value),
126
+ back: (value: number) => {
127
+ const overshoot = 1.70158
128
+ return value * value * ((overshoot + 1) * value - overshoot)
129
+ },
130
+ in: wrapIn,
131
+ out: wrapOut,
132
+ inOut: wrapInOut,
133
+ }
134
+
135
+ export function interpolate(
136
+ input: number,
137
+ inputRange: number[],
138
+ outputRange: number[],
139
+ options?: {
140
+ extrapolateLeft?: Extrapolate
141
+ extrapolateRight?: Extrapolate
142
+ easing?: EasingFunction
143
+ },
144
+ ) {
145
+ if (inputRange.length !== outputRange.length || inputRange.length < 2) {
146
+ throw new Error('interpolate() expects inputRange and outputRange of the same length >= 2')
147
+ }
148
+
149
+ const leftMode = options?.extrapolateLeft ?? 'extend'
150
+ const rightMode = options?.extrapolateRight ?? 'extend'
151
+ const easing = options?.easing
152
+
153
+ const firstInput = inputRange[0]
154
+ const lastInput = inputRange[inputRange.length - 1]
155
+
156
+ if (input < firstInput) {
157
+ if (leftMode === 'identity') return input
158
+ if (leftMode === 'clamp') return outputRange[0]
159
+ }
160
+
161
+ if (input > lastInput) {
162
+ if (rightMode === 'identity') return input
163
+ if (rightMode === 'clamp') return outputRange[outputRange.length - 1]
164
+ }
165
+
166
+ let segmentIndex = 0
167
+ for (let index = 0; index < inputRange.length - 1; index += 1) {
168
+ if (inputRange[index + 1] >= input) {
169
+ segmentIndex = index
170
+ break
171
+ }
172
+ segmentIndex = inputRange.length - 2
173
+ }
174
+
175
+ const inputStart = inputRange[segmentIndex]
176
+ const inputEnd = inputRange[segmentIndex + 1]
177
+ const outputStart = outputRange[segmentIndex]
178
+ const outputEnd = outputRange[segmentIndex + 1]
179
+ const span = inputEnd - inputStart
180
+ const rawProgress = span === 0 ? 0 : (input - inputStart) / span
181
+ const progress = clamp(easing ? easing(clamp(rawProgress, 0, 1)) : rawProgress, 0, 1)
182
+
183
+ return outputStart + (outputEnd - outputStart) * progress
184
+ }
185
+
186
+ export function Img({
187
+ src,
188
+ alt,
189
+ style,
190
+ ...rest
191
+ }: {
192
+ src: string
193
+ alt?: string
194
+ style?: CSSProperties
195
+ [key: string]: unknown
196
+ }) {
197
+ return <img {...rest} src={src} alt={alt} style={style} />
198
+ }
199
+
94
200
  export function AbsoluteFill({
95
201
  children,
96
202
  style,
@@ -1,19 +0,0 @@
1
- import { DefaultIntroBumper } from './default-intro-bumper'
2
-
3
- const meta = {
4
- title: 'core/intro/DefaultIntroBumper',
5
- component: DefaultIntroBumper,
6
- args: {
7
- kicker: 'A Vibecuting Original',
8
- title: 'Video Project Core',
9
- subtitle: 'A cinematic opening bumper with centered title treatment and room for production credits.',
10
- creditLine: 'Directed by Vibecuting Studio',
11
- footer: 'Opening Sequence',
12
- accent: '#020617',
13
- secondaryAccent: '#1d4ed8',
14
- },
15
- }
16
-
17
- export default meta
18
-
19
- export const Default = {}