@vanillaskyai/video 0.5.6 → 0.5.8
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.
- package/CHANGELOG.md +14 -0
- package/dist/{bg-confetti-572VDSYM.js → bg-confetti-SHQI7ATB.js} +2 -2
- package/dist/{bg-emoji-T4IEJ6U2.js → bg-emoji-XYFRA63Q.js} +2 -2
- package/dist/{bg-media-2D5SQSJX.js → bg-media-FEBATBT2.js} +8 -6
- package/dist/{brand-message-2JCTRIGS.js → brand-message-P56WEJPG.js} +5 -3
- package/dist/{chart-bar-GAJMUB2E.js → chart-bar-ZB45ZRKH.js} +5 -3
- package/dist/{chart-counter-HYGBGXNX.js → chart-counter-HFYNE4HT.js} +8 -6
- package/dist/{chart-progress-ring-DUUVMJAJ.js → chart-progress-ring-ZKMLRGSB.js} +5 -3
- package/dist/check-runtime.js +3 -1
- package/dist/{chunk-CTEYFVUY.js → chunk-6M6DATLW.js} +26 -82
- package/dist/chunk-C6WVCZRW.js +19 -0
- package/dist/chunk-HT6BGERF.js +167 -0
- package/dist/{chunk-3QEKIC6C.js → chunk-NGY3TNND.js} +121 -11
- package/dist/{chunk-MFYFZQHM.js → chunk-W3VDIBGR.js} +1 -0
- package/dist/chunk-WJ6FLKNC.js +15 -0
- package/dist/cli.js +9 -0
- package/dist/{cta-logo-JIG22SWA.js → cta-logo-S4OMTNXD.js} +5 -3
- package/dist/{cta-media-GIHQTPPK.js → cta-media-EROTHDRR.js} +5 -3
- package/dist/{incoming-call-2O5NPJ7B.js → incoming-call-5IWJ2TAS.js} +5 -3
- package/dist/{infographic-before-after-FQXCQ2CY.js → infographic-before-after-2I7YZVDD.js} +2 -2
- package/dist/{infographic-feature-list-MVJ3GQVK.js → infographic-feature-list-7SK65U3K.js} +5 -3
- package/dist/{infographic-problem-solution-ZUF54SNF.js → infographic-problem-solution-IW35S6BR.js} +5 -3
- package/dist/{infographic-stat-row-4DLC5NSC.js → infographic-stat-row-XHUZZPDM.js} +5 -3
- package/dist/{infographic-steps-IT23RFV6.js → infographic-steps-JDDEDI7X.js} +5 -3
- package/dist/{preload-media-IYFMPMLB.js → preload-media-LJXWKTWG.js} +2 -0
- package/dist/{prompt-input-IL7HP5WX.js → prompt-input-6ZWXEL3V.js} +5 -3
- package/dist/react.js +30 -28
- package/dist/{reaction-IDFJZ7HI.js → reaction-Z3JIM3MQ.js} +5 -3
- package/dist/scene-video-backdrop-IL4F2SVD.js +9 -0
- package/dist/{showcase-code-EIGXDZE3.js → showcase-code-NWQAAJIA.js} +5 -3
- package/dist/{showcase-phone-STUZJRXV.js → showcase-phone-5UW45ATT.js} +5 -3
- package/dist/{showcase-terminal-SYP6TKP2.js → showcase-terminal-UVOD25UF.js} +5 -3
- package/dist/{showcase-web-57R4RMTG.js → showcase-web-3AW6VHIG.js} +5 -3
- package/dist/{social-milestone-J6QVX4YJ.js → social-milestone-KPKHFOB5.js} +8 -6
- package/dist/{social-notification-2RYS7NM4.js → social-notification-EDOU6TZB.js} +5 -3
- package/dist/{social-review-stack-25C6JJ4W.js → social-review-stack-EZOO33SV.js} +5 -3
- package/dist/{social-testimonial-SH54T4CW.js → social-testimonial-DLOINMMY.js} +5 -3
- package/dist/{social-tweet-T7RTFQ6T.js → social-tweet-6JUM323G.js} +5 -3
- package/examples/nextjs-quickstart/package.json +1 -1
- package/package.json +1 -1
- package/registry/items/backgrounds.json +19 -1
- package/registry/items/barChart.json +2 -2
- package/registry/items/beforeAfter.json +1 -1
- package/registry/items/bigNumber.json +2 -2
- package/registry/items/brandMessage.json +2 -2
- package/registry/items/cardList.json +2 -2
- package/registry/items/codeEditor.json +2 -2
- package/registry/items/confetti.json +1 -1
- package/registry/items/ctaLogo.json +2 -2
- package/registry/items/ctaMedia.json +2 -2
- package/registry/items/emojiBurst.json +1 -1
- package/registry/items/incomingCall.json +2 -2
- package/registry/items/media.json +2 -2
- package/registry/items/milestone.json +2 -2
- package/registry/items/notification.json +2 -2
- package/registry/items/phoneMockup.json +2 -2
- package/registry/items/problemSolution.json +2 -2
- package/registry/items/progressRing.json +2 -2
- package/registry/items/promptInput.json +2 -2
- package/registry/items/reaction.json +2 -2
- package/registry/items/reviewStack.json +2 -2
- package/registry/items/steps.json +2 -2
- package/registry/items/terminal.json +2 -2
- package/registry/items/testimonial.json +2 -2
- package/registry/items/tripleStats.json +2 -2
- package/registry/items/tweet.json +2 -2
- 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.8
|
|
8
|
+
|
|
9
|
+
- Moved the public source to a fresh repository at
|
|
10
|
+
`github.com/VanillaSkyAi/video`. No runtime code changed in this release; the
|
|
11
|
+
package, its public API, and its behaviour are identical to 0.5.7.
|
|
12
|
+
|
|
13
|
+
## 0.5.7
|
|
14
|
+
|
|
15
|
+
- Keeps one persistent video backdrop element across consecutive iPhone and
|
|
16
|
+
iPad scenes, cross-fades through the decoded incoming poster during Safari's
|
|
17
|
+
source reset, avoids detached iOS preload decoders, and removes the CSS
|
|
18
|
+
poster workaround introduced in 0.5.6. Desktop retains its decoded
|
|
19
|
+
video-to-video cross-fade.
|
|
20
|
+
|
|
7
21
|
## 0.5.6
|
|
8
22
|
|
|
9
23
|
- Keeps a video's warmed poster painted behind its frame so Mobile Safari
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
import "./chunk-L5BTTCZV.js";
|
|
9
9
|
import {
|
|
10
10
|
BrandGradientOverlay
|
|
11
|
-
} from "./chunk-
|
|
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-
|
|
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-CTEYFVUY.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-
|
|
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-
|
|
7
|
+
} from "./chunk-6M6DATLW.js";
|
|
8
8
|
import {
|
|
9
9
|
renderWithEmoji
|
|
10
10
|
} from "./chunk-L5BTTCZV.js";
|
|
11
|
-
import "./chunk-
|
|
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-
|
|
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-
|
|
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-CTEYFVUY.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-
|
|
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-
|
|
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-
|
|
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
|
package/dist/check-runtime.js
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import {
|
|
2
2
|
VideoFrame
|
|
3
|
-
} from "./chunk-
|
|
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-
|
|
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,
|
|
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,46 +150,18 @@ var SceneBackground = ({
|
|
|
178
150
|
seed: gradSeed
|
|
179
151
|
}
|
|
180
152
|
),
|
|
181
|
-
showMedia && (resolved === "video" ? /* @__PURE__ */ jsx(
|
|
182
|
-
|
|
153
|
+
showMedia && !hasExternalVideoBackdrop && (resolved === "video" ? /* @__PURE__ */ jsx(
|
|
154
|
+
SceneVideoBackdrop,
|
|
183
155
|
{
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
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
|
-
// Mobile WebKit can briefly make a newly mounted video layer
|
|
212
|
-
// transparent while handing the decoder over from the previous
|
|
213
|
-
// scene. Keep the already-warmed poster painted behind the
|
|
214
|
-
// replaced content so that gap never exposes the gradient.
|
|
215
|
-
backgroundImage: mediaPoster ? `url(${mediaPoster})` : void 0,
|
|
216
|
-
backgroundSize: "cover",
|
|
217
|
-
backgroundPosition: resolvedPosition,
|
|
218
|
-
transform: bgTransform.transform,
|
|
219
|
-
transformOrigin: bgTransform.transformOrigin
|
|
220
|
-
}
|
|
156
|
+
mediaUrl,
|
|
157
|
+
mediaPoster,
|
|
158
|
+
mediaPosition,
|
|
159
|
+
backgroundEffect,
|
|
160
|
+
progress,
|
|
161
|
+
beatIntensity,
|
|
162
|
+
isPlaying,
|
|
163
|
+
onReady: () => setMediaPaint("ready"),
|
|
164
|
+
onError: () => setMediaPaint("failed")
|
|
221
165
|
}
|
|
222
166
|
) : /* @__PURE__ */ jsx(
|
|
223
167
|
"div",
|
|
@@ -234,7 +178,7 @@ var SceneBackground = ({
|
|
|
234
178
|
}
|
|
235
179
|
}
|
|
236
180
|
)),
|
|
237
|
-
showTreatment && treatmentLayers.map((layer) => /* @__PURE__ */ jsx(
|
|
181
|
+
(hasExternalVideoBackdrop ? externalVideoReady : showTreatment) && !externalVideoFailed && treatmentLayers.map((layer) => /* @__PURE__ */ jsx(
|
|
238
182
|
"div",
|
|
239
183
|
{
|
|
240
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
|
+
};
|