@vibecuting/video-project-core 0.1.26 → 0.1.27

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 (213) hide show
  1. package/package.json +4 -4
  2. package/src/core/intro/_shared/intro-layout.test.ts +18 -0
  3. package/src/core/intro/_shared/intro-layout.ts +50 -0
  4. package/src/core/intro/cyberpunk-intro-holo/default-cyberpunk-intro-bumper-Horizontal.tsx +25 -0
  5. package/src/core/intro/cyberpunk-intro-holo/default-cyberpunk-intro-bumper-Landscape.tsx +25 -0
  6. package/src/core/intro/cyberpunk-intro-holo/default-cyberpunk-intro-bumper.stories.tsx +31 -0
  7. package/src/core/intro/cyberpunk-intro-holo/default-cyberpunk-intro-bumper.tsx +118 -0
  8. package/src/core/intro/cyberpunk-intro-holo/index.ts +11 -0
  9. package/src/core/intro/cyberpunk-intro-neon/default-cyberpunk-intro-bumper-Horizontal.tsx +24 -0
  10. package/src/core/intro/cyberpunk-intro-neon/default-cyberpunk-intro-bumper-Landscape.tsx +24 -0
  11. package/src/core/intro/cyberpunk-intro-neon/default-cyberpunk-intro-bumper.stories.tsx +30 -0
  12. package/src/core/intro/cyberpunk-intro-neon/default-cyberpunk-intro-bumper.tsx +108 -0
  13. package/src/core/intro/cyberpunk-intro-neon/index.ts +10 -0
  14. package/src/core/intro/default-cinematic-intro-bumper/default-cinematic-intro-bumper-Horizontal.tsx +24 -0
  15. package/src/core/intro/default-cinematic-intro-bumper/default-cinematic-intro-bumper-Landscape.tsx +24 -0
  16. package/src/core/intro/default-cinematic-intro-bumper/default-cinematic-intro-bumper.stories.tsx +29 -0
  17. package/src/core/intro/default-cinematic-intro-bumper/default-cinematic-intro-bumper.tsx +234 -0
  18. package/src/core/intro/default-cinematic-intro-bumper/index.ts +11 -0
  19. package/src/core/intro/default-festival-intro-bumper/default-festival-intro-bumper-Horizontal.tsx +24 -0
  20. package/src/core/intro/default-festival-intro-bumper/default-festival-intro-bumper-Landscape.tsx +24 -0
  21. package/src/core/intro/default-festival-intro-bumper/default-festival-intro-bumper.stories.tsx +29 -0
  22. package/src/core/intro/default-festival-intro-bumper/default-festival-intro-bumper.tsx +187 -0
  23. package/src/core/intro/default-festival-intro-bumper/index.ts +11 -0
  24. package/src/core/intro/default-intro-bumper/default-intro-bumper-Horizontal.tsx +24 -0
  25. package/src/core/intro/default-intro-bumper/default-intro-bumper-Landscape.tsx +24 -0
  26. package/src/core/intro/default-intro-bumper/default-intro-bumper.stories.tsx +41 -0
  27. package/src/core/intro/default-intro-bumper/default-intro-bumper.tsx +256 -0
  28. package/src/core/intro/default-intro-bumper/index.ts +11 -0
  29. package/src/core/intro/default-noir-intro-bumper/default-noir-intro-bumper-Horizontal.tsx +24 -0
  30. package/src/core/intro/default-noir-intro-bumper/default-noir-intro-bumper-Landscape.tsx +24 -0
  31. package/src/core/intro/default-noir-intro-bumper/default-noir-intro-bumper.stories.tsx +29 -0
  32. package/src/core/intro/default-noir-intro-bumper/default-noir-intro-bumper.tsx +122 -0
  33. package/src/core/intro/default-noir-intro-bumper/index.ts +11 -0
  34. package/src/core/intro/default-trailer-intro-bumper/default-trailer-intro-bumper-Horizontal.tsx +24 -0
  35. package/src/core/intro/default-trailer-intro-bumper/default-trailer-intro-bumper-Landscape.tsx +24 -0
  36. package/src/core/intro/default-trailer-intro-bumper/default-trailer-intro-bumper.stories.tsx +29 -0
  37. package/src/core/intro/default-trailer-intro-bumper/default-trailer-intro-bumper.tsx +181 -0
  38. package/src/core/intro/default-trailer-intro-bumper/index.ts +11 -0
  39. package/src/core/intro/documentary-intro-observation/default-documentary-intro-bumper-Horizontal.tsx +18 -0
  40. package/src/core/intro/documentary-intro-observation/default-documentary-intro-bumper-Landscape.tsx +18 -0
  41. package/src/core/intro/documentary-intro-observation/default-documentary-intro-bumper.stories.tsx +31 -0
  42. package/src/core/intro/documentary-intro-observation/default-documentary-intro-bumper.tsx +158 -0
  43. package/src/core/intro/documentary-intro-observation/index.ts +10 -0
  44. package/src/core/intro/family-intro-reunion/default-family-intro-bumper-Horizontal.tsx +18 -0
  45. package/src/core/intro/family-intro-reunion/default-family-intro-bumper-Landscape.tsx +18 -0
  46. package/src/core/intro/family-intro-reunion/default-family-intro-bumper.stories.tsx +43 -0
  47. package/src/core/intro/family-intro-reunion/default-family-intro-bumper.tsx +165 -0
  48. package/src/core/intro/family-intro-reunion/index.ts +10 -0
  49. package/src/core/intro/festival-intro-spotlight/default-festival-intro-bumper-Horizontal.tsx +1 -0
  50. package/src/core/intro/festival-intro-spotlight/default-festival-intro-bumper-Landscape.tsx +1 -0
  51. package/src/core/intro/festival-intro-spotlight/default-festival-intro-bumper.stories.tsx +30 -0
  52. package/src/core/intro/festival-intro-spotlight/default-festival-intro-bumper.tsx +105 -0
  53. package/src/core/intro/festival-intro-spotlight/index.ts +10 -0
  54. package/src/core/intro/index.test.ts +45 -0
  55. package/src/core/intro/index.ts +17 -0
  56. package/src/core/intro/noir-intro-city/default-noir-intro-bumper-Horizontal.tsx +24 -0
  57. package/src/core/intro/noir-intro-city/default-noir-intro-bumper-Landscape.tsx +24 -0
  58. package/src/core/intro/noir-intro-city/default-noir-intro-bumper.stories.tsx +31 -0
  59. package/src/core/intro/noir-intro-city/default-noir-intro-bumper.tsx +96 -0
  60. package/src/core/intro/noir-intro-city/index.ts +10 -0
  61. package/src/core/intro/noir-intro-deluxe/default-noir-intro-bumper-Horizontal.tsx +1 -0
  62. package/src/core/intro/noir-intro-deluxe/default-noir-intro-bumper-Landscape.tsx +1 -0
  63. package/src/core/intro/noir-intro-deluxe/default-noir-intro-bumper.stories.tsx +31 -0
  64. package/src/core/intro/noir-intro-deluxe/default-noir-intro-bumper.tsx +117 -0
  65. package/src/core/intro/noir-intro-deluxe/index.ts +10 -0
  66. package/src/core/intro/sci-fi-intro/default-sci-fi-intro-bumper-Horizontal.tsx +1 -0
  67. package/src/core/intro/sci-fi-intro/default-sci-fi-intro-bumper-Landscape.tsx +1 -0
  68. package/src/core/intro/sci-fi-intro/default-sci-fi-intro-bumper.stories.tsx +48 -0
  69. package/src/core/intro/sci-fi-intro/default-sci-fi-intro-bumper.tsx +105 -0
  70. package/src/core/intro/sci-fi-intro/index.ts +10 -0
  71. package/src/core/intro/thriller-intro-suspense/default-thriller-intro-bumper-Horizontal.tsx +18 -0
  72. package/src/core/intro/thriller-intro-suspense/default-thriller-intro-bumper-Landscape.tsx +18 -0
  73. package/src/core/intro/thriller-intro-suspense/default-thriller-intro-bumper.stories.tsx +31 -0
  74. package/src/core/intro/thriller-intro-suspense/default-thriller-intro-bumper.tsx +155 -0
  75. package/src/core/intro/thriller-intro-suspense/index.ts +10 -0
  76. package/src/core/intro/trailer-intro-premiere/default-trailer-intro-bumper-Horizontal.tsx +1 -0
  77. package/src/core/intro/trailer-intro-premiere/default-trailer-intro-bumper-Landscape.tsx +1 -0
  78. package/src/core/intro/trailer-intro-premiere/default-trailer-intro-bumper.stories.tsx +30 -0
  79. package/src/core/intro/trailer-intro-premiere/default-trailer-intro-bumper.tsx +104 -0
  80. package/src/core/intro/trailer-intro-premiere/index.ts +10 -0
  81. package/src/core/intro/travel-intro-journey/default-travel-intro-bumper-Horizontal.tsx +18 -0
  82. package/src/core/intro/travel-intro-journey/default-travel-intro-bumper-Landscape.tsx +18 -0
  83. package/src/core/intro/travel-intro-journey/default-travel-intro-bumper.stories.tsx +43 -0
  84. package/src/core/intro/travel-intro-journey/default-travel-intro-bumper.tsx +158 -0
  85. package/src/core/intro/travel-intro-journey/index.ts +10 -0
  86. package/src/core/intro/western-intro/default-western-intro-bumper-Horizontal.tsx +24 -0
  87. package/src/core/intro/western-intro/default-western-intro-bumper-Landscape.tsx +24 -0
  88. package/src/core/intro/western-intro/default-western-intro-bumper.stories.tsx +29 -0
  89. package/src/core/intro/western-intro/default-western-intro-bumper.tsx +146 -0
  90. package/src/core/intro/western-intro/index.ts +4 -0
  91. package/src/core/intro/western-intro-gangster/default-western-intro-bumper-Horizontal.tsx +25 -0
  92. package/src/core/intro/western-intro-gangster/default-western-intro-bumper-Landscape.tsx +25 -0
  93. package/src/core/intro/western-intro-gangster/default-western-intro-bumper.stories.tsx +31 -0
  94. package/src/core/intro/western-intro-gangster/default-western-intro-bumper.tsx +105 -0
  95. package/src/core/intro/western-intro-gangster/index.ts +11 -0
  96. package/src/core/outro/_shared/outro-layout.test.ts +32 -0
  97. package/src/core/outro/_shared/outro-layout.ts +72 -0
  98. package/src/core/outro/award-outro-celebration/default-award-outro-bumper-Horizontal.tsx +18 -0
  99. package/src/core/outro/award-outro-celebration/default-award-outro-bumper-Landscape.tsx +18 -0
  100. package/src/core/outro/award-outro-celebration/default-award-outro-bumper.stories.tsx +42 -0
  101. package/src/core/outro/award-outro-celebration/default-award-outro-bumper.tsx +152 -0
  102. package/src/core/outro/award-outro-celebration/index.ts +10 -0
  103. package/src/core/outro/blackout-outro-finale/default-blackout-outro-bumper-Horizontal.tsx +1 -0
  104. package/src/core/outro/blackout-outro-finale/default-blackout-outro-bumper-Landscape.tsx +1 -0
  105. package/src/core/outro/blackout-outro-finale/default-blackout-outro-bumper.stories.tsx +28 -0
  106. package/src/core/outro/blackout-outro-finale/default-blackout-outro-bumper.tsx +71 -0
  107. package/src/core/outro/blackout-outro-finale/index.ts +10 -0
  108. package/src/core/outro/credits-roll-outro-epic/default-credits-roll-outro-Horizontal.tsx +24 -0
  109. package/src/core/outro/credits-roll-outro-epic/default-credits-roll-outro-Landscape.tsx +24 -0
  110. package/src/core/outro/credits-roll-outro-epic/default-credits-roll-outro.stories.tsx +31 -0
  111. package/src/core/outro/credits-roll-outro-epic/default-credits-roll-outro.tsx +106 -0
  112. package/src/core/outro/credits-roll-outro-epic/index.ts +10 -0
  113. package/src/core/outro/credits-roll-outro-premium/default-credits-roll-outro-Horizontal.tsx +1 -0
  114. package/src/core/outro/credits-roll-outro-premium/default-credits-roll-outro-Landscape.tsx +1 -0
  115. package/src/core/outro/credits-roll-outro-premium/default-credits-roll-outro.stories.tsx +30 -0
  116. package/src/core/outro/credits-roll-outro-premium/default-credits-roll-outro.tsx +88 -0
  117. package/src/core/outro/credits-roll-outro-premium/index.ts +10 -0
  118. package/src/core/outro/credits-roll-outro-royal/default-credits-roll-outro-Horizontal.tsx +25 -0
  119. package/src/core/outro/credits-roll-outro-royal/default-credits-roll-outro-Landscape.tsx +25 -0
  120. package/src/core/outro/credits-roll-outro-royal/default-credits-roll-outro.stories.tsx +32 -0
  121. package/src/core/outro/credits-roll-outro-royal/default-credits-roll-outro.tsx +110 -0
  122. package/src/core/outro/credits-roll-outro-royal/index.ts +11 -0
  123. package/src/core/outro/default-blackout-outro-bumper/default-blackout-outro-bumper-Horizontal.tsx +22 -0
  124. package/src/core/outro/default-blackout-outro-bumper/default-blackout-outro-bumper-Landscape.tsx +22 -0
  125. package/src/core/outro/default-blackout-outro-bumper/default-blackout-outro-bumper.stories.tsx +48 -0
  126. package/src/core/outro/default-blackout-outro-bumper/default-blackout-outro-bumper.tsx +124 -0
  127. package/src/core/outro/default-blackout-outro-bumper/index.ts +11 -0
  128. package/src/core/outro/default-credits-roll-outro/default-credits-roll-outro-Horizontal.tsx +22 -0
  129. package/src/core/outro/default-credits-roll-outro/default-credits-roll-outro-Landscape.tsx +22 -0
  130. package/src/core/outro/default-credits-roll-outro/default-credits-roll-outro.stories.tsx +48 -0
  131. package/src/core/outro/default-credits-roll-outro/default-credits-roll-outro.tsx +208 -0
  132. package/src/core/outro/default-credits-roll-outro/index.ts +11 -0
  133. package/src/core/outro/default-epilogue-outro/default-epilogue-outro-Horizontal.tsx +22 -0
  134. package/src/core/outro/default-epilogue-outro/default-epilogue-outro-Landscape.tsx +22 -0
  135. package/src/core/outro/default-epilogue-outro/default-epilogue-outro.stories.tsx +48 -0
  136. package/src/core/outro/default-epilogue-outro/default-epilogue-outro.tsx +115 -0
  137. package/src/core/outro/default-epilogue-outro/index.ts +11 -0
  138. package/src/core/outro/default-outro-bumper/default-outro-bumper-Horizontal.tsx +22 -0
  139. package/src/core/outro/default-outro-bumper/default-outro-bumper-Landscape.tsx +22 -0
  140. package/src/core/outro/default-outro-bumper/default-outro-bumper.stories.tsx +48 -0
  141. package/src/core/outro/default-outro-bumper/default-outro-bumper.tsx +159 -0
  142. package/src/core/outro/default-outro-bumper/index.ts +11 -0
  143. package/src/core/outro/default-sunset-outro-bumper/default-sunset-outro-bumper-Horizontal.tsx +22 -0
  144. package/src/core/outro/default-sunset-outro-bumper/default-sunset-outro-bumper-Landscape.tsx +22 -0
  145. package/src/core/outro/default-sunset-outro-bumper/default-sunset-outro-bumper.stories.tsx +48 -0
  146. package/src/core/outro/default-sunset-outro-bumper/default-sunset-outro-bumper.tsx +183 -0
  147. package/src/core/outro/default-sunset-outro-bumper/index.ts +11 -0
  148. package/src/core/outro/festival-outro-encore/default-festival-outro-bumper-Horizontal.tsx +18 -0
  149. package/src/core/outro/festival-outro-encore/default-festival-outro-bumper-Landscape.tsx +18 -0
  150. package/src/core/outro/festival-outro-encore/default-festival-outro-bumper.stories.tsx +31 -0
  151. package/src/core/outro/festival-outro-encore/default-festival-outro-bumper.tsx +130 -0
  152. package/src/core/outro/festival-outro-encore/index.ts +10 -0
  153. package/src/core/outro/heist-outro/default-heist-outro-bumper-Horizontal.tsx +24 -0
  154. package/src/core/outro/heist-outro/default-heist-outro-bumper-Landscape.tsx +24 -0
  155. package/src/core/outro/heist-outro/default-heist-outro-bumper.stories.tsx +29 -0
  156. package/src/core/outro/heist-outro/default-heist-outro-bumper.tsx +160 -0
  157. package/src/core/outro/heist-outro/index.ts +4 -0
  158. package/src/core/outro/index.test.ts +88 -0
  159. package/src/core/outro/index.ts +73 -0
  160. package/src/core/outro/memoir-outro-reflection/default-memoir-outro-bumper-Horizontal.tsx +18 -0
  161. package/src/core/outro/memoir-outro-reflection/default-memoir-outro-bumper-Landscape.tsx +18 -0
  162. package/src/core/outro/memoir-outro-reflection/default-memoir-outro-bumper.stories.tsx +42 -0
  163. package/src/core/outro/memoir-outro-reflection/default-memoir-outro-bumper.tsx +158 -0
  164. package/src/core/outro/memoir-outro-reflection/index.ts +10 -0
  165. package/src/core/outro/romance-outro/default-romance-outro-bumper-Horizontal.tsx +1 -0
  166. package/src/core/outro/romance-outro/default-romance-outro-bumper-Landscape.tsx +1 -0
  167. package/src/core/outro/romance-outro/default-romance-outro-bumper.stories.tsx +48 -0
  168. package/src/core/outro/romance-outro/default-romance-outro-bumper.tsx +123 -0
  169. package/src/core/outro/romance-outro/index.ts +10 -0
  170. package/src/core/outro/sunset-outro-coda/default-sunset-outro-bumper-Horizontal.tsx +1 -0
  171. package/src/core/outro/sunset-outro-coda/default-sunset-outro-bumper-Landscape.tsx +1 -0
  172. package/src/core/outro/sunset-outro-coda/default-sunset-outro-bumper.stories.tsx +30 -0
  173. package/src/core/outro/sunset-outro-coda/default-sunset-outro-bumper.tsx +75 -0
  174. package/src/core/outro/sunset-outro-coda/index.ts +10 -0
  175. package/src/core/scene/slide/_shared/index.ts +27 -0
  176. package/src/core/scene/slide/_shared/media-templates.test.ts +47 -0
  177. package/src/core/scene/slide/_shared/media-templates.tsx +324 -0
  178. package/src/core/scene/slide/index.test.ts +28 -0
  179. package/src/core/scene/slide/index.ts +14 -0
  180. package/src/core/scene/slide/person-intro/default-person-intro-duo-slide.tsx +19 -0
  181. package/src/core/scene/slide/person-intro/default-person-intro-group-slide.tsx +168 -0
  182. package/src/core/scene/slide/person-intro/default-person-intro-quad-slide.tsx +19 -0
  183. package/src/core/scene/slide/person-intro/default-person-intro-slide-Horizontal.animated.stories.tsx +47 -0
  184. package/src/core/scene/slide/person-intro/default-person-intro-slide-Horizontal.stories.tsx +46 -0
  185. package/src/core/scene/slide/person-intro/default-person-intro-slide-Horizontal.tsx +302 -0
  186. package/src/core/scene/slide/person-intro/default-person-intro-slide-Landscape.tsx +20 -0
  187. package/src/core/scene/slide/person-intro/default-person-intro-slide.animated.stories.tsx +126 -0
  188. package/src/core/scene/slide/person-intro/default-person-intro-slide.stories.tsx +119 -0
  189. package/src/core/scene/slide/person-intro/default-person-intro-slide.tsx +363 -0
  190. package/src/core/scene/slide/person-intro/default-person-intro-trio-slide.tsx +19 -0
  191. package/src/core/scene/slide/person-intro/index.ts +8 -0
  192. package/src/core/scene/slide/photo-album/default-photo-album-multi-slide.tsx +19 -0
  193. package/src/core/scene/slide/photo-album/default-photo-album-pair-slide.tsx +19 -0
  194. package/src/core/scene/slide/photo-album/default-photo-album-single-slide.tsx +19 -0
  195. package/src/core/scene/slide/photo-album/default-photo-album-slide-Horizontal.animated.stories.tsx +26 -0
  196. package/src/core/scene/slide/photo-album/default-photo-album-slide-Horizontal.stories.tsx +25 -0
  197. package/src/core/scene/slide/photo-album/default-photo-album-slide-Horizontal.tsx +20 -0
  198. package/src/core/scene/slide/photo-album/default-photo-album-slide-Landscape.tsx +20 -0
  199. package/src/core/scene/slide/photo-album/default-photo-album-slide.animated.stories.tsx +94 -0
  200. package/src/core/scene/slide/photo-album/default-photo-album-slide.stories.tsx +87 -0
  201. package/src/core/scene/slide/photo-album/default-photo-album-slide.tsx +414 -0
  202. package/src/core/scene/slide/photo-album/index.ts +7 -0
  203. package/src/core/scene/slide/video-showcase/default-video-showcase-multi-slide.tsx +195 -0
  204. package/src/core/scene/slide/video-showcase/default-video-showcase-slide-Horizontal.tsx +212 -0
  205. package/src/core/scene/slide/video-showcase/default-video-showcase-slide-Landscape.tsx +20 -0
  206. package/src/core/scene/slide/video-showcase/default-video-showcase-slide.animated.stories.tsx +78 -0
  207. package/src/core/scene/slide/video-showcase/default-video-showcase-slide.stories.tsx +74 -0
  208. package/src/core/scene/slide/video-showcase/default-video-showcase-slide.tsx +365 -0
  209. package/src/core/scene/slide/video-showcase/index.ts +5 -0
  210. package/src/core/intro/default-intro-bumper.stories.tsx +0 -19
  211. package/src/core/intro/default-intro-bumper.tsx +0 -218
  212. package/src/core/outro/default-outro-bumper.stories.tsx +0 -19
  213. package/src/core/outro/default-outro-bumper.tsx +0 -218
