@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,20 @@
1
+ import type { ComponentProps } from 'react'
2
+
3
+ import { VideoComponent, type ScenePluginMetadata } from '@vibecuting/component-project-helper'
4
+
5
+ import { DefaultEffectsPhotoScene, componentMetadata as baseComponentMetadata } from './default-effects-photo-scene'
6
+
7
+ export const componentMetadata: ScenePluginMetadata = {
8
+ ...baseComponentMetadata,
9
+ name: 'DefaultEffectsPhotoSceneHorizontal',
10
+ description: 'Photo effects scene for 9:16 portrait previews with a vertical layout',
11
+ sourceFile: 'src/core/scene/photo/effects-photo/default-effects-photo-scene-Horizontal.tsx',
12
+ aspectRatio: '9:16',
13
+ tags: Array.from(new Set([...(baseComponentMetadata.tags ?? []), 'horizontal'])),
14
+ }
15
+
16
+ export const DefaultEffectsPhotoSceneHorizontal = VideoComponent(componentMetadata)(function DefaultEffectsPhotoSceneHorizontal(
17
+ props: ComponentProps<typeof DefaultEffectsPhotoScene>,
18
+ ) {
19
+ return <DefaultEffectsPhotoScene {...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 { DefaultEffectsPhotoScene, componentMetadata as baseComponentMetadata } from './default-effects-photo-scene'
6
+
7
+ export const componentMetadata: ScenePluginMetadata = {
8
+ ...baseComponentMetadata,
9
+ name: 'DefaultEffectsPhotoSceneLandscape',
10
+ description: 'Photo effects scene for 16:9 landscape previews with a wide cinematic layout',
11
+ sourceFile: 'src/core/scene/photo/effects-photo/default-effects-photo-scene-Landscape.tsx',
12
+ aspectRatio: '16:9',
13
+ tags: Array.from(new Set([...(baseComponentMetadata.tags ?? []), 'landscape'])),
14
+ }
15
+
16
+ export const DefaultEffectsPhotoSceneLandscape = VideoComponent(componentMetadata)(function DefaultEffectsPhotoSceneLandscape(
17
+ props: ComponentProps<typeof DefaultEffectsPhotoScene>,
18
+ ) {
19
+ return <DefaultEffectsPhotoScene {...props} />
20
+ })
@@ -0,0 +1,44 @@
1
+ import { DefaultEffectsPhotoSceneLandscape } from './default-effects-photo-scene-Landscape'
2
+
3
+ const photoUrl = 'https://heyaai-statics-1342239856.cos.ap-guangzhou.myqcloud.com/tmp/premium_photo-1779404552087-0f905162376f-121.jpeg'
4
+
5
+ const meta = {
6
+ title: 'core/scene/photo/effects-photo/DefaultEffectsPhotoSceneLandscape',
7
+ component: DefaultEffectsPhotoSceneLandscape,
8
+ args: {
9
+ title: 'Golden Echo',
10
+ subtitle: 'Layered photo grading with glow, grain, warmth and a cinematic vignette.',
11
+ badge: 'Effects Photo',
12
+ imageSrc: photoUrl,
13
+ effects: [
14
+ { type: 'glow', intensity: 0.55 },
15
+ { type: 'vignette', intensity: 0.65 },
16
+ { type: 'grain', intensity: 0.12 },
17
+ { type: 'warmth', intensity: 0.18, hue: '#f59e0b' },
18
+ ],
19
+ accent: '#020617',
20
+ secondaryAccent: '#1d4ed8',
21
+ },
22
+ }
23
+
24
+ export default meta
25
+
26
+ export const Default = {
27
+ parameters: {
28
+ scenePreviewAspectRatio: '16:9',
29
+ },
30
+ }
31
+
32
+ export const Animated = {
33
+ parameters: {
34
+ scenePreviewAspectRatio: '16:9',
35
+ scenePreviewMode: 'animation',
36
+ },
37
+ }
38
+
39
+ export const Both = {
40
+ parameters: {
41
+ scenePreviewAspectRatio: '16:9',
42
+ scenePreviewMode: 'both',
43
+ },
44
+ }
@@ -0,0 +1,352 @@
1
+ import { useMemo } from 'react'
2
+
3
+ import { z } from 'zod'
4
+
5
+ import { VideoComponent, defineScenePluginMetadata } from '@vibecuting/component-project-helper'
6
+ import { Easing, Img, interpolate, spring, useCurrentFrame, useVideoConfig } from 'remotion'
7
+
8
+ import { BaseRemotionScene, type BaseRemotionSceneProps, useRemotionSceneRuntime, useSceneConfig } from '../../../../base'
9
+ import { defineSceneComponent } from '../../../../plugins/scene-component'
10
+
11
+ export type PhotoEffectType = 'vignette' | 'grain' | 'glow' | 'warmth' | 'soft-focus'
12
+
13
+ export interface PhotoEffect {
14
+ type: PhotoEffectType
15
+ intensity?: number
16
+ hue?: string
17
+ }
18
+
19
+ export interface DefaultEffectsPhotoSceneProps extends BaseRemotionSceneProps {
20
+ sceneId?: string
21
+ sceneName?: string
22
+ title?: string
23
+ subtitle?: string
24
+ badge?: string
25
+ imageSrc: string
26
+ effects?: PhotoEffect[]
27
+ accent?: string
28
+ secondaryAccent?: string
29
+ textColor?: string
30
+ }
31
+
32
+ export const componentMetadata = defineScenePluginMetadata({
33
+ resourceKind: 'scene',
34
+ name: 'DefaultEffectsPhotoScene',
35
+ description: 'Photo scene with layered Remotion effects and cinematic grading',
36
+ sourceFile: 'src/core/scene/photo/effects-photo/default-effects-photo-scene.tsx',
37
+ pluginKey: 'core.photo.effects-photo',
38
+ tags: ['scene', 'photo', 'effects', 'image', 'cinematic'],
39
+ aspectRatio: '16:9',
40
+ sceneType: 'scene',
41
+ sceneFamily: 'custom',
42
+ rootLayout: 'absolute-fill',
43
+ propsTypeName: 'DefaultEffectsPhotoSceneProps',
44
+ })
45
+
46
+ function matchesEffect(effects: PhotoEffect[] | undefined, type: PhotoEffectType) {
47
+ return effects?.some((effect) => effect.type === type) ?? false
48
+ }
49
+
50
+ function effectIntensity(effects: PhotoEffect[] | undefined, type: PhotoEffectType, fallback: number) {
51
+ return effects?.find((effect) => effect.type === type)?.intensity ?? fallback
52
+ }
53
+
54
+ export const DefaultEffectsPhotoScene = VideoComponent(componentMetadata)(
55
+ defineSceneComponent({
56
+ family: 'custom',
57
+ propsSchema: z.object({
58
+ sceneId: z.string().optional(),
59
+ sceneName: z.string().optional(),
60
+ title: z.string().optional(),
61
+ subtitle: z.string().optional(),
62
+ badge: z.string().optional(),
63
+ imageSrc: z.string(),
64
+ effects: z
65
+ .array(
66
+ z.object({
67
+ type: z.enum(['vignette', 'grain', 'glow', 'warmth', 'soft-focus']),
68
+ intensity: z.number().min(0).max(1).optional(),
69
+ hue: z.string().optional(),
70
+ }),
71
+ )
72
+ .optional(),
73
+ accent: z.string().optional(),
74
+ secondaryAccent: z.string().optional(),
75
+ textColor: z.string().optional(),
76
+ }),
77
+ component: function DefaultEffectsPhotoScene({
78
+ id,
79
+ name,
80
+ sceneId,
81
+ sceneName,
82
+ title,
83
+ subtitle,
84
+ badge,
85
+ imageSrc,
86
+ effects,
87
+ accent,
88
+ secondaryAccent,
89
+ textColor,
90
+ }: DefaultEffectsPhotoSceneProps) {
91
+ const runtime = useRemotionSceneRuntime()
92
+ const sceneConfig = useSceneConfig()
93
+ const frame = useCurrentFrame()
94
+ const { fps } = useVideoConfig()
95
+ const portrait = runtime.height > runtime.width
96
+ const animated = sceneConfig.sceneType === 'animation'
97
+ const animationProgress =
98
+ sceneConfig.sceneType === 'animation'
99
+ ? spring({
100
+ frame,
101
+ fps,
102
+ config: { damping: 22, mass: 0.8, stiffness: 130 },
103
+ })
104
+ : 1
105
+ const reveal = sceneConfig.sceneType === 'animation' ? spring({ frame, fps, delay: 6, config: { damping: 20, mass: 0.7, stiffness: 150 } }) : 1
106
+ const focusDrift = sceneConfig.sceneType === 'animation' ? Math.sin((frame / fps) * Math.PI * 0.75) : 0
107
+ const scale = 1.01 + (1 - animationProgress) * 0.06 + focusDrift * 0.008
108
+ const translateX = (1 - animationProgress) * (portrait ? -8 : -12) + focusDrift * (portrait ? 8 : 12)
109
+ const translateY = (1 - animationProgress) * 10 + focusDrift * 16
110
+ const titleSize = Math.round(runtime.height * (portrait ? 0.034 : 0.04))
111
+ const subtitleSize = Math.round(runtime.height * 0.017)
112
+ const framePaddingX = Math.round(runtime.width * (portrait ? 0.015 : 0.014))
113
+ const framePaddingY = Math.round(runtime.height * (portrait ? 0.014 : 0.012))
114
+ const frameLeft = framePaddingX
115
+ const frameTop = framePaddingY
116
+ const frameWidth = Math.max(1, runtime.width - framePaddingX * 2)
117
+ const frameHeight = Math.max(1, runtime.height - framePaddingY * 2)
118
+ const imageFilter = animated ? 'brightness(1.08) contrast(1.04) saturate(1.08)' : 'brightness(1.9) contrast(1.18) saturate(1.22)'
119
+ const vignette = matchesEffect(effects, 'vignette')
120
+ const grain = matchesEffect(effects, 'grain')
121
+ const glow = matchesEffect(effects, 'glow')
122
+ const warmth = matchesEffect(effects, 'warmth')
123
+ const softFocus = matchesEffect(effects, 'soft-focus')
124
+ const vignetteOpacity = effectIntensity(effects, 'vignette', 0.52) * (0.65 + reveal * 0.35)
125
+ const glowOpacity = effectIntensity(effects, 'glow', 0.45) * (0.7 + reveal * 0.3)
126
+ const grainOpacity = effectIntensity(effects, 'grain', 0.12)
127
+ const warmthHue = effects?.find((effect) => effect.type === 'warmth')?.hue ?? accent ?? '#f97316'
128
+ const focusOverlay = interpolate(reveal, [0, 1], [0, 1], {
129
+ easing: Easing.inOut(Easing.quad),
130
+ extrapolateLeft: 'clamp',
131
+ extrapolateRight: 'clamp',
132
+ })
133
+
134
+ const effectLayers = useMemo(
135
+ () => (
136
+ <>
137
+ {glow ? (
138
+ <div
139
+ aria-hidden="true"
140
+ style={{
141
+ position: 'absolute',
142
+ inset: '4%',
143
+ opacity: glowOpacity * 0.55,
144
+ filter: 'blur(20px) saturate(1.18) brightness(0.98)',
145
+ transform: `scale(${1.03 + (1 - animationProgress) * 0.02})`,
146
+ pointerEvents: 'none',
147
+ }}
148
+ >
149
+ <Img
150
+ src={imageSrc}
151
+ alt={title ?? 'Effects photo'}
152
+ style={{
153
+ width: '100%',
154
+ height: '100%',
155
+ objectFit: 'cover',
156
+ }}
157
+ />
158
+ </div>
159
+ ) : null}
160
+ {softFocus ? (
161
+ <div
162
+ aria-hidden="true"
163
+ style={{
164
+ position: 'absolute',
165
+ inset: 0,
166
+ opacity: 0.18 + focusOverlay * 0.08,
167
+ filter: 'blur(10px) saturate(1.04)',
168
+ transform: `scale(${1.02 + focusOverlay * 0.01})`,
169
+ pointerEvents: 'none',
170
+ }}
171
+ >
172
+ <Img
173
+ src={imageSrc}
174
+ alt={title ?? 'Effects photo'}
175
+ style={{
176
+ width: '100%',
177
+ height: '100%',
178
+ objectFit: 'cover',
179
+ }}
180
+ />
181
+ </div>
182
+ ) : null}
183
+ {vignette ? (
184
+ <div
185
+ aria-hidden="true"
186
+ style={{
187
+ position: 'absolute',
188
+ inset: 0,
189
+ background:
190
+ 'radial-gradient(circle at center, rgba(255,255,255,0.04) 0%, rgba(255,255,255,0.01) 28%, rgba(2,6,23,0.14) 56%, rgba(2,6,23,0.46) 100%)',
191
+ opacity: vignetteOpacity * 0.72,
192
+ pointerEvents: 'none',
193
+ }}
194
+ />
195
+ ) : null}
196
+ {warmth ? (
197
+ <div
198
+ aria-hidden="true"
199
+ style={{
200
+ position: 'absolute',
201
+ inset: 0,
202
+ background: `linear-gradient(135deg, ${warmthHue} 0%, rgba(255,255,255,0.02) 36%, ${secondaryAccent ?? 'rgba(59,130,246,0.14)'} 100%)`,
203
+ mixBlendMode: 'screen',
204
+ opacity: 0.08 + focusOverlay * 0.08,
205
+ pointerEvents: 'none',
206
+ }}
207
+ />
208
+ ) : null}
209
+ {grain ? (
210
+ <div
211
+ aria-hidden="true"
212
+ style={{
213
+ position: 'absolute',
214
+ inset: 0,
215
+ opacity: grainOpacity,
216
+ backgroundImage:
217
+ 'radial-gradient(rgba(255,255,255,0.35) 0.7px, transparent 0.7px), radial-gradient(rgba(0,0,0,0.3) 0.7px, transparent 0.7px)',
218
+ backgroundSize: '4px 4px, 4px 4px',
219
+ backgroundPosition: '0 0, 2px 2px',
220
+ mixBlendMode: 'soft-light',
221
+ pointerEvents: 'none',
222
+ }}
223
+ />
224
+ ) : null}
225
+ </>
226
+ ),
227
+ [
228
+ animationProgress,
229
+ focusOverlay,
230
+ grain,
231
+ grainOpacity,
232
+ glow,
233
+ glowOpacity,
234
+ imageSrc,
235
+ secondaryAccent,
236
+ softFocus,
237
+ title,
238
+ vignette,
239
+ vignetteOpacity,
240
+ warmth,
241
+ warmthHue,
242
+ ],
243
+ )
244
+
245
+ return (
246
+ <BaseRemotionScene
247
+ id={id ?? sceneId}
248
+ name={name ?? sceneName ?? title}
249
+ style={{
250
+ background:
251
+ portrait
252
+ ? `linear-gradient(180deg, ${accent ?? '#020617'} 0%, #000000 100%)`
253
+ : `radial-gradient(circle at 50% 18%, ${secondaryAccent ?? 'rgba(255,255,255,0.08)'} 0%, ${accent ?? '#020617'} 52%, #000000 100%)`,
254
+ color: textColor ?? '#f8fafc',
255
+ padding: Math.round(runtime.height * (portrait ? 0.02 : 0.03)),
256
+ }}
257
+ >
258
+ <div
259
+ style={{
260
+ position: 'absolute',
261
+ inset: 0,
262
+ overflow: 'hidden',
263
+ border: '1px solid rgba(255,255,255,0.1)',
264
+ background: 'rgba(2,6,23,0.82)',
265
+ isolation: 'isolate',
266
+ }}
267
+ >
268
+ <div
269
+ style={{
270
+ position: 'absolute',
271
+ top: frameTop,
272
+ left: frameLeft,
273
+ width: frameWidth,
274
+ height: frameHeight,
275
+ border: animated ? '1px solid rgba(255,255,255,0.1)' : '1px solid rgba(255,255,255,0.16)',
276
+ boxShadow: animated ? '0 18px 56px rgba(0,0,0,0.24)' : '0 12px 32px rgba(0,0,0,0.14)',
277
+ backgroundColor: animated ? 'rgba(2,6,23,0.14)' : 'rgba(248,250,252,0.06)',
278
+ backgroundImage: `url(${imageSrc})`,
279
+ backgroundSize: 'cover',
280
+ backgroundPosition: `${50}% ${portrait ? 44 : 52}%`,
281
+ backgroundRepeat: 'no-repeat',
282
+ overflow: 'hidden',
283
+ filter: imageFilter,
284
+ }}
285
+ >
286
+ </div>
287
+
288
+ <div
289
+ style={{
290
+ position: 'absolute',
291
+ top: frameTop,
292
+ left: frameLeft,
293
+ width: frameWidth,
294
+ height: frameHeight,
295
+ }}
296
+ >
297
+ {effectLayers}
298
+ </div>
299
+
300
+ <div
301
+ aria-hidden="true"
302
+ style={{
303
+ position: 'absolute',
304
+ inset: 0,
305
+ background:
306
+ 'linear-gradient(180deg, rgba(2,6,23,0.04) 0%, rgba(2,6,23,0.12) 38%, rgba(2,6,23,0.52) 100%)',
307
+ pointerEvents: 'none',
308
+ }}
309
+ />
310
+
311
+ <div
312
+ style={{
313
+ position: 'absolute',
314
+ inset: 0,
315
+ display: 'grid',
316
+ alignContent: 'space-between',
317
+ padding: Math.round(runtime.height * (portrait ? 0.02 : 0.03)),
318
+ zIndex: 2,
319
+ pointerEvents: 'none',
320
+ }}
321
+ >
322
+ <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'start', gap: 12 }}>
323
+ <div
324
+ style={{
325
+ display: 'inline-flex',
326
+ alignItems: 'center',
327
+ gap: 8,
328
+ border: '1px solid rgba(255,255,255,0.18)',
329
+ background: 'rgba(2,6,23,0.6)',
330
+ color: '#f8fafc',
331
+ padding: '8px 12px',
332
+ letterSpacing: '0.22em',
333
+ textTransform: 'uppercase',
334
+ fontSize: 11,
335
+ lineHeight: 1,
336
+ }}
337
+ >
338
+ {badge ?? 'Effects Photo'}
339
+ </div>
340
+ </div>
341
+
342
+ <div style={{ display: 'grid', gap: 8, maxWidth: portrait ? '86%' : '58%' }}>
343
+ {title ? <div style={{ fontSize: titleSize, fontWeight: 800, letterSpacing: '-0.06em', lineHeight: 0.94 }}>{title}</div> : null}
344
+ {subtitle ? <div style={{ fontSize: subtitleSize, lineHeight: 1.45, opacity: 0.84 }}>{subtitle}</div> : null}
345
+ </div>
346
+ </div>
347
+ </div>
348
+ </BaseRemotionScene>
349
+ )
350
+ },
351
+ }),
352
+ )
@@ -0,0 +1,3 @@
1
+ export { DefaultEffectsPhotoScene, componentMetadata as DefaultEffectsPhotoSceneMetadata } from './default-effects-photo-scene'
2
+ export { DefaultEffectsPhotoSceneLandscape, componentMetadata as DefaultEffectsPhotoSceneLandscapeMetadata } from './default-effects-photo-scene-Landscape'
3
+ export { DefaultEffectsPhotoSceneHorizontal, componentMetadata as DefaultEffectsPhotoSceneHorizontalMetadata } from './default-effects-photo-scene-Horizontal'
@@ -0,0 +1,25 @@
1
+ export { DefaultLivePhotoScene, componentMetadata as DefaultLivePhotoSceneMetadata } from './default-live-photo-scene'
2
+ export { DefaultLivePhotoSceneLandscape, componentMetadata as DefaultLivePhotoSceneLandscapeMetadata } from './default-live-photo-scene-Landscape'
3
+ export { DefaultLivePhotoSceneHorizontal, componentMetadata as DefaultLivePhotoSceneHorizontalMetadata } from './default-live-photo-scene-Horizontal'
4
+ export { DefaultPhotoWallScene, componentMetadata as DefaultPhotoWallSceneMetadata } from './default-photo-wall-scene'
5
+ export { DefaultPhotoWallSceneLandscape, componentMetadata as DefaultPhotoWallSceneLandscapeMetadata } from './default-photo-wall-scene-Landscape'
6
+ export { DefaultPhotoWallSceneHorizontal, componentMetadata as DefaultPhotoWallSceneHorizontalMetadata } from './default-photo-wall-scene-Horizontal'
7
+ export { DefaultPhotoStripScene, componentMetadata as DefaultPhotoStripSceneMetadata } from './default-photo-strip-scene'
8
+ export { DefaultPhotoStripSceneLandscape, componentMetadata as DefaultPhotoStripSceneLandscapeMetadata } from './default-photo-strip-scene-Landscape'
9
+ export { DefaultPhotoStripSceneHorizontal, componentMetadata as DefaultPhotoStripSceneHorizontalMetadata } from './default-photo-strip-scene-Horizontal'
10
+ export {
11
+ DefaultEffectsPhotoScene,
12
+ DefaultEffectsPhotoSceneLandscape,
13
+ DefaultEffectsPhotoSceneHorizontal,
14
+ DefaultEffectsPhotoSceneMetadata,
15
+ DefaultEffectsPhotoSceneLandscapeMetadata,
16
+ DefaultEffectsPhotoSceneHorizontalMetadata,
17
+ } from './effects-photo'
18
+ export {
19
+ Default3DVRPhotoScene,
20
+ Default3DVRPhotoSceneLandscape,
21
+ Default3DVRPhotoSceneHorizontal,
22
+ Default3DVRPhotoSceneMetadata,
23
+ Default3DVRPhotoSceneLandscapeMetadata,
24
+ Default3DVRPhotoSceneHorizontalMetadata,
25
+ } from './3dvr-photo'
@@ -0,0 +1,112 @@
1
+ import { describe, expect, it, vi } from 'vitest'
2
+
3
+ vi.mock('remotion', async () => import('../../../storybook/remotion-preview'))
4
+
5
+ import { SceneViewport } from '../../../storybook/SceneViewport'
6
+ import { Default3DVRPhotoSceneLandscape } from './3dvr-photo/default-3dvr-photo-scene-Landscape'
7
+ import { DefaultEffectsPhotoSceneLandscape } from './effects-photo/default-effects-photo-scene-Landscape'
8
+
9
+ const photoUrl = 'https://heyaai-statics-1342239856.cos.ap-guangzhou.myqcloud.com/tmp/premium_photo-1779404552087-0f905162376f-121.jpeg'
10
+ const { renderToStaticMarkup } = require('/data/projects/foldspace-stack-apps/vibecuting/packages/@vibecuting/video-project-core/node_modules/.pnpm/react-dom@19.2.7_react@19.2.7/node_modules/react-dom/server')
11
+
12
+ describe('photo scene storybook rendering', () => {
13
+ it('renders 3dvr-photo in storybook preview', () => {
14
+ const html = renderToStaticMarkup(
15
+ <SceneViewport width={1280} height={720} aspectRatio="16:9" mode="static">
16
+ <Default3DVRPhotoSceneLandscape
17
+ title="Stereo Window"
18
+ subtitle="3D camera controls over a still frame with subtle orbit, pitch and depth."
19
+ badge="3D VR Photo"
20
+ imageSrc={photoUrl}
21
+ yaw={12}
22
+ pitch={4}
23
+ roll={0}
24
+ perspective={980}
25
+ zoom={1}
26
+ depth={26}
27
+ focusX={0.5}
28
+ focusY={0.45}
29
+ accent="#020617"
30
+ secondaryAccent="#1d4ed8"
31
+ />
32
+ </SceneViewport>,
33
+ )
34
+
35
+ expect(html).toContain('Stereo Window')
36
+ expect(html).toContain(photoUrl)
37
+ })
38
+
39
+ it('renders 3dvr-photo animation preview in storybook preview', () => {
40
+ const html = renderToStaticMarkup(
41
+ <SceneViewport width={1280} height={720} aspectRatio="16:9" mode="animation">
42
+ <Default3DVRPhotoSceneLandscape
43
+ title="Stereo Window"
44
+ subtitle="3D camera controls over a still frame with subtle orbit, pitch and depth."
45
+ badge="3D VR Photo"
46
+ imageSrc={photoUrl}
47
+ yaw={12}
48
+ pitch={4}
49
+ roll={0}
50
+ perspective={980}
51
+ zoom={1}
52
+ depth={26}
53
+ focusX={0.5}
54
+ focusY={0.45}
55
+ accent="#020617"
56
+ secondaryAccent="#1d4ed8"
57
+ />
58
+ </SceneViewport>,
59
+ )
60
+
61
+ expect(html).toContain('Stereo Window')
62
+ expect(html).toContain(photoUrl)
63
+ })
64
+
65
+ it('renders effects-photo in storybook preview', () => {
66
+ const html = renderToStaticMarkup(
67
+ <SceneViewport width={1280} height={720} aspectRatio="16:9" mode="static">
68
+ <DefaultEffectsPhotoSceneLandscape
69
+ title="Golden Echo"
70
+ subtitle="Layered photo grading with glow, grain, warmth and a cinematic vignette."
71
+ badge="Effects Photo"
72
+ imageSrc={photoUrl}
73
+ effects={[
74
+ { type: 'glow', intensity: 0.55 },
75
+ { type: 'vignette', intensity: 0.65 },
76
+ { type: 'grain', intensity: 0.12 },
77
+ { type: 'warmth', intensity: 0.18, hue: '#f59e0b' },
78
+ ]}
79
+ accent="#020617"
80
+ secondaryAccent="#1d4ed8"
81
+ />
82
+ </SceneViewport>,
83
+ )
84
+
85
+ expect(html).toContain('Golden Echo')
86
+ expect(html).toContain(photoUrl)
87
+ })
88
+
89
+ it('renders effects-photo animation preview in storybook preview', () => {
90
+ const html = renderToStaticMarkup(
91
+ <SceneViewport width={1280} height={720} aspectRatio="16:9" mode="animation">
92
+ <DefaultEffectsPhotoSceneLandscape
93
+ title="Golden Echo"
94
+ subtitle="Layered photo grading with glow, grain, warmth and a cinematic vignette."
95
+ badge="Effects Photo"
96
+ imageSrc={photoUrl}
97
+ effects={[
98
+ { type: 'glow', intensity: 0.55 },
99
+ { type: 'vignette', intensity: 0.65 },
100
+ { type: 'grain', intensity: 0.12 },
101
+ { type: 'warmth', intensity: 0.18, hue: '#f59e0b' },
102
+ ]}
103
+ accent="#020617"
104
+ secondaryAccent="#1d4ed8"
105
+ />
106
+ </SceneViewport>,
107
+ )
108
+
109
+ expect(html).toContain('Golden Echo')
110
+ expect(html).toContain(photoUrl)
111
+ })
112
+ })
@@ -4,3 +4,30 @@ export { getSlideTypographyScale } from './slide-typography'
4
4
  export type { SlideTypographyScale } from './slide-typography'
5
5
  export { getAdaptiveSlideGridLayout, getOverflowSafeSlideGridLayout } from './slide-grid'
6
6
  export type { SlideGridLayout, OverflowSafeSlideGridOptions } from './slide-grid'
7
+ export {
8
+ MediaTemplateSection,
9
+ clampTextLines,
10
+ columnRailStyle,
11
+ createTileStyle,
12
+ fitMediaStyle,
13
+ getPhotoGridLayout,
14
+ getProfileHeroLayout,
15
+ getVideoPosterRailLayout,
16
+ gridStyle,
17
+ renderMediaBadge,
18
+ renderMediaPlaceholder,
19
+ safeFullSizeStyle,
20
+ stackContentStyle,
21
+ } from './media-templates'
22
+ export type {
23
+ MediaTemplateRuntime,
24
+ MediaTileStyle,
25
+ PhotoGridLayout,
26
+ PhotoGridTemplateItem,
27
+ ProfileHeroLayout,
28
+ ProfileHeroStat,
29
+ ProfileHeroTemplateItem,
30
+ VideoPosterRailLayout,
31
+ VideoPosterRailItem,
32
+ MediaTemplateSectionProps,
33
+ } from './media-templates'
@@ -0,0 +1,47 @@
1
+ import { describe, expect, it } from 'vitest'
2
+
3
+ import {
4
+ getPhotoGridLayout,
5
+ getProfileHeroLayout,
6
+ getVideoPosterRailLayout,
7
+ } from './media-templates'
8
+
9
+ describe('media template layouts', () => {
10
+ it('keeps photo grids compact and inside portrait bounds', () => {
11
+ const layout = getPhotoGridLayout(5, { width: 1080, height: 1920 })
12
+
13
+ expect(layout).toMatchObject({
14
+ columns: 2,
15
+ rows: 3,
16
+ visibleItems: 5,
17
+ mediaAspectRatio: '4 / 3',
18
+ })
19
+ expect(layout.cardMinHeight).toBeGreaterThanOrEqual(120)
20
+ expect(layout.gap).toBeLessThanOrEqual(18)
21
+ })
22
+
23
+ it('switches poster rails to a stacked column in portrait scenes', () => {
24
+ const layout = getVideoPosterRailLayout(4, { width: 1080, height: 1920 })
25
+
26
+ expect(layout).toMatchObject({
27
+ railDirection: 'column',
28
+ columns: 1,
29
+ rows: 4,
30
+ visibleItems: 4,
31
+ posterAspectRatio: '9 / 16',
32
+ })
33
+ expect(layout.posterMinHeight).toBeGreaterThanOrEqual(128)
34
+ expect(layout.posterMinWidth).toBeGreaterThanOrEqual(220)
35
+ })
36
+
37
+ it('reserves enough room for profile hero content on landscape scenes', () => {
38
+ const layout = getProfileHeroLayout({ width: 1920, height: 1080 }, 3)
39
+
40
+ expect(layout).toMatchObject({
41
+ columns: 2,
42
+ statColumns: 3,
43
+ })
44
+ expect(layout.avatarSize).toBeGreaterThanOrEqual(120)
45
+ expect(layout.bodyMaxWidth).toBeLessThan(1920)
46
+ })
47
+ })