stormcloud-video-player 0.6.6 → 0.6.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/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;
@@ -6093,7 +6068,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6093
6068
  return StormcloudVideoPlayer;
6094
6069
  }();
6095
6070
  // src/ui/StormcloudVideoPlayer.tsx
6096
- import { FaPlay, FaPause, FaVolumeUp, FaVolumeMute, FaVolumeDown, FaExpand, FaCompress, FaSpinner } from "react-icons/fa";
6071
+ import { FaPlay, FaPause, FaVolumeUp, FaVolumeMute, FaVolumeDown, FaExpand, FaCompress } from "react-icons/fa";
6097
6072
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
6098
6073
  var CRITICAL_PROPS = [
6099
6074
  "src",
@@ -6103,6 +6078,7 @@ var CRITICAL_PROPS = [
6103
6078
  "driftToleranceMs"
6104
6079
  ];
6105
6080
  var CONTROLS_HIDE_DELAY = 3e3;
6081
+ var DEFAULT_PLAYER_ASPECT_RATIO = 16 / 9;
6106
6082
  var StormcloudVideoPlayerComponent = React.memo(function(props) {
6107
6083
  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, restVideoAttrs = _object_without_properties(props, [
6108
6084
  "src",
@@ -6160,6 +6136,7 @@ var StormcloudVideoPlayerComponent = React.memo(function(props) {
6160
6136
  var _React_useState15 = _sliced_to_array(React.useState(true), 2), controlsVisible = _React_useState15[0], setControlsVisible = _React_useState15[1];
6161
6137
  var _React_useState16 = _sliced_to_array(React.useState(typeof window !== "undefined" ? window.innerWidth : 1920), 2), viewportWidth = _React_useState16[0], setViewportWidth = _React_useState16[1];
6162
6138
  var _React_useState17 = _sliced_to_array(React.useState(typeof window !== "undefined" ? window.innerHeight > window.innerWidth : false), 2), isPortrait = _React_useState17[0], setIsPortrait = _React_useState17[1];
6139
+ var _React_useState18 = _sliced_to_array(React.useState(DEFAULT_PLAYER_ASPECT_RATIO), 2), playerAspectRatio = _React_useState18[0], setPlayerAspectRatio = _React_useState18[1];
6163
6140
  var getResponsiveScale = function getResponsiveScale() {
6164
6141
  if (viewportWidth < 480) return 0.7;
6165
6142
  if (viewportWidth < 768) return 0.8;
@@ -6401,6 +6378,13 @@ var StormcloudVideoPlayerComponent = React.memo(function(props) {
6401
6378
  }, []);
6402
6379
  useEffect(function() {
6403
6380
  if (!videoRef.current) return;
6381
+ var handleLoadedMetadata = function handleLoadedMetadata() {
6382
+ var video2 = videoRef.current;
6383
+ if (!video2) return;
6384
+ if (video2.videoWidth > 0 && video2.videoHeight > 0) {
6385
+ setPlayerAspectRatio(video2.videoWidth / video2.videoHeight);
6386
+ }
6387
+ };
6404
6388
  var handleCanPlay = function handleCanPlay() {
6405
6389
  setIsLoading(false);
6406
6390
  if (bufferingTimeoutRef.current) {
@@ -6447,6 +6431,8 @@ var StormcloudVideoPlayerComponent = React.memo(function(props) {
6447
6431
  setShowCenterPlay(true);
6448
6432
  };
6449
6433
  var video = videoRef.current;
6434
+ handleLoadedMetadata();
6435
+ video.addEventListener("loadedmetadata", handleLoadedMetadata);
6450
6436
  video.addEventListener("canplay", handleCanPlay);
6451
6437
  video.addEventListener("canplaythrough", handleCanPlayThrough);
6452
6438
  video.addEventListener("waiting", handleWaiting);
@@ -6461,6 +6447,7 @@ var StormcloudVideoPlayerComponent = React.memo(function(props) {
6461
6447
  clearTimeout(bufferingTimeoutRef.current);
6462
6448
  bufferingTimeoutRef.current = null;
6463
6449
  }
6450
+ video.removeEventListener("loadedmetadata", handleLoadedMetadata);
6464
6451
  video.removeEventListener("canplay", handleCanPlay);
6465
6452
  video.removeEventListener("canplaythrough", handleCanPlayThrough);
6466
6453
  video.removeEventListener("waiting", handleWaiting);
@@ -6471,6 +6458,11 @@ var StormcloudVideoPlayerComponent = React.memo(function(props) {
6471
6458
  }, [
6472
6459
  debugAdTiming
6473
6460
  ]);
6461
+ useEffect(function() {
6462
+ setPlayerAspectRatio(DEFAULT_PLAYER_ASPECT_RATIO);
6463
+ }, [
6464
+ src
6465
+ ]);
6474
6466
  useEffect(function() {
6475
6467
  return function() {
6476
6468
  if (controlsTimerRef.current) {
@@ -6496,7 +6488,7 @@ var StormcloudVideoPlayerComponent = React.memo(function(props) {
6496
6488
  return /* @__PURE__ */ jsxs(Fragment, {
6497
6489
  children: [
6498
6490
  /* @__PURE__ */ jsx("style", {
6499
- 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 "
6491
+ 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 "
6500
6492
  }),
6501
6493
  /* @__PURE__ */ jsxs("div", {
6502
6494
  ref: wrapperRef,
@@ -6514,6 +6506,7 @@ var StormcloudVideoPlayerComponent = React.memo(function(props) {
6514
6506
  width: isFullscreen ? "100vw" : "100%",
6515
6507
  height: isFullscreen ? "100vh" : "auto",
6516
6508
  minHeight: isFullscreen ? "100vh" : "auto",
6509
+ aspectRatio: isFullscreen ? void 0 : playerAspectRatio,
6517
6510
  maxWidth: isFullscreen ? "100vw" : "100%",
6518
6511
  maxHeight: isFullscreen ? "100vh" : "none",
6519
6512
  zIndex: isFullscreen ? 999999 : void 0,
@@ -6528,7 +6521,7 @@ var StormcloudVideoPlayerComponent = React.memo(function(props) {
6528
6521
  style: _object_spread({
6529
6522
  display: "block",
6530
6523
  width: "100%",
6531
- height: isFullscreen ? "100%" : "auto",
6524
+ height: "100%",
6532
6525
  maxWidth: "100%",
6533
6526
  maxHeight: isFullscreen ? "100%" : "none",
6534
6527
  objectFit: isFullscreen ? "cover" : "contain",
@@ -6542,18 +6535,44 @@ var StormcloudVideoPlayerComponent = React.memo(function(props) {
6542
6535
  }, restVideoAttrs), {
6543
6536
  children: children
6544
6537
  })),
6545
- (isLoading || isBuffering) && !hideLoadingIndicator && /* @__PURE__ */ jsx(FaSpinner, {
6538
+ (isLoading || isBuffering) && !hideLoadingIndicator && /* @__PURE__ */ jsxs("div", {
6546
6539
  className: "sc-loading-indicator",
6547
- size: 40,
6548
- color: "rgba(255, 255, 255, 0.85)",
6549
6540
  style: {
6550
6541
  position: "absolute",
6551
- top: "calc(50% - 20px)",
6552
- left: "calc(50% - 20px)",
6542
+ top: "50%",
6543
+ left: "50%",
6544
+ transform: "translate(-50%, -50%)",
6553
6545
  zIndex: 20,
6554
- animation: "sc-spin 0.9s linear infinite",
6555
- filter: "drop-shadow(0 2px 8px rgba(0, 0, 0, 0.6))"
6556
- }
6546
+ width: "".concat(Math.max(34, 38 * responsiveScale), "px"),
6547
+ height: "".concat(Math.max(34, 38 * responsiveScale), "px"),
6548
+ display: "flex",
6549
+ alignItems: "center",
6550
+ justifyContent: "center",
6551
+ animation: "sc-loading-glow 1.4s ease-in-out infinite",
6552
+ filter: "drop-shadow(0 6px 14px rgba(0, 0, 0, 0.55))"
6553
+ },
6554
+ children: [
6555
+ /* @__PURE__ */ jsx("div", {
6556
+ style: {
6557
+ position: "absolute",
6558
+ inset: 0,
6559
+ borderRadius: "50%",
6560
+ border: "3px solid rgba(255, 255, 255, 0.25)",
6561
+ borderTopColor: "#ff0000",
6562
+ borderRightColor: "rgba(255, 255, 255, 0.85)",
6563
+ animation: "sc-spin 0.8s linear infinite"
6564
+ }
6565
+ }),
6566
+ /* @__PURE__ */ jsx("div", {
6567
+ style: {
6568
+ width: "7px",
6569
+ height: "7px",
6570
+ borderRadius: "50%",
6571
+ background: "#ff0000",
6572
+ boxShadow: "0 0 10px rgba(255, 0, 0, 0.65)"
6573
+ }
6574
+ })
6575
+ ]
6557
6576
  }),
6558
6577
  showLicenseWarning && /* @__PURE__ */ jsxs("div", {
6559
6578
  style: {
@@ -6789,7 +6808,8 @@ var StormcloudVideoPlayerComponent = React.memo(function(props) {
6789
6808
  /* @__PURE__ */ jsxs("div", {
6790
6809
  style: {
6791
6810
  display: "flex",
6792
- alignItems: "center"
6811
+ alignItems: "center",
6812
+ paddingRight: "".concat(6 * responsiveScale, "px")
6793
6813
  },
6794
6814
  onMouseEnter: function onMouseEnter() {
6795
6815
  return setShowVolumeSlider(true);
@@ -6820,13 +6840,13 @@ var StormcloudVideoPlayerComponent = React.memo(function(props) {
6820
6840
  }),
6821
6841
  /* @__PURE__ */ jsx("div", {
6822
6842
  style: {
6823
- width: showVolumeSlider ? "".concat(62 * responsiveScale, "px") : "0px",
6843
+ width: showVolumeSlider ? "".concat(68 * responsiveScale, "px") : "0px",
6824
6844
  overflow: "hidden",
6825
6845
  transition: "width 0.2s cubic-bezier(0.4, 0, 0.2, 1)",
6826
6846
  display: "flex",
6827
6847
  alignItems: "center",
6828
- paddingLeft: showVolumeSlider ? "2px" : "0",
6829
- paddingRight: showVolumeSlider ? "4px" : "0"
6848
+ paddingLeft: showVolumeSlider ? "".concat(3 * responsiveScale, "px") : "0",
6849
+ paddingRight: showVolumeSlider ? "".concat(8 * responsiveScale, "px") : "0"
6830
6850
  },
6831
6851
  children: /* @__PURE__ */ jsxs("div", {
6832
6852
  style: {
@@ -7073,7 +7093,8 @@ var StormcloudVideoPlayerComponent = React.memo(function(props) {
7073
7093
  alignItems: "center",
7074
7094
  background: "rgba(0, 0, 0, 0.6)",
7075
7095
  borderRadius: "".concat(18 * responsiveScale, "px"),
7076
- padding: "2px"
7096
+ padding: "2px",
7097
+ paddingRight: "".concat(8 * responsiveScale, "px")
7077
7098
  },
7078
7099
  onMouseEnter: function onMouseEnter() {
7079
7100
  return setShowVolumeSlider(true);
@@ -7102,13 +7123,13 @@ var StormcloudVideoPlayerComponent = React.memo(function(props) {
7102
7123
  }),
7103
7124
  /* @__PURE__ */ jsx("div", {
7104
7125
  style: {
7105
- width: showVolumeSlider ? "".concat(62 * responsiveScale, "px") : "0px",
7126
+ width: showVolumeSlider ? "".concat(68 * responsiveScale, "px") : "0px",
7106
7127
  overflow: "hidden",
7107
7128
  transition: "width 0.2s cubic-bezier(0.4, 0, 0.2, 1)",
7108
7129
  display: "flex",
7109
7130
  alignItems: "center",
7110
- paddingLeft: showVolumeSlider ? "2px" : "0",
7111
- paddingRight: showVolumeSlider ? "6px" : "0"
7131
+ paddingLeft: showVolumeSlider ? "".concat(3 * responsiveScale, "px") : "0",
7132
+ paddingRight: showVolumeSlider ? "".concat(10 * responsiveScale, "px") : "0"
7112
7133
  },
7113
7134
  children: /* @__PURE__ */ jsxs("div", {
7114
7135
  style: {