@@ -0,0 +1,363 @@
1
+ import type { ReactNode } from 'react'
2
+
3
+ import { z } from 'zod'
4
+
5
+ import { VideoComponent, defineScenePluginMetadata } from '@vibecuting/component-project-helper'
6
+
7
+ import { defineSceneComponent } from '../../../../plugins/scene-component'
8
+ import { SceneMotionLayer, useRemotionSceneRuntime } from '../../../../base'
9
+ import type { DefaultSceneProps } from '../../../../scenes/default-scene-props'
10
+ import { SlideFrame, getOverflowSafeSlideGridLayout, getSlideTypographyScale } from '../_shared'
11
+
12
+ export type PersonIntroLink = {
13
+ label: string
14
+ href?: string
15
+ meta?: string
16
+ }
17
+
18
+ export type PersonIntroHighlight = {
19
+ label: string
20
+ value?: string
21
+ detail?: string
22
+ }
23
+
24
+ export interface DefaultPersonIntroSlideProps extends DefaultSceneProps {
25
+ name: string
26
+ role?: string
27
+ bio?: string
28
+ avatar?: ReactNode
29
+ links?: PersonIntroLink[]
30
+ highlights?: PersonIntroHighlight[]
31
+ }
32
+
33
+ export const personIntroPropsSchema = z.object({
34
+ sceneId: z.string().optional(),
35
+ sceneName: z.string().optional(),
36
+ name: z.string().min(1),
37
+ role: z.string().optional(),
38
+ bio: z.string().optional(),
39
+ avatar: z.any().optional(),
40
+ links: z
41
+ .array(
42
+ z.object({
43
+ label: z.string().min(1),
44
+ href: z.string().optional(),
45
+ meta: z.string().optional(),
46
+ }),
47
+ )
48
+ .optional(),
49
+ highlights: z
50
+ .array(
51
+ z.object({
52
+ label: z.string().min(1),
53
+ value: z.string().optional(),
54
+ detail: z.string().optional(),
55
+ }),
56
+ )
57
+ .optional(),
58
+ })
59
+
60
+ export const componentMetadata = defineScenePluginMetadata({
61
+ resourceKind: 'scene',
62
+ name: 'DefaultPersonIntroSlide',
63
+ description: 'Profile-first person introduction slide',
64
+ sourceFile: 'src/core/scene/slide/person-intro/default-person-intro-slide.tsx',
65
+ pluginKey: 'core.slide.person-intro',
66
+ tags: ['scene', 'slide', 'person', 'profile', 'intro'],
67
+ aspectRatio: '16:9',
68
+ sceneType: 'scene',
69
+ sceneFamily: 'slide',
70
+ rootLayout: 'absolute-fill',
71
+ propsTypeName: 'DefaultPersonIntroSlideProps',
72
+ })
73
+
74
+ function buildInitials(name: string) {
75
+ const initials = name
76
+ .split(/\s+/)
77
+ .filter(Boolean)
78
+ .slice(0, 2)
79
+ .map((part) => part[0] ?? '')
80
+ .join('')
81
+ .toUpperCase()
82
+
83
+ return initials || 'P'
84
+ }
85
+
86
+ function PersonIntroAvatarFallback({ name }: { name: string }) {
87
+ const initials = buildInitials(name)
88
+ return (
89
+ <div
90
+ style={{
91
+ width: '100%',
92
+ height: '100%',
93
+ display: 'grid',
94
+ placeItems: 'center',
95
+ background: 'linear-gradient(135deg, rgba(59,130,246,0.32), rgba(14,165,233,0.12))',
96
+ color: '#f8fafc',
97
+ fontSize: 'clamp(32px, 3.4vw, 58px)',
98
+ fontWeight: 800,
99
+ letterSpacing: '-0.06em',
100
+ }}
101
+ >
102
+ {initials}
103
+ </div>
104
+ )
105
+ }
106
+
107
+ function PersonIntroLinkChip({ link }: { link: PersonIntroLink }) {
108
+ const content = (
109
+ <div
110
+ style={{
111
+ width: '100%',
112
+ minWidth: 0,
113
+ padding: '12px 14px',
114
+ display: 'grid',
115
+ gap: 4,
116
+ border: '1px solid rgba(148,163,184,0.18)',
117
+ background: 'rgba(15,23,42,0.6)',
118
+ color: '#e2e8f0',
119
+ overflow: 'hidden',
120
+ }}
121
+ >
122
+ <div style={{ fontSize: 13, fontWeight: 700, lineHeight: 1.2, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{link.label}</div>
123
+ {link.meta ? (
124
+ <div style={{ fontSize: 11, lineHeight: 1.2, letterSpacing: '0.04em', textTransform: 'uppercase', color: 'rgba(148,163,184,0.92)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
125
+ {link.meta}
126
+ </div>
127
+ ) : null}
128
+ </div>
129
+ )
130
+
131
+ if (!link.href) {
132
+ return content
133
+ }
134
+
135
+ return (
136
+ <a href={link.href} target="_blank" rel="noreferrer noopener" style={{ display: 'block', textDecoration: 'none', minWidth: 0 }}>
137
+ {content}
138
+ </a>
139
+ )
140
+ }
141
+
142
+ function PersonIntroHighlightCard({ highlight }: { highlight: PersonIntroHighlight }) {
143
+ return (
144
+ <article
145
+ style={{
146
+ minHeight: 0,
147
+ padding: '16px',
148
+ display: 'grid',
149
+ gap: 8,
150
+ background: 'rgba(15,23,42,0.68)',
151
+ border: '1px solid rgba(148,163,184,0.16)',
152
+ color: '#e2e8f0',
153
+ overflow: 'hidden',
154
+ }}
155
+ >
156
+ <div style={{ fontSize: 12, letterSpacing: '0.18em', textTransform: 'uppercase', color: 'rgba(148,163,184,0.9)' }}>{highlight.label}</div>
157
+ {highlight.value ? <div style={{ fontSize: 'clamp(20px, 2.2vw, 34px)', fontWeight: 800, lineHeight: 1.05, letterSpacing: '-0.05em' }}>{highlight.value}</div> : null}
158
+ {highlight.detail ? (
159
+ <div
160
+ style={{
161
+ fontSize: 14,
162
+ lineHeight: 1.45,
163
+ color: 'rgba(226,232,240,0.78)',
164
+ display: '-webkit-box',
165
+ WebkitBoxOrient: 'vertical',
166
+ WebkitLineClamp: 3,
167
+ overflow: 'hidden',
168
+ }}
169
+ >
170
+ {highlight.detail}
171
+ </div>
172
+ ) : null}
173
+ </article>
174
+ )
175
+ }
176
+
177
+ export const DefaultPersonIntroSlide = VideoComponent(componentMetadata)(
178
+ defineSceneComponent({
179
+ family: 'slide',
180
+ propsSchema: personIntroPropsSchema,
181
+ component: function DefaultPersonIntroSlide({
182
+ sceneId,
183
+ sceneName,
184
+ name,
185
+ role,
186
+ bio,
187
+ avatar,
188
+ links = [],
189
+ highlights = [],
190
+ }: DefaultPersonIntroSlideProps) {
191
+ const runtime = useRemotionSceneRuntime()
192
+ const isPortrait = runtime.height > runtime.width
193
+ const scale = getSlideTypographyScale(runtime.height)
194
+ const linkGrid = getOverflowSafeSlideGridLayout(links.length || 1, isPortrait ? 2 : 3, {
195
+ runtimeWidth: runtime.width,
196
+ reservedWidth: isPortrait ? 48 : 160,
197
+ runtimeHeight: runtime.height,
198
+ reservedHeight: isPortrait ? 460 : 240,
199
+ minCardWidth: isPortrait ? 132 : 148,
200
+ minCardHeight: 48,
201
+ })
202
+ const highlightGrid = getOverflowSafeSlideGridLayout(highlights.length || 1, isPortrait ? 2 : 3, {
203
+ runtimeWidth: runtime.width,
204
+ reservedWidth: isPortrait ? 48 : 160,
205
+ runtimeHeight: runtime.height,
206
+ reservedHeight: isPortrait ? 420 : 260,
207
+ minCardWidth: isPortrait ? 180 : 220,
208
+ minCardHeight: isPortrait ? 104 : 128,
209
+ })
210
+ const avatarSize = isPortrait ? Math.max(120, Math.round(runtime.width * 0.26)) : Math.max(180, Math.round(runtime.height * 0.24))
211
+
212
+ return (
213
+ <SlideFrame
214
+ pluginKey={componentMetadata.pluginKey}
215
+ sceneId={sceneId}
216
+ sceneName={sceneName ?? name}
217
+ background="linear-gradient(135deg, #020617 0%, #0f172a 48%, #1e293b 100%)"
218
+ >
219
+ <section
220
+ style={{
221
+ width: '100%',
222
+ height: '100%',
223
+ display: 'grid',
224
+ gridTemplateColumns: isPortrait ? '1fr' : 'minmax(330px, 0.95fr) minmax(0, 1.05fr)',
225
+ gap: isPortrait ? 18 : 28,
226
+ padding: isPortrait ? '40px 24px' : '64px 80px',
227
+ color: '#e2e8f0',
228
+ }}
229
+ >
230
+ <SceneMotionLayer variant="panel">
231
+ <article
232
+ style={{
233
+ minWidth: 0,
234
+ height: '100%',
235
+ padding: isPortrait ? '18px' : '24px',
236
+ display: 'flex',
237
+ flexDirection: 'column',
238
+ gap: isPortrait ? 18 : 22,
239
+ background: 'rgba(15,23,42,0.58)',
240
+ border: '1px solid rgba(148,163,184,0.18)',
241
+ overflow: 'hidden',
242
+ }}
243
+ >
244
+ <div
245
+ style={{
246
+ display: 'grid',
247
+ gridTemplateColumns: isPortrait ? 'auto 1fr' : 'auto 1fr',
248
+ gap: isPortrait ? 16 : 20,
249
+ alignItems: 'center',
250
+ minWidth: 0,
251
+ }}
252
+ >
253
+ <div
254
+ style={{
255
+ width: avatarSize,
256
+ height: avatarSize,
257
+ overflow: 'hidden',
258
+ borderRadius: 0,
259
+ background: 'rgba(15,23,42,0.92)',
260
+ border: '1px solid rgba(148,163,184,0.24)',
261
+ }}
262
+ >
263
+ {avatar ?? <PersonIntroAvatarFallback name={name} />}
264
+ </div>
265
+
266
+ <div style={{ minWidth: 0, display: 'grid', gap: 8 }}>
267
+ <div style={{ fontSize: scale.eyebrow, letterSpacing: '0.18em', textTransform: 'uppercase', color: 'rgba(148,163,184,0.9)' }}>Profile</div>
268
+ <h1 style={{ margin: 0, fontSize: isPortrait ? Math.max(scale.title * 0.82, 36) : scale.title, lineHeight: 0.94, letterSpacing: '-0.06em' }}>
269
+ {name}
270
+ </h1>
271
+ {role ? (
272
+ <div
273
+ style={{
274
+ fontSize: isPortrait ? scale.body * 0.92 : scale.body,
275
+ lineHeight: 1.35,
276
+ color: 'rgba(226,232,240,0.86)',
277
+ display: '-webkit-box',
278
+ WebkitBoxOrient: 'vertical',
279
+ WebkitLineClamp: 2,
280
+ overflow: 'hidden',
281
+ }}
282
+ >
283
+ {role}
284
+ </div>
285
+ ) : null}
286
+ </div>
287
+ </div>
288
+
289
+ {bio ? (
290
+ <div
291
+ style={{
292
+ fontSize: isPortrait ? scale.body * 0.88 : scale.body,
293
+ lineHeight: 1.52,
294
+ color: 'rgba(226,232,240,0.78)',
295
+ display: '-webkit-box',
296
+ WebkitBoxOrient: 'vertical',
297
+ WebkitLineClamp: isPortrait ? 4 : 5,
298
+ overflow: 'hidden',
299
+ }}
300
+ >
301
+ {bio}
302
+ </div>
303
+ ) : null}
304
+
305
+ {links.length ? (
306
+ <div style={{ display: 'grid', gap: 10 }}>
307
+ <div style={{ fontSize: scale.eyebrow, letterSpacing: '0.16em', textTransform: 'uppercase', color: 'rgba(148,163,184,0.84)' }}>Links</div>
308
+ <div
309
+ style={{
310
+ display: 'grid',
311
+ gridTemplateColumns: `repeat(${Math.max(1, linkGrid.columns)}, minmax(0, 1fr))`,
312
+ gap: linkGrid.gap,
313
+ }}
314
+ >
315
+ {links.slice(0, 5).map((link) => (
316
+ <PersonIntroLinkChip key={`${link.label}-${link.href ?? link.meta ?? ''}`} link={link} />
317
+ ))}
318
+ </div>
319
+ </div>
320
+ ) : null}
321
+ </article>
322
+ </SceneMotionLayer>
323
+
324
+ <div style={{ display: 'grid', alignContent: 'start', gap: isPortrait ? 16 : 20, minWidth: 0 }}>
325
+ <SceneMotionLayer variant="hero-copy" delayIndex={1}>
326
+ <article
327
+ style={{
328
+ minWidth: 0,
329
+ padding: isPortrait ? '18px' : '24px',
330
+ display: 'grid',
331
+ gap: 14,
332
+ background: 'rgba(2,6,23,0.52)',
333
+ border: '1px solid rgba(148,163,184,0.16)',
334
+ overflow: 'hidden',
335
+ }}
336
+ >
337
+ <div style={{ display: 'flex', alignItems: 'baseline', justifyContent: 'space-between', gap: 12 }}>
338
+ <div style={{ fontSize: scale.eyebrow, letterSpacing: '0.18em', textTransform: 'uppercase', color: 'rgba(148,163,184,0.9)' }}>Highlights</div>
339
+ <div style={{ fontSize: scale.caption, color: 'rgba(148,163,184,0.72)' }}>{Math.min(highlights.length, 5)} items</div>
340
+ </div>
341
+
342
+ <div
343
+ style={{
344
+ display: 'grid',
345
+ gridTemplateColumns: `repeat(${Math.max(1, highlightGrid.columns)}, minmax(0, 1fr))`,
346
+ gap: highlightGrid.gap,
347
+ }}
348
+ >
349
+ {(highlights.length ? highlights : [{ label: 'Focus', value: 'Profile-first', detail: 'Introduce the person with clear identity, context, and proof points.' }]).slice(0, 5).map((highlight, index) => (
350
+ <SceneMotionLayer key={`${highlight.label}-${index}`} variant="card" delayIndex={index + 2}>
351
+ <PersonIntroHighlightCard highlight={highlight} />
352
+ </SceneMotionLayer>
353
+ ))}
354
+ </div>
355
+ </article>
356
+ </SceneMotionLayer>
357
+ </div>
358
+ </section>
359
+ </SlideFrame>
360
+ )
361
+ },
362
+ }),
363
+ )
@@ -0,0 +1,19 @@
1
+ import type { ComponentProps } from 'react'
2
+
3
+ import { VideoComponent, type ScenePluginMetadata } from '@vibecuting/component-project-helper'
4
+
5
+ import { DefaultPersonIntroGroupSlide, componentMetadata as baseComponentMetadata } from './default-person-intro-group-slide'
6
+
7
+ export const componentMetadata: ScenePluginMetadata = {
8
+ ...baseComponentMetadata,
9
+ name: 'DefaultPersonIntroTrioSlide',
10
+ description: 'Three person intro slide',
11
+ sourceFile: 'src/core/scene/slide/person-intro/default-person-intro-trio-slide.tsx',
12
+ tags: Array.from(new Set([...(baseComponentMetadata.tags ?? []), 'trio', 'three-person'])),
13
+ }
14
+
15
+ export const DefaultPersonIntroTrioSlide = VideoComponent(componentMetadata)(function DefaultPersonIntroTrioSlide(
16
+ props: ComponentProps<typeof DefaultPersonIntroGroupSlide>,
17
+ ) {
18
+ return <DefaultPersonIntroGroupSlide {...props} />
19
+ })
@@ -0,0 +1,8 @@
1
+ export { DefaultPersonIntroSlide } from './default-person-intro-slide'
2
+ export { componentMetadata } from './default-person-intro-slide'
3
+ export { DefaultPersonIntroSlideLandscape, componentMetadata as DefaultPersonIntroSlideLandscapeMetadata } from './default-person-intro-slide-Landscape'
4
+ export { DefaultPersonIntroSlideHorizontal, componentMetadata as DefaultPersonIntroSlideHorizontalMetadata } from './default-person-intro-slide-Horizontal'
5
+ export { DefaultPersonIntroGroupSlide, componentMetadata as DefaultPersonIntroGroupSlideMetadata } from './default-person-intro-group-slide'
6
+ export { DefaultPersonIntroDuoSlide, componentMetadata as DefaultPersonIntroDuoSlideMetadata } from './default-person-intro-duo-slide'
7
+ export { DefaultPersonIntroTrioSlide, componentMetadata as DefaultPersonIntroTrioSlideMetadata } from './default-person-intro-trio-slide'
8
+ export { DefaultPersonIntroQuadSlide, componentMetadata as DefaultPersonIntroQuadSlideMetadata } from './default-person-intro-quad-slide'
@@ -0,0 +1,19 @@
1
+ import type { ComponentProps } from 'react'
2
+
3
+ import { VideoComponent, type ScenePluginMetadata } from '@vibecuting/component-project-helper'
4
+
5
+ import { DefaultPhotoAlbumSlide, componentMetadata as baseComponentMetadata } from './default-photo-album-slide'
6
+
7
+ export const componentMetadata: ScenePluginMetadata = {
8
+ ...baseComponentMetadata,
9
+ name: 'DefaultPhotoAlbumMultiSlide',
10
+ description: 'Multi photo collage slide',
11
+ sourceFile: 'src/core/scene/slide/photo-album/default-photo-album-multi-slide.tsx',
12
+ tags: Array.from(new Set([...(baseComponentMetadata.tags ?? []), 'multi', 'collage'])),
13
+ }
14
+
15
+ export const DefaultPhotoAlbumMultiSlide = VideoComponent(componentMetadata)(function DefaultPhotoAlbumMultiSlide(
16
+ props: ComponentProps<typeof DefaultPhotoAlbumSlide>,
17
+ ) {
18
+ return <DefaultPhotoAlbumSlide {...props} />
19
+ })
@@ -0,0 +1,19 @@
1
+ import type { ComponentProps } from 'react'
2
+
3
+ import { VideoComponent, type ScenePluginMetadata } from '@vibecuting/component-project-helper'
4
+
5
+ import { DefaultPhotoAlbumSlide, componentMetadata as baseComponentMetadata } from './default-photo-album-slide'
6
+
7
+ export const componentMetadata: ScenePluginMetadata = {
8
+ ...baseComponentMetadata,
9
+ name: 'DefaultPhotoAlbumPairSlide',
10
+ description: 'Two photo side-by-side slide',
11
+ sourceFile: 'src/core/scene/slide/photo-album/default-photo-album-pair-slide.tsx',
12
+ tags: Array.from(new Set([...(baseComponentMetadata.tags ?? []), 'pair', 'two-up'])),
13
+ }
14
+
15
+ export const DefaultPhotoAlbumPairSlide = VideoComponent(componentMetadata)(function DefaultPhotoAlbumPairSlide(
16
+ props: ComponentProps<typeof DefaultPhotoAlbumSlide>,
17
+ ) {
18
+ return <DefaultPhotoAlbumSlide {...props} />
19
+ })
@@ -0,0 +1,19 @@
1
+ import type { ComponentProps } from 'react'
2
+
3
+ import { VideoComponent, type ScenePluginMetadata } from '@vibecuting/component-project-helper'
4
+
5
+ import { DefaultPhotoAlbumSlide, componentMetadata as baseComponentMetadata } from './default-photo-album-slide'
6
+
7
+ export const componentMetadata: ScenePluginMetadata = {
8
+ ...baseComponentMetadata,
9
+ name: 'DefaultPhotoAlbumSingleSlide',
10
+ description: 'Single photo hero slide',
11
+ sourceFile: 'src/core/scene/slide/photo-album/default-photo-album-single-slide.tsx',
12
+ tags: Array.from(new Set([...(baseComponentMetadata.tags ?? []), 'single', 'hero-photo'])),
13
+ }
14
+
15
+ export const DefaultPhotoAlbumSingleSlide = VideoComponent(componentMetadata)(function DefaultPhotoAlbumSingleSlide(
16
+ props: ComponentProps<typeof DefaultPhotoAlbumSlide>,
17
+ ) {
18
+ return <DefaultPhotoAlbumSlide {...props} />
19
+ })
@@ -0,0 +1,26 @@
1
+ import { DefaultPhotoAlbumSlideHorizontal } from './default-photo-album-slide-Horizontal'
2
+
3
+ const meta = {
4
+ title: 'core/scene/slide/photo-album/DefaultPhotoAlbumSlideHorizontal/Animated',
5
+ component: DefaultPhotoAlbumSlideHorizontal,
6
+ args: {
7
+ title: 'Weekend in Kyoto',
8
+ subtitle: 'A compact vertical collage for social recap videos and portrait-first previews.',
9
+ photos: [
10
+ { title: 'Arrival', caption: 'Old streets, early light', meta: 'Day 1' },
11
+ { title: 'Market stop', caption: 'Local snacks and handmade ceramics', meta: 'Nishiki' },
12
+ { title: 'Temple walk', caption: 'Soft weather, slower pace', meta: 'Afternoon' },
13
+ { title: 'Dinner table', caption: 'Shared plates and warm conversation', meta: 'Evening' },
14
+ { title: 'Night city', caption: 'Neon reflections after sunset', meta: 'Day 2' },
15
+ ],
16
+ },
17
+ }
18
+
19
+ export default meta
20
+
21
+ export const Animated = {
22
+ parameters: {
23
+ scenePreviewMode: 'animation',
24
+ scenePreviewAspectRatio: '9:16',
25
+ },
26
+ }
@@ -0,0 +1,25 @@
1
+ import { DefaultPhotoAlbumSlideHorizontal } from './default-photo-album-slide-Horizontal'
2
+
3
+ const meta = {
4
+ title: 'core/scene/slide/photo-album/DefaultPhotoAlbumSlideHorizontal',
5
+ component: DefaultPhotoAlbumSlideHorizontal,
6
+ args: {
7
+ title: 'Weekend in Kyoto',
8
+ subtitle: 'A compact vertical collage for social recap videos and portrait-first previews.',
9
+ photos: [
10
+ { title: 'Arrival', caption: 'Old streets, early light', meta: 'Day 1' },
11
+ { title: 'Market stop', caption: 'Local snacks and handmade ceramics', meta: 'Nishiki' },
12
+ { title: 'Temple walk', caption: 'Soft weather, slower pace', meta: 'Afternoon' },
13
+ { title: 'Dinner table', caption: 'Shared plates and warm conversation', meta: 'Evening' },
14
+ { title: 'Night city', caption: 'Neon reflections after sunset', meta: 'Day 2' },
15
+ ],
16
+ },
17
+ }
18
+
19
+ export default meta
20
+
21
+ export const Default = {
22
+ parameters: {
23
+ scenePreviewAspectRatio: '9:16',
24
+ },
25
+ }
@@ -0,0 +1,20 @@
1
+ import type { ComponentProps } from 'react'
2
+
3
+ import { VideoComponent, type ScenePluginMetadata } from '@vibecuting/component-project-helper'
4
+
5
+ import { DefaultPhotoAlbumSlide, componentMetadata as baseComponentMetadata } from './default-photo-album-slide'
6
+
7
+ export const componentMetadata: ScenePluginMetadata = {
8
+ ...baseComponentMetadata,
9
+ name: 'DefaultPhotoAlbumSlideHorizontal',
10
+ description: 'Photo album collage slide (Portrait 9:16 variant)',
11
+ sourceFile: 'src/core/scene/slide/photo-album/default-photo-album-slide-Horizontal.tsx',
12
+ aspectRatio: '9:16',
13
+ tags: Array.from(new Set([...(baseComponentMetadata.tags ?? []), 'horizontal'])),
14
+ }
15
+
16
+ export const DefaultPhotoAlbumSlideHorizontal = VideoComponent(componentMetadata)(function DefaultPhotoAlbumSlideHorizontal(
17
+ props: ComponentProps<typeof DefaultPhotoAlbumSlide>,
18
+ ) {
19
+ return <DefaultPhotoAlbumSlide {...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 { DefaultPhotoAlbumSlide, componentMetadata as baseComponentMetadata } from './default-photo-album-slide'
6
+
7
+ export const componentMetadata: ScenePluginMetadata = {
8
+ ...baseComponentMetadata,
9
+ name: 'DefaultPhotoAlbumSlideLandscape',
10
+ description: 'Photo album collage slide (Landscape 16:9 variant)',
11
+ sourceFile: 'src/core/scene/slide/photo-album/default-photo-album-slide-Landscape.tsx',
12
+ aspectRatio: '16:9',
13
+ tags: Array.from(new Set([...(baseComponentMetadata.tags ?? []), 'landscape'])),
14
+ }
15
+
16
+ export const DefaultPhotoAlbumSlideLandscape = VideoComponent(componentMetadata)(function DefaultPhotoAlbumSlideLandscape(
17
+ props: ComponentProps<typeof DefaultPhotoAlbumSlide>,
18
+ ) {
19
+ return <DefaultPhotoAlbumSlide {...props} />
20
+ })
@@ -0,0 +1,94 @@
1
+ import { DefaultPhotoAlbumSlideLandscape } from './default-photo-album-slide-Landscape'
2
+ import { DefaultPhotoAlbumMultiSlide } from './default-photo-album-multi-slide'
3
+ import { DefaultPhotoAlbumPairSlide } from './default-photo-album-pair-slide'
4
+ import { DefaultPhotoAlbumSingleSlide } from './default-photo-album-single-slide'
5
+
6
+ const meta = {
7
+ title: 'core/scene/slide/photo-album/DefaultPhotoAlbumSlideLandscape/Animated',
8
+ component: DefaultPhotoAlbumSlideLandscape,
9
+ args: {
10
+ title: 'Weekend in Kyoto',
11
+ subtitle: 'A quiet album layout for travel recaps, family memories, and event highlights.',
12
+ photos: [
13
+ { title: 'Arrival', caption: 'Old streets, early light', meta: 'Day 1' },
14
+ { title: 'Market stop', caption: 'Local snacks and handmade ceramics', meta: 'Nishiki' },
15
+ { title: 'Temple walk', caption: 'Soft weather, slower pace', meta: 'Afternoon' },
16
+ { title: 'Dinner table', caption: 'Shared plates and warm conversation', meta: 'Evening' },
17
+ { title: 'Night city', caption: 'Neon reflections after sunset', meta: 'Day 2' },
18
+ ],
19
+ },
20
+ }
21
+
22
+ export default meta
23
+
24
+ export const Animated = {
25
+ parameters: {
26
+ scenePreviewMode: 'animation',
27
+ scenePreviewAspectRatio: '16:9',
28
+ },
29
+ }
30
+
31
+ export const Single = {
32
+ render: (storyArgs: typeof meta.args) => <DefaultPhotoAlbumSingleSlide {...storyArgs} />,
33
+ args: {
34
+ title: 'One Frame, One Memory',
35
+ subtitle: 'Animated single-photo composition.',
36
+ photos: [{ title: 'Cover shot', caption: 'A single strong image', meta: 'Hero photo' }],
37
+ },
38
+ parameters: {
39
+ scenePreviewMode: 'animation',
40
+ scenePreviewAspectRatio: '16:9',
41
+ },
42
+ }
43
+
44
+ export const Pair = {
45
+ render: (storyArgs: typeof meta.args) => <DefaultPhotoAlbumPairSlide {...storyArgs} />,
46
+ args: {
47
+ title: 'Before and After',
48
+ subtitle: 'Animated pair composition.',
49
+ photos: [
50
+ { title: 'Before', caption: 'Original capture', meta: 'Shot 1' },
51
+ { title: 'After', caption: 'Edited result', meta: 'Shot 2' },
52
+ ],
53
+ },
54
+ parameters: {
55
+ scenePreviewMode: 'animation',
56
+ scenePreviewAspectRatio: '16:9',
57
+ },
58
+ }
59
+
60
+ export const Multi = {
61
+ render: (storyArgs: typeof meta.args) => <DefaultPhotoAlbumMultiSlide {...storyArgs} />,
62
+ args: meta.args,
63
+ parameters: {
64
+ scenePreviewMode: 'animation',
65
+ scenePreviewAspectRatio: '16:9',
66
+ },
67
+ }
68
+
69
+ export const SinglePortrait = {
70
+ render: (storyArgs: typeof meta.args) => <DefaultPhotoAlbumSingleSlide {...storyArgs} />,
71
+ args: Single.args,
72
+ parameters: {
73
+ scenePreviewMode: 'animation',
74
+ scenePreviewAspectRatio: '9:16',
75
+ },
76
+ }
77
+
78
+ export const PairPortrait = {
79
+ render: (storyArgs: typeof meta.args) => <DefaultPhotoAlbumPairSlide {...storyArgs} />,
80
+ args: Pair.args,
81
+ parameters: {
82
+ scenePreviewMode: 'animation',
83
+ scenePreviewAspectRatio: '9:16',
84
+ },
85
+ }
86
+
87
+ export const MultiPortrait = {
88
+ render: (storyArgs: typeof meta.args) => <DefaultPhotoAlbumMultiSlide {...storyArgs} />,
89
+ args: Multi.args,
90
+ parameters: {
91
+ scenePreviewMode: 'animation',
92
+ scenePreviewAspectRatio: '9:16',
93
+ },
94
+ }