@vanillaskyai/video 0.5.5 → 0.5.7

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 (67) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/{bg-confetti-572VDSYM.js → bg-confetti-SHQI7ATB.js} +2 -2
  3. package/dist/{bg-emoji-T4IEJ6U2.js → bg-emoji-XYFRA63Q.js} +2 -2
  4. package/dist/{bg-media-5YR4OLFG.js → bg-media-FEBATBT2.js} +8 -6
  5. package/dist/{brand-message-7524B6HC.js → brand-message-P56WEJPG.js} +5 -3
  6. package/dist/{chart-bar-5UMZXTON.js → chart-bar-ZB45ZRKH.js} +5 -3
  7. package/dist/{chart-counter-QUVLAX42.js → chart-counter-HFYNE4HT.js} +8 -6
  8. package/dist/{chart-progress-ring-IYCNRU7T.js → chart-progress-ring-ZKMLRGSB.js} +5 -3
  9. package/dist/check-runtime.js +3 -1
  10. package/dist/{chunk-EHXDKCYR.js → chunk-6M6DATLW.js} +26 -75
  11. package/dist/chunk-C6WVCZRW.js +19 -0
  12. package/dist/chunk-HT6BGERF.js +167 -0
  13. package/dist/{chunk-3QEKIC6C.js → chunk-NGY3TNND.js} +121 -11
  14. package/dist/{chunk-MFYFZQHM.js → chunk-W3VDIBGR.js} +1 -0
  15. package/dist/chunk-WJ6FLKNC.js +15 -0
  16. package/dist/cli.js +9 -0
  17. package/dist/{cta-logo-PREL7MLE.js → cta-logo-S4OMTNXD.js} +5 -3
  18. package/dist/{cta-media-YWTYVLR6.js → cta-media-EROTHDRR.js} +5 -3
  19. package/dist/{incoming-call-C3FX4SFR.js → incoming-call-5IWJ2TAS.js} +5 -3
  20. package/dist/{infographic-before-after-FQXCQ2CY.js → infographic-before-after-2I7YZVDD.js} +2 -2
  21. package/dist/{infographic-feature-list-WWX5AGU4.js → infographic-feature-list-7SK65U3K.js} +5 -3
  22. package/dist/{infographic-problem-solution-3JBBGNXU.js → infographic-problem-solution-IW35S6BR.js} +5 -3
  23. package/dist/{infographic-stat-row-7X6KEEUD.js → infographic-stat-row-XHUZZPDM.js} +5 -3
  24. package/dist/{infographic-steps-FI5LN4SS.js → infographic-steps-JDDEDI7X.js} +5 -3
  25. package/dist/{preload-media-IYFMPMLB.js → preload-media-LJXWKTWG.js} +2 -0
  26. package/dist/{prompt-input-NNXF6WVS.js → prompt-input-6ZWXEL3V.js} +5 -3
  27. package/dist/react.js +30 -28
  28. package/dist/{reaction-DH6M6LSQ.js → reaction-Z3JIM3MQ.js} +5 -3
  29. package/dist/scene-video-backdrop-IL4F2SVD.js +9 -0
  30. package/dist/{showcase-code-QDJM7E2Z.js → showcase-code-NWQAAJIA.js} +5 -3
  31. package/dist/{showcase-phone-IIYR34CF.js → showcase-phone-5UW45ATT.js} +5 -3
  32. package/dist/{showcase-terminal-3253HMTE.js → showcase-terminal-UVOD25UF.js} +5 -3
  33. package/dist/{showcase-web-H7GB3FBH.js → showcase-web-3AW6VHIG.js} +5 -3
  34. package/dist/{social-milestone-MLWAWF6X.js → social-milestone-KPKHFOB5.js} +8 -6
  35. package/dist/{social-notification-2UQKKOB3.js → social-notification-EDOU6TZB.js} +5 -3
  36. package/dist/{social-review-stack-VHJPE6GM.js → social-review-stack-EZOO33SV.js} +5 -3
  37. package/dist/{social-testimonial-QUNCY52L.js → social-testimonial-DLOINMMY.js} +5 -3
  38. package/dist/{social-tweet-33HIL4RR.js → social-tweet-6JUM323G.js} +5 -3
  39. package/examples/nextjs-quickstart/package.json +1 -1
  40. package/package.json +1 -1
  41. package/registry/items/backgrounds.json +19 -1
  42. package/registry/items/barChart.json +2 -2
  43. package/registry/items/beforeAfter.json +1 -1
  44. package/registry/items/bigNumber.json +2 -2
  45. package/registry/items/brandMessage.json +2 -2
  46. package/registry/items/cardList.json +2 -2
  47. package/registry/items/codeEditor.json +2 -2
  48. package/registry/items/confetti.json +1 -1
  49. package/registry/items/ctaLogo.json +2 -2
  50. package/registry/items/ctaMedia.json +2 -2
  51. package/registry/items/emojiBurst.json +1 -1
  52. package/registry/items/incomingCall.json +2 -2
  53. package/registry/items/media.json +2 -2
  54. package/registry/items/milestone.json +2 -2
  55. package/registry/items/notification.json +2 -2
  56. package/registry/items/phoneMockup.json +2 -2
  57. package/registry/items/problemSolution.json +2 -2
  58. package/registry/items/progressRing.json +2 -2
  59. package/registry/items/promptInput.json +2 -2
  60. package/registry/items/reaction.json +2 -2
  61. package/registry/items/reviewStack.json +2 -2
  62. package/registry/items/steps.json +2 -2
  63. package/registry/items/terminal.json +2 -2
  64. package/registry/items/testimonial.json +2 -2
  65. package/registry/items/tripleStats.json +2 -2
  66. package/registry/items/tweet.json +2 -2
  67. package/registry/items/webMockup.json +2 -2
