stormcloud-video-player 0.7.1 → 0.7.3

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/lib/index.js CHANGED
@@ -964,7 +964,6 @@ function createVastAdLayer(contentVideo, options) {
964
964
  var tornDown = false;
965
965
  var trackingFired = createEmptyTrackingState();
966
966
  var adStallTimerId;
967
- var savedContentVideoStyles;
968
967
  var currentAdEventHandlers;
969
968
  var preloadSlots = /* @__PURE__ */ new Map();
970
969
  function emit(event, payload) {
@@ -1081,7 +1080,7 @@ function createVastAdLayer(contentVideo, options) {
1081
1080
  video.style.top = "0";
1082
1081
  video.style.width = "100%";
1083
1082
  video.style.height = "100%";
1084
- video.style.objectFit = "cover";
1083
+ video.style.objectFit = "contain";
1085
1084
  video.style.backgroundColor = "#000";
1086
1085
  video.playsInline = true;
1087
1086
  video.muted = false;
@@ -1196,31 +1195,12 @@ function createVastAdLayer(contentVideo, options) {
1196
1195
  delete contentVideo.dataset.stormcloudAdPlaying;
1197
1196
  }
1198
1197
  }
1199
- function applyContentVideoAdCoverStyles() {
1200
- if (!singleElementMode) return;
1201
- savedContentVideoStyles = {
1202
- objectFit: contentVideo.style.objectFit,
1203
- width: contentVideo.style.width,
1204
- height: contentVideo.style.height
1205
- };
1206
- contentVideo.style.objectFit = "cover";
1207
- contentVideo.style.width = "100%";
1208
- contentVideo.style.height = "100%";
1209
- }
1210
- function restoreContentVideoStyles() {
1211
- if (!singleElementMode || !savedContentVideoStyles) return;
1212
- contentVideo.style.objectFit = savedContentVideoStyles.objectFit;
1213
- contentVideo.style.width = savedContentVideoStyles.width;
1214
- contentVideo.style.height = savedContentVideoStyles.height;
1215
- savedContentVideoStyles = void 0;
1216
- }
1217
1198
  function handleAdComplete() {
1218
1199
  if (tornDown) return;
1219
1200
  clearAdStallTimer();
1220
1201
  if (debug) console.log("".concat(LOG, " Handling ad completion"));
1221
1202
  adPlaying = false;
1222
1203
  setAdPlayingFlag(false);
1223
- restoreContentVideoStyles();
1224
1204
  if (adContainerEl) {
1225
1205
  adContainerEl.style.display = "none";
1226
1206
  adContainerEl.style.pointerEvents = "none";
@@ -1235,7 +1215,6 @@ function createVastAdLayer(contentVideo, options) {
1235
1215
  if (debug) console.log("".concat(LOG, " Handling ad error"));
1236
1216
  adPlaying = false;
1237
1217
  setAdPlayingFlag(false);
1238
- restoreContentVideoStyles();
1239
1218
  if (adContainerEl) {
1240
1219
  adContainerEl.style.display = "none";
1241
1220
  adContainerEl.style.pointerEvents = "none";
@@ -1406,7 +1385,6 @@ function createVastAdLayer(contentVideo, options) {
1406
1385
  ];
1407
1386
  contentVideo.style.visibility = "visible";
1408
1387
  contentVideo.style.opacity = "1";
1409
- applyContentVideoAdCoverStyles();
1410
1388
  emit("content_pause");
1411
1389
  setupAdEventListeners();
1412
1390
  adVolume2 = originalMutedState ? 1 : originalVolume;
@@ -1645,7 +1623,6 @@ function createVastAdLayer(contentVideo, options) {
1645
1623
  ];
1646
1624
  contentVideo.style.visibility = "visible";
1647
1625
  contentVideo.style.opacity = "1";
1648
- applyContentVideoAdCoverStyles();
1649
1626
  emit("content_pause");
1650
1627
  setupAdEventListeners();
1651
1628
  adVolume2 = originalMutedState ? 1 : originalVolume;
@@ -1796,7 +1773,6 @@ function createVastAdLayer(contentVideo, options) {
1796
1773
  if (debug) console.log("".concat(LOG, " Stopping ad"));
1797
1774
  adPlaying = false;
1798
1775
  setAdPlayingFlag(false);
1799
- restoreContentVideoStyles();
1800
1776
  contentVideo.muted = originalMutedState;
1801
1777
  contentVideo.volume = originalMutedState ? 0 : originalVolume;
1802
1778
  contentVideo.style.visibility = "visible";
@@ -1835,7 +1811,6 @@ function createVastAdLayer(contentVideo, options) {
1835
1811
  destroyed = true;
1836
1812
  adPlaying = false;
1837
1813
  setAdPlayingFlag(false);
1838
- restoreContentVideoStyles();
1839
1814
  contentVideo.muted = originalMutedState;
1840
1815
  contentVideo.volume = originalVolume;
1841
1816
  var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
@@ -6133,7 +6108,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6133
6108
  return StormcloudVideoPlayer;
6134
6109
  }();
6135
6110
  // src/ui/StormcloudVideoPlayer.tsx
6136
- import { FaPlay, FaPause, FaVolumeUp, FaVolumeMute, FaVolumeDown, FaExpand, FaCompress, FaSpinner } from "react-icons/fa";
6111
+ import { FaPlay, FaPause, FaVolumeUp, FaVolumeMute, FaVolumeDown, FaExpand, FaCompress } from "react-icons/fa";
6137
6112
  // src/ui/OverlayRenderer.tsx
6138
6113
  import React, { useEffect, useRef, useState, useCallback } from "react";
6139
6114
  // src/utils/overlays.ts
@@ -7243,6 +7218,7 @@ var CRITICAL_PROPS = [
7243
7218
  "driftToleranceMs"
7244
7219
  ];
7245
7220
  var CONTROLS_HIDE_DELAY = 3e3;
7221
+ var DEFAULT_PLAYER_ASPECT_RATIO = 16 / 9;
7246
7222
  var StormcloudVideoPlayerComponent = React2.memo(function(props) {
7247
7223
  var src = props.src, autoplay = props.autoplay, muted = props.muted, lowLatencyMode = props.lowLatencyMode, allowNativeHls = props.allowNativeHls, driftToleranceMs = props.driftToleranceMs, immediateManifestAds = props.immediateManifestAds, debugAdTiming = props.debugAdTiming, showCustomControls = props.showCustomControls, hideLoadingIndicator = props.hideLoadingIndicator, onVolumeToggle = props.onVolumeToggle, onFullscreenToggle = props.onFullscreenToggle, onControlClick = props.onControlClick, onReady = props.onReady, wrapperClassName = props.wrapperClassName, wrapperStyle = props.wrapperStyle, className = props.className, style = props.style, controls = props.controls, playsInline = props.playsInline, preload = props.preload, poster = props.poster, children = props.children, licenseKey = props.licenseKey, minSegmentsBeforePlay = props.minSegmentsBeforePlay, disableAds = props.disableAds, disableFiller = props.disableFiller, swirlProjectId = props.swirlProjectId, restVideoAttrs = _object_without_properties(props, [
7248
7224
  "src",
@@ -7303,6 +7279,7 @@ var StormcloudVideoPlayerComponent = React2.memo(function(props) {
7303
7279
  var _React2_useState17 = _sliced_to_array(React2.useState(null), 2), overlayCoordSpace = _React2_useState17[0], setOverlayCoordSpace = _React2_useState17[1];
7304
7280
  var _React2_useState18 = _sliced_to_array(React2.useState(typeof window !== "undefined" ? window.innerWidth : 1920), 2), viewportWidth = _React2_useState18[0], setViewportWidth = _React2_useState18[1];
7305
7281
  var _React2_useState19 = _sliced_to_array(React2.useState(typeof window !== "undefined" ? window.innerHeight > window.innerWidth : false), 2), isPortrait = _React2_useState19[0], setIsPortrait = _React2_useState19[1];
7282
+ var _React2_useState20 = _sliced_to_array(React2.useState(DEFAULT_PLAYER_ASPECT_RATIO), 2), playerAspectRatio = _React2_useState20[0], setPlayerAspectRatio = _React2_useState20[1];
7306
7283
  var getResponsiveScale = function getResponsiveScale() {
7307
7284
  if (viewportWidth < 480) return 0.7;
7308
7285
  if (viewportWidth < 768) return 0.8;
@@ -7598,6 +7575,13 @@ var StormcloudVideoPlayerComponent = React2.memo(function(props) {
7598
7575
  }, []);
7599
7576
  useEffect2(function() {
7600
7577
  if (!videoRef.current) return;
7578
+ var handleLoadedMetadata = function handleLoadedMetadata() {
7579
+ var video2 = videoRef.current;
7580
+ if (!video2) return;
7581
+ if (video2.videoWidth > 0 && video2.videoHeight > 0) {
7582
+ setPlayerAspectRatio(video2.videoWidth / video2.videoHeight);
7583
+ }
7584
+ };
7601
7585
  var handleCanPlay = function handleCanPlay() {
7602
7586
  setIsLoading(false);
7603
7587
  if (bufferingTimeoutRef.current) {
@@ -7644,6 +7628,8 @@ var StormcloudVideoPlayerComponent = React2.memo(function(props) {
7644
7628
  setShowCenterPlay(true);
7645
7629
  };
7646
7630
  var video = videoRef.current;
7631
+ handleLoadedMetadata();
7632
+ video.addEventListener("loadedmetadata", handleLoadedMetadata);
7647
7633
  video.addEventListener("canplay", handleCanPlay);
7648
7634
  video.addEventListener("canplaythrough", handleCanPlayThrough);
7649
7635
  video.addEventListener("waiting", handleWaiting);
@@ -7658,6 +7644,7 @@ var StormcloudVideoPlayerComponent = React2.memo(function(props) {
7658
7644
  clearTimeout(bufferingTimeoutRef.current);
7659
7645
  bufferingTimeoutRef.current = null;
7660
7646
  }
7647
+ video.removeEventListener("loadedmetadata", handleLoadedMetadata);
7661
7648
  video.removeEventListener("canplay", handleCanPlay);
7662
7649
  video.removeEventListener("canplaythrough", handleCanPlayThrough);
7663
7650
  video.removeEventListener("waiting", handleWaiting);
@@ -7668,6 +7655,11 @@ var StormcloudVideoPlayerComponent = React2.memo(function(props) {
7668
7655
  }, [
7669
7656
  debugAdTiming
7670
7657
  ]);
7658
+ useEffect2(function() {
7659
+ setPlayerAspectRatio(DEFAULT_PLAYER_ASPECT_RATIO);
7660
+ }, [
7661
+ src
7662
+ ]);
7671
7663
  useEffect2(function() {
7672
7664
  return function() {
7673
7665
  if (controlsTimerRef.current) {
@@ -7693,7 +7685,7 @@ var StormcloudVideoPlayerComponent = React2.memo(function(props) {
7693
7685
  return /* @__PURE__ */ jsxs2(Fragment2, {
7694
7686
  children: [
7695
7687
  /* @__PURE__ */ jsx2("style", {
7696
- children: "\n @keyframes sc-spin {\n from { transform: rotate(0deg); }\n to { transform: rotate(360deg); }\n }\n @keyframes sc-pulse {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.6; }\n }\n @keyframes sc-fade-in {\n from { opacity: 0; transform: translateY(8px); }\n to { opacity: 1; transform: translateY(0); }\n }\n .sc-wrapper:fullscreen,\n .sc-wrapper:has(*:fullscreen) {\n border-radius: 0 !important;\n box-shadow: none !important;\n width: 100vw !important;\n height: 100vh !important;\n max-width: 100vw !important;\n max-height: 100vh !important;\n position: fixed !important;\n top: 0 !important;\n left: 0 !important;\n z-index: 999999 !important;\n background: #000 !important;\n display: flex !important;\n align-items: center !important;\n justify-content: center !important;\n }\n .sc-ctrl-btn {\n background: none;\n border: none;\n color: #fff;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 50%;\n padding: 8px;\n transition: background 0.15s ease, opacity 0.15s ease;\n opacity: 0.9;\n }\n .sc-ctrl-btn:hover {\n opacity: 1;\n background: rgba(255, 255, 255, 0.1);\n }\n .sc-ctrl-btn:active {\n opacity: 0.7;\n }\n .sc-controls-bar {\n transition: opacity 0.35s ease, transform 0.35s ease;\n }\n .sc-progress-track:hover .sc-progress-thumb {\n transform: translate(-50%, -50%) scale(1) !important;\n }\n .sc-loading-hidden .sc-loading-indicator {\n display: none !important;\n }\n "
7688
+ children: "\n @keyframes sc-spin {\n from { transform: rotate(0deg); }\n to { transform: rotate(360deg); }\n }\n @keyframes sc-loading-glow {\n 0%, 100% { opacity: 0.85; transform: scale(1); }\n 50% { opacity: 1; transform: scale(1.05); }\n }\n @keyframes sc-pulse {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.6; }\n }\n @keyframes sc-fade-in {\n from { opacity: 0; transform: translateY(8px); }\n to { opacity: 1; transform: translateY(0); }\n }\n .sc-wrapper:fullscreen,\n .sc-wrapper:has(*:fullscreen) {\n border-radius: 0 !important;\n box-shadow: none !important;\n width: 100vw !important;\n height: 100vh !important;\n max-width: 100vw !important;\n max-height: 100vh !important;\n position: fixed !important;\n top: 0 !important;\n left: 0 !important;\n z-index: 999999 !important;\n background: #000 !important;\n display: flex !important;\n align-items: center !important;\n justify-content: center !important;\n }\n .sc-ctrl-btn {\n background: none;\n border: none;\n color: #fff;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 50%;\n padding: 8px;\n transition: background 0.15s ease, opacity 0.15s ease;\n opacity: 0.9;\n }\n .sc-ctrl-btn:hover {\n opacity: 1;\n background: rgba(255, 255, 255, 0.1);\n }\n .sc-ctrl-btn:active {\n opacity: 0.7;\n }\n .sc-controls-bar {\n transition: opacity 0.35s ease, transform 0.35s ease;\n }\n .sc-progress-track:hover .sc-progress-thumb {\n transform: translate(-50%, -50%) scale(1) !important;\n }\n .sc-loading-hidden .sc-loading-indicator {\n display: none !important;\n }\n "
7697
7689
  }),
7698
7690
  /* @__PURE__ */ jsxs2("div", {
7699
7691
  ref: wrapperRef,
@@ -7711,6 +7703,7 @@ var StormcloudVideoPlayerComponent = React2.memo(function(props) {
7711
7703
  width: isFullscreen ? "100vw" : "100%",
7712
7704
  height: isFullscreen ? "100vh" : "auto",
7713
7705
  minHeight: isFullscreen ? "100vh" : "auto",
7706
+ aspectRatio: isFullscreen ? void 0 : playerAspectRatio,
7714
7707
  maxWidth: isFullscreen ? "100vw" : "100%",
7715
7708
  maxHeight: isFullscreen ? "100vh" : "none",
7716
7709
  zIndex: isFullscreen ? 999999 : void 0,
@@ -7727,7 +7720,7 @@ var StormcloudVideoPlayerComponent = React2.memo(function(props) {
7727
7720
  zIndex: 1,
7728
7721
  display: "block",
7729
7722
  width: "100%",
7730
- height: isFullscreen ? "100%" : "auto",
7723
+ height: "100%",
7731
7724
  maxWidth: "100%",
7732
7725
  maxHeight: isFullscreen ? "100%" : "none",
7733
7726
  objectFit: isFullscreen ? "cover" : "contain",
@@ -7747,18 +7740,44 @@ var StormcloudVideoPlayerComponent = React2.memo(function(props) {
7747
7740
  videoRef: videoRef,
7748
7741
  coordinateSpace: overlayCoordSpace
7749
7742
  }),
7750
- (isLoading || isBuffering) && !hideLoadingIndicator && /* @__PURE__ */ jsx2(FaSpinner, {
7743
+ (isLoading || isBuffering) && !hideLoadingIndicator && /* @__PURE__ */ jsxs2("div", {
7751
7744
  className: "sc-loading-indicator",
7752
- size: 40,
7753
- color: "rgba(255, 255, 255, 0.85)",
7754
7745
  style: {
7755
7746
  position: "absolute",
7756
- top: "calc(50% - 20px)",
7757
- left: "calc(50% - 20px)",
7747
+ top: "50%",
7748
+ left: "50%",
7749
+ transform: "translate(-50%, -50%)",
7758
7750
  zIndex: 20,
7759
- animation: "sc-spin 0.9s linear infinite",
7760
- filter: "drop-shadow(0 2px 8px rgba(0, 0, 0, 0.6))"
7761
- }
7751
+ width: "".concat(Math.max(34, 38 * responsiveScale), "px"),
7752
+ height: "".concat(Math.max(34, 38 * responsiveScale), "px"),
7753
+ display: "flex",
7754
+ alignItems: "center",
7755
+ justifyContent: "center",
7756
+ animation: "sc-loading-glow 1.4s ease-in-out infinite",
7757
+ filter: "drop-shadow(0 6px 14px rgba(0, 0, 0, 0.55))"
7758
+ },
7759
+ children: [
7760
+ /* @__PURE__ */ jsx2("div", {
7761
+ style: {
7762
+ position: "absolute",
7763
+ inset: 0,
7764
+ borderRadius: "50%",
7765
+ border: "3px solid rgba(255, 255, 255, 0.25)",
7766
+ borderTopColor: "#ff0000",
7767
+ borderRightColor: "rgba(255, 255, 255, 0.85)",
7768
+ animation: "sc-spin 0.8s linear infinite"
7769
+ }
7770
+ }),
7771
+ /* @__PURE__ */ jsx2("div", {
7772
+ style: {
7773
+ width: "7px",
7774
+ height: "7px",
7775
+ borderRadius: "50%",
7776
+ background: "#ff0000",
7777
+ boxShadow: "0 0 10px rgba(255, 0, 0, 0.65)"
7778
+ }
7779
+ })
7780
+ ]
7762
7781
  }),
7763
7782
  showLicenseWarning && /* @__PURE__ */ jsxs2("div", {
7764
7783
  style: {
@@ -7994,7 +8013,8 @@ var StormcloudVideoPlayerComponent = React2.memo(function(props) {
7994
8013
  /* @__PURE__ */ jsxs2("div", {
7995
8014
  style: {
7996
8015
  display: "flex",
7997
- alignItems: "center"
8016
+ alignItems: "center",
8017
+ paddingRight: "".concat(6 * responsiveScale, "px")
7998
8018
  },
7999
8019
  onMouseEnter: function onMouseEnter() {
8000
8020
  return setShowVolumeSlider(true);
@@ -8025,13 +8045,13 @@ var StormcloudVideoPlayerComponent = React2.memo(function(props) {
8025
8045
  }),
8026
8046
  /* @__PURE__ */ jsx2("div", {
8027
8047
  style: {
8028
- width: showVolumeSlider ? "".concat(62 * responsiveScale, "px") : "0px",
8048
+ width: showVolumeSlider ? "".concat(68 * responsiveScale, "px") : "0px",
8029
8049
  overflow: "hidden",
8030
8050
  transition: "width 0.2s cubic-bezier(0.4, 0, 0.2, 1)",
8031
8051
  display: "flex",
8032
8052
  alignItems: "center",
8033
- paddingLeft: showVolumeSlider ? "2px" : "0",
8034
- paddingRight: showVolumeSlider ? "4px" : "0"
8053
+ paddingLeft: showVolumeSlider ? "".concat(3 * responsiveScale, "px") : "0",
8054
+ paddingRight: showVolumeSlider ? "".concat(8 * responsiveScale, "px") : "0"
8035
8055
  },
8036
8056
  children: /* @__PURE__ */ jsxs2("div", {
8037
8057
  style: {
@@ -8278,7 +8298,8 @@ var StormcloudVideoPlayerComponent = React2.memo(function(props) {
8278
8298
  alignItems: "center",
8279
8299
  background: "rgba(0, 0, 0, 0.6)",
8280
8300
  borderRadius: "".concat(18 * responsiveScale, "px"),
8281
- padding: "2px"
8301
+ padding: "2px",
8302
+ paddingRight: "".concat(8 * responsiveScale, "px")
8282
8303
  },
8283
8304
  onMouseEnter: function onMouseEnter() {
8284
8305
  return setShowVolumeSlider(true);
@@ -8307,13 +8328,13 @@ var StormcloudVideoPlayerComponent = React2.memo(function(props) {
8307
8328
  }),
8308
8329
  /* @__PURE__ */ jsx2("div", {
8309
8330
  style: {
8310
- width: showVolumeSlider ? "".concat(62 * responsiveScale, "px") : "0px",
8331
+ width: showVolumeSlider ? "".concat(68 * responsiveScale, "px") : "0px",
8311
8332
  overflow: "hidden",
8312
8333
  transition: "width 0.2s cubic-bezier(0.4, 0, 0.2, 1)",
8313
8334
  display: "flex",
8314
8335
  alignItems: "center",
8315
- paddingLeft: showVolumeSlider ? "2px" : "0",
8316
- paddingRight: showVolumeSlider ? "6px" : "0"
8336
+ paddingLeft: showVolumeSlider ? "".concat(3 * responsiveScale, "px") : "0",
8337
+ paddingRight: showVolumeSlider ? "".concat(10 * responsiveScale, "px") : "0"
8317
8338
  },
8318
8339
  children: /* @__PURE__ */ jsxs2("div", {
8319
8340
  style: {