package/CHANGELOG.md CHANGED
@@ -4,6 +4,20 @@ VanillaSky follows semantic versioning. This changelog begins with the 0.1 beta.
4
4
 
5
5
  ## Unreleased
6
6
 
7
+ ## 0.5.7
8
+
9
+ - Keeps one persistent video backdrop element across consecutive iPhone and
10
+ iPad scenes, cross-fades through the decoded incoming poster during Safari's
11
+ source reset, avoids detached iOS preload decoders, and removes the CSS
12
+ poster workaround introduced in 0.5.6. Desktop retains its decoded
13
+ video-to-video cross-fade.
14
+
15
+ ## 0.5.6
16
+
17
+ - Keeps a video's warmed poster painted behind its frame so Mobile Safari
18
+ cannot expose the brand gradient while transferring its decoder between
19
+ consecutive media scenes.
20
+
7
21
  ## 0.5.5
8
22
 
9
23
  - Keeps a Mobile Safari video poster visible until the replacement video has
@@ -8,7 +8,7 @@ import {
8
8
  import "./chunk-L5BTTCZV.js";
9
9
  import {
10
10
  BrandGradientOverlay
11
- } from "./chunk-MFYFZQHM.js";
11
+ } from "./chunk-W3VDIBGR.js";
12
12
  import "./chunk-XTOXFMLM.js";
13
13
  import {
14
14
  resolveTokens
@@ -36,7 +36,7 @@ var BgConfettiTemplate = ({
36
36
  style: {
37
37
  width,
38
38
  height,
39
- backgroundColor: "#000",
39
+ backgroundColor: "var(--vanillasky-template-surface, #000)",
40
40
  position: "relative",
41
41
  overflow: "hidden",
42
42
  fontFamily: font
@@ -9,7 +9,7 @@ import {
9
9
  } from "./chunk-L5BTTCZV.js";
10
10
  import {
11
11
  BrandGradientOverlay
12
- } from "./chunk-MFYFZQHM.js";
12
+ } from "./chunk-W3VDIBGR.js";
13
13
  import "./chunk-XTOXFMLM.js";
14
14
  import {
15
15
  resolveTokens
@@ -65,7 +65,7 @@ var BgEmojiTemplate = ({
65
65
  style: {
66
66
  width,
67
67
  height,
68
- backgroundColor: "#000",
68
+ backgroundColor: "var(--vanillasky-template-surface, #000)",
69
69
  position: "relative",
70
70
  overflow: "hidden",
71
71
  fontFamily: font
@@ -1,17 +1,19 @@
1
- import {
2
- SceneBackground,
3
- getMediaBackgroundProps
4
- } from "./chunk-EHXDKCYR.js";
5
1
  import {
6
2
  ConfettiLayer
7
3
  } from "./chunk-CJ7F2CE6.js";
8
4
  import "./chunk-QAAO7OAY.js";
5
+ import {
6
+ SceneBackground,
7
+ getMediaBackgroundProps
8
+ } from "./chunk-6M6DATLW.js";
9
9
  import {
10
10
  TemplateText
11
11
  } from "./chunk-TCEHK2BW.js";
12
12
  import "./chunk-L5BTTCZV.js";
13
- import "./chunk-MFYFZQHM.js";
13
+ import "./chunk-HT6BGERF.js";
14
+ import "./chunk-W3VDIBGR.js";
14
15
  import "./chunk-XTOXFMLM.js";
16
+ import "./chunk-C6WVCZRW.js";
15
17
  import {
16
18
  hasSceneMedia
17
19
  } from "./chunk-224QNWRA.js";
@@ -43,7 +45,7 @@ var BgMediaTemplate = ({
43
45
  style: {
44
46
  width,
45
47
  height,
46
- backgroundColor: "#000",
48
+ backgroundColor: "var(--vanillasky-template-surface, #000)",
47
49
  position: "relative",
48
50
  overflow: "hidden",
49
51
  fontFamily: font
@@ -4,14 +4,16 @@ import {
4
4
  import {
5
5
  SceneBackground,
6
6
  getMediaBackgroundProps
7
- } from "./chunk-EHXDKCYR.js";
7
+ } from "./chunk-6M6DATLW.js";
8
8
  import {
9
9
  renderWithEmoji
10
10
  } from "./chunk-L5BTTCZV.js";
11
- import "./chunk-MFYFZQHM.js";
11
+ import "./chunk-HT6BGERF.js";
12
+ import "./chunk-W3VDIBGR.js";
12
13
  import {
13
14
  interpolate
14
15
  } from "./chunk-XTOXFMLM.js";
16
+ import "./chunk-C6WVCZRW.js";
15
17
  import "./chunk-224QNWRA.js";
16
18
  import "./chunk-XWWLKRNU.js";
17
19
 
@@ -208,7 +210,7 @@ var BrandMessageTemplate = ({
208
210
  style: {
209
211
  width,
210
212
  height,
211
- backgroundColor: "#000",
213
+ backgroundColor: "var(--vanillasky-template-surface, #000)",
212
214
  position: "relative",
213
215
  overflow: "hidden",
214
216
  // System fonts only — see BrandMessageBubble for the why
@@ -1,20 +1,22 @@
1
1
  import {
2
2
  SceneBackground,
3
3
  getMediaBackgroundProps
4
- } from "./chunk-EHXDKCYR.js";
4
+ } from "./chunk-6M6DATLW.js";
5
5
  import {
6
6
  TemplateText
7
7
  } from "./chunk-TCEHK2BW.js";
8
8
  import "./chunk-L5BTTCZV.js";
9
+ import "./chunk-HT6BGERF.js";
9
10
  import {
10
11
  TOP_TEXT_AREA_RATIO,
11
12
  withOpacity
12
- } from "./chunk-MFYFZQHM.js";
13
+ } from "./chunk-W3VDIBGR.js";
13
14
  import {
14
15
  SPRING_SNAPPY,
15
16
  interpolate,
16
17
  spring
17
18
  } from "./chunk-XTOXFMLM.js";
19
+ import "./chunk-C6WVCZRW.js";
18
20
  import {
19
21
  hasSceneMedia
20
22
  } from "./chunk-224QNWRA.js";
@@ -246,7 +248,7 @@ var ChartBarTemplate = ({
246
248
  style: {
247
249
  width,
248
250
  height,
249
- backgroundColor: "#000",
251
+ backgroundColor: "var(--vanillasky-template-surface, #000)",
250
252
  position: "relative",
251
253
  overflow: "hidden",
252
254
  fontFamily: font
@@ -1,26 +1,28 @@
1
1
  import {
2
2
  getResponsiveFontSize
3
3
  } from "./chunk-S7HFLYNN.js";
4
- import {
5
- SceneBackground,
6
- getMediaBackgroundProps
7
- } from "./chunk-EHXDKCYR.js";
8
4
  import {
9
5
  ConfettiLayer
10
6
  } from "./chunk-CJ7F2CE6.js";
11
7
  import "./chunk-QAAO7OAY.js";
8
+ import {
9
+ SceneBackground,
10
+ getMediaBackgroundProps
11
+ } from "./chunk-6M6DATLW.js";
12
12
  import {
13
13
  TemplateText
14
14
  } from "./chunk-TCEHK2BW.js";
15
15
  import "./chunk-L5BTTCZV.js";
16
+ import "./chunk-HT6BGERF.js";
16
17
  import {
17
18
  TOP_TEXT_AREA_RATIO,
18
19
  withOpacity
19
- } from "./chunk-MFYFZQHM.js";
20
+ } from "./chunk-W3VDIBGR.js";
20
21
  import {
21
22
  interpolate,
22
23
  spring
23
24
  } from "./chunk-XTOXFMLM.js";
25
+ import "./chunk-C6WVCZRW.js";
24
26
  import {
25
27
  hasSceneMedia
26
28
  } from "./chunk-224QNWRA.js";
@@ -207,7 +209,7 @@ var ChartCounterTemplate = ({
207
209
  style: {
208
210
  width,
209
211
  height,
210
- backgroundColor: "#000",
212
+ backgroundColor: "var(--vanillasky-template-surface, #000)",
211
213
  position: "relative",
212
214
  overflow: "hidden",
213
215
  fontFamily: font
@@ -5,18 +5,20 @@ import {
5
5
  import {
6
6
  SceneBackground,
7
7
  getMediaBackgroundProps
8
- } from "./chunk-EHXDKCYR.js";
8
+ } from "./chunk-6M6DATLW.js";
9
9
  import {
10
10
  TemplateText
11
11
  } from "./chunk-TCEHK2BW.js";
12
12
  import "./chunk-L5BTTCZV.js";
13
+ import "./chunk-HT6BGERF.js";
13
14
  import {
14
15
  TOP_TEXT_AREA_RATIO,
15
16
  withOpacity
16
- } from "./chunk-MFYFZQHM.js";
17
+ } from "./chunk-W3VDIBGR.js";
17
18
  import {
18
19
  interpolate
19
20
  } from "./chunk-XTOXFMLM.js";
21
+ import "./chunk-C6WVCZRW.js";
20
22
  import {
21
23
  hasSceneMedia
22
24
  } from "./chunk-224QNWRA.js";
@@ -233,7 +235,7 @@ var ChartProgressRingTemplate = ({
233
235
  style: {
234
236
  width,
235
237
  height,
236
- backgroundColor: "#000",
238
+ backgroundColor: "var(--vanillasky-template-surface, #000)",
237
239
  position: "relative",
238
240
  overflow: "hidden",
239
241
  fontFamily: font
@@ -1,12 +1,14 @@
1
1
  import {
2
2
  VideoFrame
3
- } from "./chunk-3QEKIC6C.js";
3
+ } from "./chunk-NGY3TNND.js";
4
+ import "./chunk-C6WVCZRW.js";
4
5
  import "./chunk-224QNWRA.js";
5
6
  import "./chunk-XWWLKRNU.js";
6
7
  import "./chunk-SPVTJH3F.js";
7
8
  import {
8
9
  resolveVideoBrand
9
10
  } from "./chunk-XGRA2MUV.js";
11
+ import "./chunk-WJ6FLKNC.js";
10
12
  import "./chunk-73NTSFFI.js";
11
13
 
12
14
  // src/cli/check-runtime.ts
@@ -1,25 +1,21 @@
1
+ import {
2
+ SceneVideoBackdrop,
3
+ resolveMediaPosition
4
+ } from "./chunk-HT6BGERF.js";
1
5
  import {
2
6
  BrandGradientOverlay,
3
7
  getBackgroundTransform
4
- } from "./chunk-MFYFZQHM.js";
8
+ } from "./chunk-W3VDIBGR.js";
9
+ import {
10
+ useExternalVideoBackdrop
11
+ } from "./chunk-C6WVCZRW.js";
5
12
  import {
6
- limitsConcurrentVideoDecoders,
7
13
  resolveMediaType
8
14
  } from "./chunk-224QNWRA.js";
9
15
 
10
16
  // src/visual-system/scene-templates/scene-background.tsx
11
- import { useEffect, useRef, useState } from "react";
17
+ import { useEffect, useState } from "react";
12
18
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
13
- var MEDIA_POSITIONS = {
14
- center: "center center",
15
- top: "center top",
16
- bottom: "center bottom",
17
- left: "left center",
18
- right: "right center"
19
- };
20
- function resolveMediaPosition(value) {
21
- return MEDIA_POSITIONS[value] ?? MEDIA_POSITIONS.center;
22
- }
23
19
  function resolveMediaTreatment(value) {
24
20
  return value === "subtle" || value === "text-safe" ? value : "cinematic";
25
21
  }
@@ -106,10 +102,13 @@ var SceneBackground = ({
106
102
  void _height;
107
103
  const resolved = resolveMediaType(mediaType, mediaUrl);
108
104
  const wantsMedia = resolved !== "gradient" && !!mediaUrl;
105
+ const externalVideoBackdrop = useExternalVideoBackdrop();
106
+ const hasExternalVideoBackdrop = externalVideoBackdrop !== false && resolved === "video";
107
+ const externalVideoFailed = externalVideoBackdrop === "fallback" && resolved === "video";
108
+ const externalVideoReady = externalVideoBackdrop === "ready" && resolved === "video";
109
109
  const [mediaPaint, setMediaPaint] = useState(
110
110
  () => initialMediaPaint(wantsMedia, resolved, mediaUrl, mediaPoster)
111
111
  );
112
- const [decodedVideoUrl, setDecodedVideoUrl] = useState();
113
112
  useEffect(() => {
114
113
  setMediaPaint(initialMediaPaint(wantsMedia, resolved, mediaUrl, mediaPoster));
115
114
  if (!wantsMedia || resolved !== "photo") return;
@@ -141,35 +140,8 @@ var SceneBackground = ({
141
140
  progress,
142
141
  beatIntensity
143
142
  );
144
- const videoRef = useRef(null);
145
- const videoStarted = useRef(false);
146
- useEffect(() => {
147
- const vid = videoRef.current;
148
- if (!vid) return;
149
- if (!isPlaying) {
150
- vid.pause();
151
- videoStarted.current = false;
152
- return;
153
- }
154
- if (!videoStarted.current) {
155
- vid.playbackRate = 1;
156
- if (vid.currentTime > 0) vid.currentTime = 0;
157
- vid.play().catch(() => {
158
- });
159
- videoStarted.current = true;
160
- }
161
- }, [progress, isPlaying]);
162
- useEffect(() => {
163
- const vid = videoRef.current;
164
- return () => {
165
- if (!vid) return;
166
- vid.pause();
167
- vid.removeAttribute("src");
168
- vid.load();
169
- };
170
- }, []);
171
143
  return /* @__PURE__ */ jsxs(Fragment, { children: [
172
- /* @__PURE__ */ jsx(
144
+ (!hasExternalVideoBackdrop || externalVideoFailed) && /* @__PURE__ */ jsx(
173
145
  BrandGradientOverlay,
174
146
  {
175
147
  style,
@@ -178,39 +150,18 @@ var SceneBackground = ({
178
150
  seed: gradSeed
179
151
  }
180
152
  ),
181
- showMedia && (resolved === "video" ? /* @__PURE__ */ jsx(
182
- "video",
153
+ showMedia && !hasExternalVideoBackdrop && (resolved === "video" ? /* @__PURE__ */ jsx(
154
+ SceneVideoBackdrop,
183
155
  {
184
- ref: videoRef,
185
- src: mediaUrl,
186
- poster: decodedVideoUrl === mediaUrl ? void 0 : mediaPoster || void 0,
187
- muted: true,
188
- loop: true,
189
- playsInline: true,
190
- preload: "auto",
191
- onLoadedData: (event) => {
192
- setMediaPaint("ready");
193
- const video = event.currentTarget;
194
- if (!limitsConcurrentVideoDecoders()) {
195
- setDecodedVideoUrl(mediaUrl);
196
- return;
197
- }
198
- video.requestVideoFrameCallback?.(() => {
199
- if (video.isConnected) setDecodedVideoUrl(mediaUrl);
200
- });
201
- },
202
- onError: () => setMediaPaint("failed"),
203
- "data-media-position": mediaPosition,
204
- style: {
205
- position: "absolute",
206
- inset: 0,
207
- width: "100%",
208
- height: "100%",
209
- objectFit: "cover",
210
- objectPosition: resolvedPosition,
211
- transform: bgTransform.transform,
212
- transformOrigin: bgTransform.transformOrigin
213
- }
156
+ mediaUrl,
157
+ mediaPoster,
158
+ mediaPosition,
159
+ backgroundEffect,
160
+ progress,
161
+ beatIntensity,
162
+ isPlaying,
163
+ onReady: () => setMediaPaint("ready"),
164
+ onError: () => setMediaPaint("failed")
214
165
  }
215
166
  ) : /* @__PURE__ */ jsx(
216
167
  "div",
@@ -227,7 +178,7 @@ var SceneBackground = ({
227
178
  }
228
179
  }
229
180
  )),
230
- showTreatment && treatmentLayers.map((layer) => /* @__PURE__ */ jsx(
181
+ (hasExternalVideoBackdrop ? externalVideoReady : showTreatment) && !externalVideoFailed && treatmentLayers.map((layer) => /* @__PURE__ */ jsx(
231
182
  "div",
232
183
  {
233
184
  "data-media-treatment": resolvedTreatment,
@@ -0,0 +1,19 @@
1
+ // src/visual-system/scene-templates/external-video-backdrop.tsx
2
+ import React from "react";
3
+ import { jsx } from "react/jsx-runtime";
4
+ var sharedContext = globalThis;
5
+ var ExternalVideoBackdropContext = sharedContext.__vanillaskyExternalVideoBackdropContext ??= React.createContext(false);
6
+ function ExternalVideoBackdropProvider({
7
+ mode,
8
+ children
9
+ }) {
10
+ return /* @__PURE__ */ jsx(ExternalVideoBackdropContext.Provider, { value: mode, children });
11
+ }
12
+ function useExternalVideoBackdrop() {
13
+ return React.useContext(ExternalVideoBackdropContext);
14
+ }
15
+
16
+ export {
17
+ ExternalVideoBackdropProvider,
18
+ useExternalVideoBackdrop
19
+ };
@@ -0,0 +1,167 @@
1
+ import {
2
+ getBackgroundTransform
3
+ } from "./chunk-W3VDIBGR.js";
4
+
5
+ // src/visual-system/scene-templates/scene-video-backdrop.tsx
6
+ import { useEffect, useRef, useState } from "react";
7
+
8
+ // src/visual-system/scene-templates/media-position.ts
9
+ var MEDIA_POSITIONS = {
10
+ center: "center center",
11
+ top: "center top",
12
+ bottom: "center bottom",
13
+ left: "left center",
14
+ right: "right center"
15
+ };
16
+ function resolveMediaPosition(value) {
17
+ return MEDIA_POSITIONS[value] ?? MEDIA_POSITIONS.center;
18
+ }
19
+
20
+ // src/visual-system/scene-templates/scene-video-backdrop.tsx
21
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
22
+ var SceneVideoBackdrop = ({
23
+ mediaUrl,
24
+ mediaPoster,
25
+ mediaPosition = "center",
26
+ backgroundEffect,
27
+ progress,
28
+ beatIntensity = 0,
29
+ isPlaying,
30
+ playbackId = mediaUrl,
31
+ retainPoster = false,
32
+ persistent = false,
33
+ preparedPoster,
34
+ onReady,
35
+ onError
36
+ }) => {
37
+ const resolvedPosition = resolveMediaPosition(mediaPosition);
38
+ const bgTransform = getBackgroundTransform(backgroundEffect, progress, beatIntensity);
39
+ const [decodedVideoUrl, setDecodedVideoUrl] = useState();
40
+ const videoRef = useRef(null);
41
+ const startedVideoUrl = useRef(void 0);
42
+ const startedPlaybackId = useRef(void 0);
43
+ const videoPresentationKey = `${playbackId}\0${mediaUrl}`;
44
+ useEffect(() => {
45
+ const video = videoRef.current;
46
+ if (!video) return;
47
+ if (!isPlaying) {
48
+ video.pause();
49
+ startedVideoUrl.current = void 0;
50
+ startedPlaybackId.current = void 0;
51
+ return;
52
+ }
53
+ if (startedPlaybackId.current === playbackId) return;
54
+ const changingSource = startedVideoUrl.current !== void 0 && startedVideoUrl.current !== mediaUrl;
55
+ video.playbackRate = 1;
56
+ if (!changingSource && video.currentTime > 0) video.currentTime = 0;
57
+ video.play().catch(() => {
58
+ });
59
+ startedVideoUrl.current = mediaUrl;
60
+ startedPlaybackId.current = playbackId;
61
+ }, [isPlaying, mediaUrl, playbackId]);
62
+ useEffect(() => {
63
+ const video = videoRef.current;
64
+ return () => {
65
+ if (!video) return;
66
+ video.pause();
67
+ video.removeAttribute("src");
68
+ video.load();
69
+ };
70
+ }, []);
71
+ const mediaStyle = {
72
+ position: "absolute",
73
+ inset: 0,
74
+ width: "100%",
75
+ height: "100%",
76
+ objectFit: "cover",
77
+ objectPosition: resolvedPosition,
78
+ transform: bgTransform.transform,
79
+ transformOrigin: bgTransform.transformOrigin,
80
+ zIndex: persistent ? 1 : void 0
81
+ };
82
+ const preparedPosition = preparedPoster ? resolveMediaPosition(preparedPoster.mediaPosition) : resolvedPosition;
83
+ const preparedTransform = getBackgroundTransform(preparedPoster?.backgroundEffect, 0, 0);
84
+ const posterPlanes = [
85
+ ...persistent && mediaPoster ? [{
86
+ presentationKey: videoPresentationKey,
87
+ mediaPoster,
88
+ mediaPosition: resolvedPosition,
89
+ transform: bgTransform.transform,
90
+ transformOrigin: bgTransform.transformOrigin,
91
+ opacity: 1,
92
+ zIndex: 0,
93
+ role: "current"
94
+ }] : [],
95
+ ...preparedPoster && preparedPoster.presentationKey !== videoPresentationKey ? [{
96
+ presentationKey: preparedPoster.presentationKey,
97
+ mediaPoster: preparedPoster.mediaPoster,
98
+ mediaPosition: preparedPosition,
99
+ transform: preparedTransform.transform,
100
+ transformOrigin: preparedTransform.transformOrigin,
101
+ opacity: preparedPoster.opacity ?? 0,
102
+ zIndex: 2,
103
+ role: "prepared"
104
+ }] : []
105
+ ];
106
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
107
+ posterPlanes.map((posterPlane) => /* @__PURE__ */ jsx(
108
+ "img",
109
+ {
110
+ src: posterPlane.mediaPoster,
111
+ alt: "",
112
+ "aria-hidden": "true",
113
+ draggable: false,
114
+ "data-video-poster-plane": posterPlane.role,
115
+ "data-video-poster-visible": posterPlane.opacity > 0 ? "true" : "false",
116
+ style: {
117
+ position: "absolute",
118
+ inset: 0,
119
+ width: "100%",
120
+ height: "100%",
121
+ objectFit: "cover",
122
+ objectPosition: posterPlane.mediaPosition,
123
+ transform: posterPlane.transform,
124
+ transformOrigin: posterPlane.transformOrigin,
125
+ zIndex: posterPlane.zIndex,
126
+ opacity: posterPlane.opacity,
127
+ pointerEvents: "none"
128
+ }
129
+ },
130
+ posterPlane.presentationKey
131
+ )),
132
+ /* @__PURE__ */ jsx(
133
+ "video",
134
+ {
135
+ ref: videoRef,
136
+ src: mediaUrl,
137
+ poster: retainPoster || decodedVideoUrl !== mediaUrl ? mediaPoster || void 0 : void 0,
138
+ muted: true,
139
+ loop: true,
140
+ playsInline: true,
141
+ preload: "auto",
142
+ onLoadedData: (event) => {
143
+ const video = event.currentTarget;
144
+ const markPresented = () => {
145
+ if (!video.isConnected) return;
146
+ onReady?.();
147
+ if (!retainPoster) setDecodedVideoUrl(mediaUrl);
148
+ };
149
+ if (video.requestVideoFrameCallback) {
150
+ video.requestVideoFrameCallback(markPresented);
151
+ return;
152
+ }
153
+ markPresented();
154
+ },
155
+ onError,
156
+ "data-media-position": mediaPosition,
157
+ "data-video-backdrop": persistent ? "persistent" : "scene",
158
+ style: mediaStyle
159
+ }
160
+ )
161
+ ] });
162
+ };
163
+
164
+ export {
165
+ resolveMediaPosition,
166
+ SceneVideoBackdrop
167
+ };