stormcloud-video-player 0.1.7 → 0.1.9

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
@@ -80,6 +80,9 @@ function createImaController(video) {
80
80
  container.style.top = "0";
81
81
  container.style.right = "0";
82
82
  container.style.bottom = "0";
83
+ container.style.display = "flex";
84
+ container.style.alignItems = "center";
85
+ container.style.justifyContent = "center";
83
86
  container.style.pointerEvents = "none";
84
87
  container.style.zIndex = "2";
85
88
  video.parentElement?.appendChild(container);
@@ -122,6 +125,9 @@ function createImaController(video) {
122
125
  container.style.top = "0";
123
126
  container.style.right = "0";
124
127
  container.style.bottom = "0";
128
+ container.style.display = "flex";
129
+ container.style.alignItems = "center";
130
+ container.style.justifyContent = "center";
125
131
  container.style.pointerEvents = "none";
126
132
  container.style.zIndex = "2";
127
133
  if (!video.parentElement) {
@@ -328,6 +334,20 @@ function createImaController(video) {
328
334
  isAdPlaying() {
329
335
  return adPlaying;
330
336
  },
337
+ resize(width, height) {
338
+ if (!adsManager || !window.google?.ima) {
339
+ console.warn(
340
+ "[IMA] Cannot resize: No ads manager or IMA SDK available"
341
+ );
342
+ return;
343
+ }
344
+ try {
345
+ console.log(`[IMA] Resizing ads manager to ${width}x${height}`);
346
+ adsManager.resize(width, height, window.google.ima.ViewMode.NORMAL);
347
+ } catch (error) {
348
+ console.warn("[IMA] Error resizing ads manager:", error);
349
+ }
350
+ },
331
351
  on(event, listener) {
332
352
  if (!listeners.has(event)) listeners.set(event, /* @__PURE__ */ new Set());
333
353
  listeners.get(event).add(listener);
@@ -498,7 +518,9 @@ async function sendInitialTracking(licenseKey) {
498
518
  browserId,
499
519
  ...clientInfo
500
520
  };
501
- const headers = { "Content-Type": "application/json" };
521
+ const headers = {
522
+ "Content-Type": "application/json"
523
+ };
502
524
  if (licenseKey) {
503
525
  headers["Authorization"] = `Bearer ${licenseKey}`;
504
526
  }
@@ -513,11 +535,7 @@ async function sendInitialTracking(licenseKey) {
513
535
  if (!response.ok) {
514
536
  throw new Error(`HTTP error! status: ${response.status}`);
515
537
  }
516
- const data = await response.json();
517
- console.log(
518
- "[StormcloudVideoPlayer] Initial tracking data sent successfully:",
519
- data
520
- );
538
+ await response.json();
521
539
  } catch (error) {
522
540
  console.error(
523
541
  "[StormcloudVideoPlayer] Error sending initial tracking data:",
@@ -533,7 +551,9 @@ async function sendHeartbeat(licenseKey) {
533
551
  browserId,
534
552
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
535
553
  };
536
- const headers = { "Content-Type": "application/json" };
554
+ const headers = {
555
+ "Content-Type": "application/json"
556
+ };
537
557
  if (licenseKey) {
538
558
  headers["Authorization"] = `Bearer ${licenseKey}`;
539
559
  }
@@ -548,8 +568,7 @@ async function sendHeartbeat(licenseKey) {
548
568
  if (!response.ok) {
549
569
  throw new Error(`HTTP error! status: ${response.status}`);
550
570
  }
551
- const data = await response.json();
552
- console.log("[StormcloudVideoPlayer] Heartbeat sent successfully:", data);
571
+ await response.json();
553
572
  } catch (error) {
554
573
  console.error("[StormcloudVideoPlayer] Error sending heartbeat:", error);
555
574
  }
@@ -568,7 +587,6 @@ var StormcloudVideoPlayer = class {
568
587
  this.showAds = false;
569
588
  this.config = config;
570
589
  this.video = config.videoElement;
571
- this.adSchedule = config.adSchedule;
572
590
  this.ima = createImaController(this.video);
573
591
  }
574
592
  async load() {
@@ -874,70 +892,61 @@ var StormcloudVideoPlayer = class {
874
892
  const durationMs = marker.durationSeconds != null ? marker.durationSeconds * 1e3 : void 0;
875
893
  this.expectedAdBreakDurationMs = durationMs;
876
894
  this.currentAdBreakStartWallClockMs = Date.now();
877
- const policy = this.adSchedule?.lateJoinPolicy ?? "play_remaining";
878
- if (policy !== "skip_to_content") {
879
- const isManifestMarker = this.isManifestBasedMarker(marker);
880
- const forceImmediate = this.config.immediateManifestAds ?? true;
895
+ const isManifestMarker = this.isManifestBasedMarker(marker);
896
+ const forceImmediate = this.config.immediateManifestAds ?? true;
897
+ if (this.config.debugAdTiming) {
898
+ console.log("[StormcloudVideoPlayer] Ad start decision:", {
899
+ isManifestMarker,
900
+ forceImmediate,
901
+ hasPts: typeof marker.ptsSeconds === "number"
902
+ });
903
+ }
904
+ if (isManifestMarker && forceImmediate) {
881
905
  if (this.config.debugAdTiming) {
882
- console.log("[StormcloudVideoPlayer] Ad start decision:", {
883
- isManifestMarker,
884
- forceImmediate,
885
- hasPts: typeof marker.ptsSeconds === "number",
886
- policy
906
+ console.log(
907
+ "[StormcloudVideoPlayer] Starting ad immediately (manifest-based)"
908
+ );
909
+ }
910
+ this.clearAdStartTimer();
911
+ this.handleAdStart(marker);
912
+ } else if (typeof marker.ptsSeconds === "number") {
913
+ const tol = this.config.driftToleranceMs ?? 1e3;
914
+ const nowMs = this.video.currentTime * 1e3;
915
+ const estCurrentPtsMs = nowMs - this.ptsDriftEmaMs;
916
+ const deltaMs = Math.floor(marker.ptsSeconds * 1e3 - estCurrentPtsMs);
917
+ if (this.config.debugAdTiming) {
918
+ console.log("[StormcloudVideoPlayer] PTS-based timing calculation:", {
919
+ nowMs,
920
+ estCurrentPtsMs,
921
+ markerPtsMs: marker.ptsSeconds * 1e3,
922
+ deltaMs,
923
+ tolerance: tol
887
924
  });
888
925
  }
889
- if (isManifestMarker && forceImmediate) {
890
- if (this.config.debugAdTiming) {
891
- console.log(
892
- "[StormcloudVideoPlayer] Starting ad immediately (manifest-based)"
893
- );
894
- }
895
- this.clearAdStartTimer();
896
- this.handleAdStart(marker);
897
- } else if (typeof marker.ptsSeconds === "number") {
898
- const tol = this.config.driftToleranceMs ?? 1e3;
899
- const nowMs = this.video.currentTime * 1e3;
900
- const estCurrentPtsMs = nowMs - this.ptsDriftEmaMs;
901
- const deltaMs = Math.floor(
902
- marker.ptsSeconds * 1e3 - estCurrentPtsMs
903
- );
926
+ if (deltaMs > tol) {
904
927
  if (this.config.debugAdTiming) {
905
928
  console.log(
906
- "[StormcloudVideoPlayer] PTS-based timing calculation:",
907
- {
908
- nowMs,
909
- estCurrentPtsMs,
910
- markerPtsMs: marker.ptsSeconds * 1e3,
911
- deltaMs,
912
- tolerance: tol
913
- }
929
+ `[StormcloudVideoPlayer] Scheduling ad start in ${deltaMs}ms`
914
930
  );
915
931
  }
916
- if (deltaMs > tol) {
917
- if (this.config.debugAdTiming) {
918
- console.log(
919
- `[StormcloudVideoPlayer] Scheduling ad start in ${deltaMs}ms`
920
- );
921
- }
922
- this.scheduleAdStartIn(deltaMs);
923
- } else {
924
- if (this.config.debugAdTiming) {
925
- console.log(
926
- "[StormcloudVideoPlayer] Starting ad immediately (within tolerance)"
927
- );
928
- }
929
- this.clearAdStartTimer();
930
- this.handleAdStart(marker);
931
- }
932
+ this.scheduleAdStartIn(deltaMs);
932
933
  } else {
933
934
  if (this.config.debugAdTiming) {
934
935
  console.log(
935
- "[StormcloudVideoPlayer] Starting ad immediately (fallback)"
936
+ "[StormcloudVideoPlayer] Starting ad immediately (within tolerance)"
936
937
  );
937
938
  }
938
939
  this.clearAdStartTimer();
939
940
  this.handleAdStart(marker);
940
941
  }
942
+ } else {
943
+ if (this.config.debugAdTiming) {
944
+ console.log(
945
+ "[StormcloudVideoPlayer] Starting ad immediately (fallback)"
946
+ );
947
+ }
948
+ this.clearAdStartTimer();
949
+ this.handleAdStart(marker);
941
950
  }
942
951
  if (this.expectedAdBreakDurationMs != null) {
943
952
  this.scheduleAdStopCountdown(this.expectedAdBreakDurationMs);
@@ -957,12 +966,11 @@ var StormcloudVideoPlayer = class {
957
966
  this.scheduleAdStopCountdown(remainingMs);
958
967
  }
959
968
  if (!this.ima.isAdPlaying()) {
960
- const policy = this.adSchedule?.lateJoinPolicy ?? "play_remaining";
961
969
  const scheduled = this.findCurrentOrNextBreak(
962
970
  this.video.currentTime * 1e3
963
971
  );
964
972
  const tags = this.selectVastTagsForBreak(scheduled) || (this.apiVastTagUrl ? [this.apiVastTagUrl] : void 0);
965
- if (policy === "play_remaining" && tags && tags.length > 0) {
973
+ if (tags && tags.length > 0) {
966
974
  const first = tags[0];
967
975
  const rest = tags.slice(1);
968
976
  this.adPodQueue = rest;
@@ -1161,11 +1169,11 @@ var StormcloudVideoPlayer = class {
1161
1169
  });
1162
1170
  this.heartbeatInterval = window.setInterval(() => {
1163
1171
  this.sendHeartbeatIfNeeded();
1164
- }, 1e3);
1172
+ }, 5e3);
1165
1173
  }
1166
1174
  sendHeartbeatIfNeeded() {
1167
1175
  const now = Date.now();
1168
- if (!this.lastHeartbeatTime || now - this.lastHeartbeatTime > 1e4) {
1176
+ if (!this.lastHeartbeatTime || now - this.lastHeartbeatTime > 3e4) {
1169
1177
  this.lastHeartbeatTime = now;
1170
1178
  sendHeartbeat(this.config.licenseKey).catch((error) => {
1171
1179
  if (this.config.debugAdTiming) {
@@ -1212,9 +1220,6 @@ var StormcloudVideoPlayer = class {
1212
1220
  });
1213
1221
  }
1214
1222
  }
1215
- setAdSchedule(schedule) {
1216
- this.adSchedule = schedule;
1217
- }
1218
1223
  getCurrentAdIndex() {
1219
1224
  return this.currentAdIndex;
1220
1225
  }
@@ -1237,17 +1242,11 @@ var StormcloudVideoPlayer = class {
1237
1242
  shouldShowNativeControls() {
1238
1243
  return this.getStreamType() !== "hls";
1239
1244
  }
1240
- async loadAdScheduleFromUrl(url) {
1241
- const res = await fetch(url);
1242
- if (!res.ok) throw new Error(`Failed to fetch ad schedule: ${res.status}`);
1243
- const data = await res.json();
1244
- this.adSchedule = data;
1245
- }
1246
- async loadDefaultVastFromAiry(airyApiUrl, params) {
1245
+ async loadDefaultVastFromAdstorm(adstormApiUrl, params) {
1247
1246
  const usp = new URLSearchParams(params || {});
1248
- const url = `${airyApiUrl}?${usp.toString()}`;
1247
+ const url = `${adstormApiUrl}?${usp.toString()}`;
1249
1248
  const res = await fetch(url);
1250
- if (!res.ok) throw new Error(`Failed to fetch Airy ads: ${res.status}`);
1249
+ if (!res.ok) throw new Error(`Failed to fetch adstorm ads: ${res.status}`);
1251
1250
  const data = await res.json();
1252
1251
  const tag = data?.adTagUrl || data?.vastTagUrl || data?.tagUrl;
1253
1252
  if (typeof tag === "string" && tag.length > 0) {
@@ -1310,7 +1309,7 @@ var StormcloudVideoPlayer = class {
1310
1309
  }
1311
1310
  }
1312
1311
  findCurrentOrNextBreak(nowMs) {
1313
- const schedule = this.adSchedule?.breaks || [];
1312
+ const schedule = [];
1314
1313
  let candidate;
1315
1314
  for (const b of schedule) {
1316
1315
  const tol = this.config.driftToleranceMs ?? 1e3;
@@ -1321,7 +1320,7 @@ var StormcloudVideoPlayer = class {
1321
1320
  return candidate;
1322
1321
  }
1323
1322
  onTimeUpdate(currentTimeSec) {
1324
- if (!this.adSchedule || this.ima.isAdPlaying()) return;
1323
+ if (this.ima.isAdPlaying()) return;
1325
1324
  const nowMs = currentTimeSec * 1e3;
1326
1325
  const breakToPlay = this.findBreakForTime(nowMs);
1327
1326
  if (breakToPlay) {
@@ -1333,10 +1332,8 @@ var StormcloudVideoPlayer = class {
1333
1332
  const endMs = adBreak.startTimeMs + durationMs;
1334
1333
  if (durationMs > 0 && nowMs > adBreak.startTimeMs && nowMs < endMs) {
1335
1334
  const remainingMs = endMs - nowMs;
1336
- const policy = this.adSchedule?.lateJoinPolicy ?? "play_remaining";
1337
- if (policy === "skip_to_content") return;
1338
1335
  const tags = this.selectVastTagsForBreak(adBreak) || (this.apiVastTagUrl ? [this.apiVastTagUrl] : void 0);
1339
- if (policy === "play_remaining" && tags && tags.length > 0) {
1336
+ if (tags && tags.length > 0) {
1340
1337
  const first = tags[0];
1341
1338
  const rest = tags.slice(1);
1342
1339
  this.adPodQueue = rest;
@@ -1484,7 +1481,7 @@ var StormcloudVideoPlayer = class {
1484
1481
  return Math.max(0, this.expectedAdBreakDurationMs - elapsed);
1485
1482
  }
1486
1483
  findBreakForTime(nowMs) {
1487
- const schedule = this.adSchedule?.breaks || [];
1484
+ const schedule = [];
1488
1485
  for (const b of schedule) {
1489
1486
  const end = (b.startTimeMs || 0) + (b.durationMs || 0);
1490
1487
  if (nowMs >= (b.startTimeMs || 0) && (b.durationMs ? nowMs < end : true)) {
@@ -1493,6 +1490,73 @@ var StormcloudVideoPlayer = class {
1493
1490
  }
1494
1491
  return void 0;
1495
1492
  }
1493
+ toggleMute() {
1494
+ this.video.muted = !this.video.muted;
1495
+ if (this.config.debugAdTiming) {
1496
+ console.log("[StormcloudVideoPlayer] Muted:", this.video.muted);
1497
+ }
1498
+ }
1499
+ toggleFullscreen() {
1500
+ return new Promise((resolve, reject) => {
1501
+ if (!document.fullscreenElement) {
1502
+ const container = this.video.parentElement;
1503
+ if (!container) {
1504
+ reject(new Error("No parent container found for fullscreen"));
1505
+ return;
1506
+ }
1507
+ container.requestFullscreen().then(() => {
1508
+ if (this.config.debugAdTiming) {
1509
+ console.log("[StormcloudVideoPlayer] Entered fullscreen");
1510
+ }
1511
+ resolve();
1512
+ }).catch((err) => {
1513
+ if (this.config.debugAdTiming) {
1514
+ console.error("[StormcloudVideoPlayer] Fullscreen error:", err);
1515
+ }
1516
+ reject(err);
1517
+ });
1518
+ } else {
1519
+ document.exitFullscreen().then(() => {
1520
+ if (this.config.debugAdTiming) {
1521
+ console.log("[StormcloudVideoPlayer] Exited fullscreen");
1522
+ }
1523
+ resolve();
1524
+ }).catch((err) => {
1525
+ if (this.config.debugAdTiming) {
1526
+ console.error(
1527
+ "[StormcloudVideoPlayer] Exit fullscreen error:",
1528
+ err
1529
+ );
1530
+ }
1531
+ reject(err);
1532
+ });
1533
+ }
1534
+ });
1535
+ }
1536
+ isMuted() {
1537
+ return this.video.muted;
1538
+ }
1539
+ isFullscreen() {
1540
+ return !!document.fullscreenElement;
1541
+ }
1542
+ get videoElement() {
1543
+ return this.video;
1544
+ }
1545
+ resize() {
1546
+ if (this.config.debugAdTiming) {
1547
+ console.log("[StormcloudVideoPlayer] Resizing player");
1548
+ }
1549
+ if (this.ima && this.ima.isAdPlaying()) {
1550
+ const width = this.video.clientWidth || 640;
1551
+ const height = this.video.clientHeight || 360;
1552
+ if (this.config.debugAdTiming) {
1553
+ console.log(
1554
+ `[StormcloudVideoPlayer] Resizing ads manager to ${width}x${height}`
1555
+ );
1556
+ }
1557
+ this.ima.resize(width, height);
1558
+ }
1559
+ }
1496
1560
  destroy() {
1497
1561
  this.clearAdStartTimer();
1498
1562
  this.clearAdStopTimer();
@@ -1507,240 +1571,588 @@ var StormcloudVideoPlayer = class {
1507
1571
  };
1508
1572
 
1509
1573
  // src/ui/StormcloudVideoPlayer.tsx
1510
- import React, { useEffect, useRef } from "react";
1574
+ import React, { useEffect, useRef, useMemo } from "react";
1511
1575
  import { jsx, jsxs } from "react/jsx-runtime";
1512
- var StormcloudVideoPlayerComponent = (props) => {
1513
- const {
1514
- src,
1515
- autoplay,
1516
- muted,
1517
- lowLatencyMode,
1518
- allowNativeHls,
1519
- driftToleranceMs,
1520
- adSchedule,
1521
- immediateManifestAds,
1522
- debugAdTiming,
1523
- showCustomControls,
1524
- onVolumeToggle,
1525
- onFullscreenToggle,
1526
- onControlClick,
1527
- onReady,
1528
- wrapperClassName,
1529
- wrapperStyle,
1530
- className,
1531
- style,
1532
- controls,
1533
- playsInline,
1534
- preload,
1535
- poster,
1536
- children,
1537
- licenseKey,
1538
- ...restVideoAttrs
1539
- } = props;
1540
- const videoRef = useRef(null);
1541
- const playerRef = useRef(null);
1542
- const [adStatus, setAdStatus] = React.useState({ showAds: false, currentIndex: 0, totalAds: 0 });
1543
- const [shouldShowNativeControls, setShouldShowNativeControls] = React.useState(true);
1544
- useEffect(() => {
1545
- if (typeof window === "undefined") return;
1546
- const el = videoRef.current;
1547
- if (!el || !src) return;
1548
- if (playerRef.current) {
1549
- try {
1550
- playerRef.current.destroy();
1551
- } catch {
1552
- }
1553
- playerRef.current = null;
1554
- }
1555
- const cfg = {
1576
+ var CRITICAL_PROPS = [
1577
+ "src",
1578
+ "allowNativeHls",
1579
+ "licenseKey",
1580
+ "lowLatencyMode",
1581
+ "driftToleranceMs"
1582
+ ];
1583
+ var StormcloudVideoPlayerComponent = React.memo(
1584
+ (props) => {
1585
+ const {
1556
1586
  src,
1557
- videoElement: el
1558
- };
1559
- if (autoplay !== void 0) cfg.autoplay = autoplay;
1560
- if (muted !== void 0) cfg.muted = muted;
1561
- if (lowLatencyMode !== void 0) cfg.lowLatencyMode = lowLatencyMode;
1562
- if (allowNativeHls !== void 0) cfg.allowNativeHls = allowNativeHls;
1563
- if (driftToleranceMs !== void 0) cfg.driftToleranceMs = driftToleranceMs;
1564
- if (adSchedule !== void 0) cfg.adSchedule = adSchedule;
1565
- if (immediateManifestAds !== void 0)
1566
- cfg.immediateManifestAds = immediateManifestAds;
1567
- if (debugAdTiming !== void 0) cfg.debugAdTiming = debugAdTiming;
1568
- if (showCustomControls !== void 0)
1569
- cfg.showCustomControls = showCustomControls;
1570
- if (onVolumeToggle !== void 0) cfg.onVolumeToggle = onVolumeToggle;
1571
- if (onFullscreenToggle !== void 0)
1572
- cfg.onFullscreenToggle = onFullscreenToggle;
1573
- if (onControlClick !== void 0) cfg.onControlClick = onControlClick;
1574
- if (licenseKey !== void 0) cfg.licenseKey = licenseKey;
1575
- const player = new StormcloudVideoPlayer(cfg);
1576
- playerRef.current = player;
1577
- player.load().then(() => {
1578
- const showNative = player.shouldShowNativeControls();
1579
- setShouldShowNativeControls(showNative);
1580
- onReady?.(player);
1581
- }).catch(() => {
1582
- });
1583
- return () => {
1584
- try {
1585
- player.destroy();
1586
- } catch {
1587
+ autoplay,
1588
+ muted,
1589
+ lowLatencyMode,
1590
+ allowNativeHls,
1591
+ driftToleranceMs,
1592
+ immediateManifestAds,
1593
+ debugAdTiming,
1594
+ showCustomControls,
1595
+ onVolumeToggle,
1596
+ onFullscreenToggle,
1597
+ onControlClick,
1598
+ onReady,
1599
+ wrapperClassName,
1600
+ wrapperStyle,
1601
+ className,
1602
+ style,
1603
+ controls,
1604
+ playsInline,
1605
+ preload,
1606
+ poster,
1607
+ children,
1608
+ licenseKey,
1609
+ ...restVideoAttrs
1610
+ } = props;
1611
+ const videoRef = useRef(null);
1612
+ const playerRef = useRef(null);
1613
+ const [adStatus, setAdStatus] = React.useState({ showAds: false, currentIndex: 0, totalAds: 0 });
1614
+ const [shouldShowNativeControls, setShouldShowNativeControls] = React.useState(true);
1615
+ const [isMuted, setIsMuted] = React.useState(false);
1616
+ const [isFullscreen, setIsFullscreen] = React.useState(false);
1617
+ const criticalPropsKey = useMemo(() => {
1618
+ return CRITICAL_PROPS.map((prop) => `${prop}:${props[prop]}`).join("|");
1619
+ }, [src, allowNativeHls, licenseKey, lowLatencyMode, driftToleranceMs]);
1620
+ useEffect(() => {
1621
+ if (typeof window === "undefined") return;
1622
+ const el = videoRef.current;
1623
+ if (!el || !src) return;
1624
+ if (playerRef.current) {
1625
+ try {
1626
+ playerRef.current.destroy();
1627
+ } catch {
1628
+ }
1629
+ playerRef.current = null;
1587
1630
  }
1588
- playerRef.current = null;
1589
- };
1590
- }, [
1591
- src,
1592
- autoplay,
1593
- muted,
1594
- lowLatencyMode,
1595
- allowNativeHls,
1596
- driftToleranceMs,
1597
- immediateManifestAds,
1598
- debugAdTiming,
1599
- showCustomControls,
1600
- onVolumeToggle,
1601
- onFullscreenToggle,
1602
- onControlClick,
1603
- onReady,
1604
- licenseKey
1605
- ]);
1606
- useEffect(() => {
1607
- if (!playerRef.current) return;
1608
- if (adSchedule) {
1631
+ const cfg = {
1632
+ src,
1633
+ videoElement: el
1634
+ };
1635
+ if (autoplay !== void 0) cfg.autoplay = autoplay;
1636
+ if (muted !== void 0) cfg.muted = muted;
1637
+ if (lowLatencyMode !== void 0) cfg.lowLatencyMode = lowLatencyMode;
1638
+ if (allowNativeHls !== void 0) cfg.allowNativeHls = allowNativeHls;
1639
+ if (driftToleranceMs !== void 0)
1640
+ cfg.driftToleranceMs = driftToleranceMs;
1641
+ if (immediateManifestAds !== void 0)
1642
+ cfg.immediateManifestAds = immediateManifestAds;
1643
+ if (debugAdTiming !== void 0) cfg.debugAdTiming = debugAdTiming;
1644
+ if (showCustomControls !== void 0)
1645
+ cfg.showCustomControls = showCustomControls;
1646
+ if (onVolumeToggle !== void 0) cfg.onVolumeToggle = onVolumeToggle;
1647
+ if (onFullscreenToggle !== void 0)
1648
+ cfg.onFullscreenToggle = onFullscreenToggle;
1649
+ if (onControlClick !== void 0) cfg.onControlClick = onControlClick;
1650
+ if (licenseKey !== void 0) cfg.licenseKey = licenseKey;
1651
+ const player = new StormcloudVideoPlayer(cfg);
1652
+ playerRef.current = player;
1653
+ player.load().then(() => {
1654
+ const showNative = player.shouldShowNativeControls();
1655
+ setShouldShowNativeControls(showNative);
1656
+ onReady?.(player);
1657
+ }).catch(() => {
1658
+ });
1659
+ return () => {
1660
+ try {
1661
+ player.destroy();
1662
+ } catch {
1663
+ }
1664
+ playerRef.current = null;
1665
+ };
1666
+ }, [criticalPropsKey]);
1667
+ useEffect(() => {
1668
+ if (!playerRef.current) return;
1609
1669
  try {
1610
- playerRef.current.setAdSchedule(adSchedule);
1611
- } catch {
1612
- }
1613
- }
1614
- }, [adSchedule]);
1615
- useEffect(() => {
1616
- if (!playerRef.current) return;
1617
- const checkAdStatus = () => {
1618
- if (playerRef.current) {
1619
- const showAds = playerRef.current.isShowingAds();
1620
- const currentIndex = playerRef.current.getCurrentAdIndex();
1621
- const totalAds = playerRef.current.getTotalAdsInBreak();
1622
- setAdStatus((prev) => {
1623
- if (prev.showAds !== showAds || prev.currentIndex !== currentIndex || prev.totalAds !== totalAds) {
1624
- return { showAds, currentIndex, totalAds };
1625
- }
1626
- return prev;
1627
- });
1670
+ if (autoplay !== void 0 && playerRef.current.videoElement) {
1671
+ playerRef.current.videoElement.autoplay = autoplay;
1672
+ }
1673
+ if (muted !== void 0 && playerRef.current.videoElement) {
1674
+ playerRef.current.videoElement.muted = muted;
1675
+ }
1676
+ } catch (error) {
1677
+ console.warn("Failed to update player properties:", error);
1628
1678
  }
1629
- };
1630
- const interval = setInterval(checkAdStatus, 500);
1631
- return () => clearInterval(interval);
1632
- }, []);
1633
- return /* @__PURE__ */ jsxs(
1634
- "div",
1635
- {
1636
- className: wrapperClassName,
1637
- style: { position: "relative", overflow: "hidden", ...wrapperStyle },
1638
- children: [
1639
- /* @__PURE__ */ jsx(
1640
- "video",
1641
- {
1642
- ref: videoRef,
1643
- className,
1644
- style: { display: "block", width: "100%", height: "100%", ...style },
1645
- controls: shouldShowNativeControls && controls,
1646
- playsInline,
1647
- preload,
1648
- poster,
1649
- ...restVideoAttrs,
1650
- children
1651
- }
1652
- ),
1653
- adStatus.showAds && adStatus.totalAds > 0 && /* @__PURE__ */ jsxs(
1654
- "div",
1655
- {
1656
- style: {
1657
- position: "absolute",
1658
- top: "10px",
1659
- right: "10px",
1660
- backgroundColor: "rgba(0, 0, 0, 0.7)",
1661
- color: "white",
1662
- padding: "4px 8px",
1663
- borderRadius: "4px",
1664
- fontSize: "12px",
1665
- fontFamily: "Arial, sans-serif",
1666
- zIndex: 10
1667
- },
1668
- children: [
1669
- "Ad ",
1670
- adStatus.currentIndex,
1671
- "/",
1672
- adStatus.totalAds
1673
- ]
1674
- }
1675
- ),
1676
- !shouldShowNativeControls && showCustomControls && /* @__PURE__ */ jsxs(
1677
- "div",
1678
- {
1679
- style: {
1680
- position: "absolute",
1681
- bottom: "10px",
1682
- right: "10px",
1683
- display: "flex",
1684
- gap: "8px",
1685
- zIndex: 10
1686
- },
1687
- children: [
1688
- onVolumeToggle && /* @__PURE__ */ jsx(
1689
- "button",
1690
- {
1691
- onClick: onVolumeToggle,
1692
- style: {
1693
- backgroundColor: "rgba(0, 0, 0, 0.7)",
1694
- color: "white",
1695
- border: "1px solid rgba(255, 255, 255, 0.3)",
1696
- borderRadius: "4px",
1697
- padding: "8px",
1698
- cursor: "pointer",
1699
- fontSize: "14px"
1700
- },
1701
- title: "Toggle Volume",
1702
- children: "\u{1F50A}"
1703
- }
1704
- ),
1705
- onFullscreenToggle && /* @__PURE__ */ jsx(
1706
- "button",
1707
- {
1708
- onClick: onFullscreenToggle,
1709
- style: {
1710
- backgroundColor: "rgba(0, 0, 0, 0.7)",
1711
- color: "white",
1712
- border: "1px solid rgba(255, 255, 255, 0.3)",
1713
- borderRadius: "4px",
1714
- padding: "8px",
1715
- cursor: "pointer",
1716
- fontSize: "14px"
1717
- },
1718
- title: "Toggle Fullscreen",
1719
- children: "\u2922"
1720
- }
1721
- )
1722
- ]
1723
- }
1724
- ),
1725
- onControlClick && /* @__PURE__ */ jsx(
1726
- "div",
1727
- {
1728
- onClick: onControlClick,
1729
- style: {
1730
- position: "absolute",
1731
- top: 0,
1732
- left: 0,
1733
- right: 0,
1734
- bottom: 0,
1735
- zIndex: 1,
1736
- cursor: "pointer"
1679
+ }, [autoplay, muted]);
1680
+ useEffect(() => {
1681
+ if (!playerRef.current) return;
1682
+ const checkAdStatus = () => {
1683
+ if (playerRef.current) {
1684
+ const showAds = playerRef.current.isShowingAds();
1685
+ const currentIndex = playerRef.current.getCurrentAdIndex();
1686
+ const totalAds = playerRef.current.getTotalAdsInBreak();
1687
+ setAdStatus((prev) => {
1688
+ if (prev.showAds !== showAds || prev.currentIndex !== currentIndex || prev.totalAds !== totalAds) {
1689
+ return { showAds, currentIndex, totalAds };
1737
1690
  }
1691
+ return prev;
1692
+ });
1693
+ }
1694
+ };
1695
+ const interval = setInterval(checkAdStatus, 500);
1696
+ return () => clearInterval(interval);
1697
+ }, []);
1698
+ useEffect(() => {
1699
+ if (typeof window === "undefined" || !playerRef.current) return;
1700
+ const handleResize = () => {
1701
+ if (playerRef.current && videoRef.current) {
1702
+ if (typeof playerRef.current.resize === "function") {
1703
+ playerRef.current.resize();
1738
1704
  }
1739
- )
1740
- ]
1705
+ }
1706
+ };
1707
+ window.addEventListener("resize", handleResize);
1708
+ return () => window.removeEventListener("resize", handleResize);
1709
+ }, []);
1710
+ useEffect(() => {
1711
+ if (!playerRef.current || !videoRef.current) return;
1712
+ const updateStates = () => {
1713
+ if (videoRef.current) {
1714
+ setIsMuted(videoRef.current.muted);
1715
+ }
1716
+ setIsFullscreen(
1717
+ document.fullscreenElement === videoRef.current?.parentElement
1718
+ );
1719
+ };
1720
+ const interval = setInterval(updateStates, 200);
1721
+ const handleFullscreenChange = () => {
1722
+ setIsFullscreen(
1723
+ document.fullscreenElement === videoRef.current?.parentElement
1724
+ );
1725
+ };
1726
+ document.addEventListener("fullscreenchange", handleFullscreenChange);
1727
+ return () => {
1728
+ clearInterval(interval);
1729
+ document.removeEventListener(
1730
+ "fullscreenchange",
1731
+ handleFullscreenChange
1732
+ );
1733
+ };
1734
+ }, []);
1735
+ return /* @__PURE__ */ jsxs(
1736
+ "div",
1737
+ {
1738
+ className: wrapperClassName,
1739
+ style: {
1740
+ display: "flex",
1741
+ alignItems: "center",
1742
+ justifyContent: "center",
1743
+ position: isFullscreen ? "fixed" : "relative",
1744
+ top: isFullscreen ? 0 : void 0,
1745
+ left: isFullscreen ? 0 : void 0,
1746
+ overflow: "hidden",
1747
+ width: isFullscreen ? "100vw" : "100%",
1748
+ height: isFullscreen ? "100vh" : "100%",
1749
+ maxWidth: isFullscreen ? "100vw" : "100%",
1750
+ maxHeight: isFullscreen ? "100vh" : "100%",
1751
+ zIndex: isFullscreen ? 9999 : void 0,
1752
+ backgroundColor: isFullscreen ? "#000" : void 0,
1753
+ ...wrapperStyle
1754
+ },
1755
+ children: [
1756
+ /* @__PURE__ */ jsx(
1757
+ "video",
1758
+ {
1759
+ ref: videoRef,
1760
+ className,
1761
+ style: {
1762
+ display: "block",
1763
+ width: "100%",
1764
+ height: "100%",
1765
+ objectFit: isFullscreen ? "cover" : "contain",
1766
+ backgroundColor: "#000",
1767
+ ...style
1768
+ },
1769
+ controls: shouldShowNativeControls && controls && !showCustomControls,
1770
+ playsInline,
1771
+ preload,
1772
+ poster,
1773
+ ...restVideoAttrs,
1774
+ children
1775
+ }
1776
+ ),
1777
+ adStatus.showAds && adStatus.totalAds > 0 && /* @__PURE__ */ jsxs(
1778
+ "div",
1779
+ {
1780
+ style: {
1781
+ position: "absolute",
1782
+ top: "10px",
1783
+ right: "10px",
1784
+ backgroundColor: "rgba(0, 0, 0, 0.7)",
1785
+ color: "white",
1786
+ padding: "4px 8px",
1787
+ borderRadius: "4px",
1788
+ fontSize: "12px",
1789
+ fontFamily: "Arial, sans-serif",
1790
+ zIndex: 10
1791
+ },
1792
+ children: [
1793
+ "Ad ",
1794
+ adStatus.currentIndex,
1795
+ "/",
1796
+ adStatus.totalAds
1797
+ ]
1798
+ }
1799
+ ),
1800
+ showCustomControls && /* @__PURE__ */ jsxs(
1801
+ "div",
1802
+ {
1803
+ style: {
1804
+ position: "absolute",
1805
+ bottom: "10px",
1806
+ right: "10px",
1807
+ display: "flex",
1808
+ gap: "8px",
1809
+ zIndex: 10
1810
+ },
1811
+ children: [
1812
+ /* @__PURE__ */ jsx(
1813
+ "button",
1814
+ {
1815
+ onClick: () => {
1816
+ if (onVolumeToggle) {
1817
+ onVolumeToggle();
1818
+ } else if (playerRef.current) {
1819
+ playerRef.current.toggleMute();
1820
+ }
1821
+ },
1822
+ onMouseEnter: (e) => {
1823
+ const target = e.currentTarget;
1824
+ target.style.transform = "translateY(-2px) scale(1.05)";
1825
+ target.style.boxShadow = "0 6px 20px rgba(0, 0, 0, 0.4), inset 0 1px 0 rgba(255, 255, 255, 0.2)";
1826
+ target.style.background = "linear-gradient(135deg, rgba(20, 20, 20, 0.9) 0%, rgba(60, 60, 60, 0.95) 100%)";
1827
+ },
1828
+ onMouseLeave: (e) => {
1829
+ const target = e.currentTarget;
1830
+ target.style.transform = "translateY(0) scale(1)";
1831
+ target.style.boxShadow = "0 4px 15px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.1)";
1832
+ target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.8) 0%, rgba(40, 40, 40, 0.9) 100%)";
1833
+ },
1834
+ style: {
1835
+ background: "linear-gradient(135deg, rgba(0, 0, 0, 0.8) 0%, rgba(40, 40, 40, 0.9) 100%)",
1836
+ color: "white",
1837
+ border: "1px solid rgba(255, 255, 255, 0.2)",
1838
+ borderRadius: "8px",
1839
+ padding: "10px",
1840
+ cursor: "pointer",
1841
+ display: "flex",
1842
+ alignItems: "center",
1843
+ justifyContent: "center",
1844
+ backdropFilter: "blur(10px)",
1845
+ boxShadow: "0 4px 15px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.1)",
1846
+ transition: "all 0.3s cubic-bezier(0.4, 0, 0.2, 1)"
1847
+ },
1848
+ title: isMuted ? "Unmute" : "Mute",
1849
+ children: isMuted ? /* @__PURE__ */ jsxs(
1850
+ "svg",
1851
+ {
1852
+ width: "18",
1853
+ height: "18",
1854
+ viewBox: "0 0 24 24",
1855
+ fill: "none",
1856
+ xmlns: "http://www.w3.org/2000/svg",
1857
+ children: [
1858
+ /* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsxs(
1859
+ "linearGradient",
1860
+ {
1861
+ id: "volumeGradient",
1862
+ x1: "0%",
1863
+ y1: "0%",
1864
+ x2: "100%",
1865
+ y2: "100%",
1866
+ children: [
1867
+ /* @__PURE__ */ jsx("stop", { offset: "0%", stopColor: "#ffffff", stopOpacity: "1" }),
1868
+ /* @__PURE__ */ jsx(
1869
+ "stop",
1870
+ {
1871
+ offset: "100%",
1872
+ stopColor: "#e0e0e0",
1873
+ stopOpacity: "0.9"
1874
+ }
1875
+ )
1876
+ ]
1877
+ }
1878
+ ) }),
1879
+ /* @__PURE__ */ jsx(
1880
+ "path",
1881
+ {
1882
+ d: "M3 8.5v7c0 .28.22.5.5.5H7l4.29 4.29c.63.63 1.71.18 1.71-.71V4.41c0-.89-1.08-1.34-1.71-.71L7 8H3.5c-.28 0-.5.22-.5.5z",
1883
+ fill: "url(#volumeGradient)",
1884
+ stroke: "rgba(255,255,255,0.3)",
1885
+ strokeWidth: "0.5"
1886
+ }
1887
+ ),
1888
+ /* @__PURE__ */ jsx(
1889
+ "path",
1890
+ {
1891
+ d: "M16.5 8.5l-1.41-1.41L12 10.18 8.91 7.09 7.5 8.5l3.09 3.09L7.5 14.68l1.41 1.41L12 13l3.09 3.09 1.41-1.41L13.41 12l3.09-3.5z",
1892
+ fill: "#ff4444",
1893
+ stroke: "rgba(255,255,255,0.5)",
1894
+ strokeWidth: "0.5"
1895
+ }
1896
+ )
1897
+ ]
1898
+ }
1899
+ ) : /* @__PURE__ */ jsxs(
1900
+ "svg",
1901
+ {
1902
+ width: "18",
1903
+ height: "18",
1904
+ viewBox: "0 0 24 24",
1905
+ fill: "none",
1906
+ xmlns: "http://www.w3.org/2000/svg",
1907
+ children: [
1908
+ /* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsxs(
1909
+ "linearGradient",
1910
+ {
1911
+ id: "volumeGradient",
1912
+ x1: "0%",
1913
+ y1: "0%",
1914
+ x2: "100%",
1915
+ y2: "100%",
1916
+ children: [
1917
+ /* @__PURE__ */ jsx("stop", { offset: "0%", stopColor: "#ffffff", stopOpacity: "1" }),
1918
+ /* @__PURE__ */ jsx(
1919
+ "stop",
1920
+ {
1921
+ offset: "100%",
1922
+ stopColor: "#e0e0e0",
1923
+ stopOpacity: "0.9"
1924
+ }
1925
+ )
1926
+ ]
1927
+ }
1928
+ ) }),
1929
+ /* @__PURE__ */ jsx(
1930
+ "path",
1931
+ {
1932
+ d: "M3 8.5v7c0 .28.22.5.5.5H7l4.29 4.29c.63.63 1.71.18 1.71-.71V4.41c0-.89-1.08-1.34-1.71-.71L7 8H3.5c-.28 0-.5.22-.5.5z",
1933
+ fill: "url(#volumeGradient)",
1934
+ stroke: "rgba(255,255,255,0.3)",
1935
+ strokeWidth: "0.5"
1936
+ }
1937
+ ),
1938
+ /* @__PURE__ */ jsx(
1939
+ "path",
1940
+ {
1941
+ d: "M15.5 12c0-1.33-.58-2.53-1.5-3.35v6.69c.92-.81 1.5-2.01 1.5-3.34z",
1942
+ fill: "url(#volumeGradient)",
1943
+ opacity: "0.8"
1944
+ }
1945
+ ),
1946
+ /* @__PURE__ */ jsx(
1947
+ "path",
1948
+ {
1949
+ d: "M14 4.45v1.75c2.01.91 3.5 3.02 3.5 5.3 0 2.28-1.49 4.39-3.5 5.3v1.75c2.89-.86 5-3.54 5-7.05s-2.11-6.19-5-7.05z",
1950
+ fill: "url(#volumeGradient)",
1951
+ opacity: "0.6"
1952
+ }
1953
+ )
1954
+ ]
1955
+ }
1956
+ )
1957
+ }
1958
+ ),
1959
+ /* @__PURE__ */ jsx(
1960
+ "button",
1961
+ {
1962
+ onClick: () => {
1963
+ if (onFullscreenToggle) {
1964
+ onFullscreenToggle();
1965
+ } else if (playerRef.current) {
1966
+ playerRef.current.toggleFullscreen().catch((err) => {
1967
+ console.error("Fullscreen error:", err);
1968
+ });
1969
+ }
1970
+ },
1971
+ onMouseEnter: (e) => {
1972
+ const target = e.currentTarget;
1973
+ target.style.transform = "translateY(-2px) scale(1.05)";
1974
+ target.style.boxShadow = "0 6px 20px rgba(0, 0, 0, 0.4), inset 0 1px 0 rgba(255, 255, 255, 0.2)";
1975
+ target.style.background = "linear-gradient(135deg, rgba(20, 20, 20, 0.9) 0%, rgba(60, 60, 60, 0.95) 100%)";
1976
+ },
1977
+ onMouseLeave: (e) => {
1978
+ const target = e.currentTarget;
1979
+ target.style.transform = "translateY(0) scale(1)";
1980
+ target.style.boxShadow = "0 4px 15px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.1)";
1981
+ target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.8) 0%, rgba(40, 40, 40, 0.9) 100%)";
1982
+ },
1983
+ style: {
1984
+ background: "linear-gradient(135deg, rgba(0, 0, 0, 0.8) 0%, rgba(40, 40, 40, 0.9) 100%)",
1985
+ color: "white",
1986
+ border: "1px solid rgba(255, 255, 255, 0.2)",
1987
+ borderRadius: "8px",
1988
+ padding: "10px",
1989
+ cursor: "pointer",
1990
+ display: "flex",
1991
+ alignItems: "center",
1992
+ justifyContent: "center",
1993
+ backdropFilter: "blur(10px)",
1994
+ boxShadow: "0 4px 15px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.1)",
1995
+ transition: "all 0.3s cubic-bezier(0.4, 0, 0.2, 1)"
1996
+ },
1997
+ title: isFullscreen ? "Exit Fullscreen" : "Enter Fullscreen",
1998
+ children: isFullscreen ? /* @__PURE__ */ jsxs(
1999
+ "svg",
2000
+ {
2001
+ width: "20",
2002
+ height: "20",
2003
+ viewBox: "0 0 24 24",
2004
+ fill: "none",
2005
+ xmlns: "http://www.w3.org/2000/svg",
2006
+ children: [
2007
+ /* @__PURE__ */ jsx(
2008
+ "path",
2009
+ {
2010
+ d: "M8 8h3v3l-1-1-2 2-1.5-1.5L8.5 8.5 8 8z",
2011
+ fill: "white",
2012
+ stroke: "rgba(255,255,255,0.8)",
2013
+ strokeWidth: "0.5"
2014
+ }
2015
+ ),
2016
+ /* @__PURE__ */ jsx(
2017
+ "path",
2018
+ {
2019
+ d: "M16 8h-3v3l1-1 2 2 1.5-1.5L15.5 8.5 16 8z",
2020
+ fill: "white",
2021
+ stroke: "rgba(255,255,255,0.8)",
2022
+ strokeWidth: "0.5"
2023
+ }
2024
+ ),
2025
+ /* @__PURE__ */ jsx(
2026
+ "path",
2027
+ {
2028
+ d: "M8 16h3v-3l-1 1-2-2-1.5 1.5L8.5 15.5 8 16z",
2029
+ fill: "white",
2030
+ stroke: "rgba(255,255,255,0.8)",
2031
+ strokeWidth: "0.5"
2032
+ }
2033
+ ),
2034
+ /* @__PURE__ */ jsx(
2035
+ "path",
2036
+ {
2037
+ d: "M16 16h-3v-3l1 1 2-2 1.5 1.5L15.5 15.5 16 16z",
2038
+ fill: "white",
2039
+ stroke: "rgba(255,255,255,0.8)",
2040
+ strokeWidth: "0.5"
2041
+ }
2042
+ )
2043
+ ]
2044
+ }
2045
+ ) : /* @__PURE__ */ jsxs(
2046
+ "svg",
2047
+ {
2048
+ width: "20",
2049
+ height: "20",
2050
+ viewBox: "0 0 24 24",
2051
+ fill: "none",
2052
+ xmlns: "http://www.w3.org/2000/svg",
2053
+ children: [
2054
+ /* @__PURE__ */ jsx(
2055
+ "path",
2056
+ {
2057
+ d: "M3 3h6v2H5v4H3V3z",
2058
+ fill: "white",
2059
+ stroke: "rgba(255,255,255,0.8)",
2060
+ strokeWidth: "0.5"
2061
+ }
2062
+ ),
2063
+ /* @__PURE__ */ jsx(
2064
+ "path",
2065
+ {
2066
+ d: "M21 3h-6v2h4v4h2V3z",
2067
+ fill: "white",
2068
+ stroke: "rgba(255,255,255,0.8)",
2069
+ strokeWidth: "0.5"
2070
+ }
2071
+ ),
2072
+ /* @__PURE__ */ jsx(
2073
+ "path",
2074
+ {
2075
+ d: "M3 21v-6h2v4h4v2H3z",
2076
+ fill: "white",
2077
+ stroke: "rgba(255,255,255,0.8)",
2078
+ strokeWidth: "0.5"
2079
+ }
2080
+ ),
2081
+ /* @__PURE__ */ jsx(
2082
+ "path",
2083
+ {
2084
+ d: "M21 21h-6v-2h4v-4h2v6z",
2085
+ fill: "white",
2086
+ stroke: "rgba(255,255,255,0.8)",
2087
+ strokeWidth: "0.5"
2088
+ }
2089
+ )
2090
+ ]
2091
+ }
2092
+ )
2093
+ }
2094
+ )
2095
+ ]
2096
+ }
2097
+ ),
2098
+ onControlClick && /* @__PURE__ */ jsx(
2099
+ "div",
2100
+ {
2101
+ onClick: onControlClick,
2102
+ style: {
2103
+ position: "absolute",
2104
+ top: 0,
2105
+ left: 0,
2106
+ right: 0,
2107
+ bottom: 0,
2108
+ zIndex: 1,
2109
+ cursor: "pointer"
2110
+ }
2111
+ }
2112
+ )
2113
+ ]
2114
+ }
2115
+ );
2116
+ },
2117
+ (prevProps, nextProps) => {
2118
+ for (const prop of CRITICAL_PROPS) {
2119
+ if (prevProps[prop] !== nextProps[prop]) {
2120
+ return false;
2121
+ }
1741
2122
  }
1742
- );
1743
- };
2123
+ const uiProps = [
2124
+ "autoplay",
2125
+ "muted",
2126
+ "controls",
2127
+ "showCustomControls",
2128
+ "className",
2129
+ "style",
2130
+ "wrapperClassName",
2131
+ "wrapperStyle",
2132
+ "playsInline",
2133
+ "preload",
2134
+ "poster",
2135
+ "children"
2136
+ ];
2137
+ for (const prop of uiProps) {
2138
+ if (prevProps[prop] !== nextProps[prop]) {
2139
+ return false;
2140
+ }
2141
+ }
2142
+ const callbackProps = [
2143
+ "onReady",
2144
+ "onVolumeToggle",
2145
+ "onFullscreenToggle",
2146
+ "onControlClick"
2147
+ ];
2148
+ for (const prop of callbackProps) {
2149
+ if (prevProps[prop] !== nextProps[prop]) {
2150
+ return false;
2151
+ }
2152
+ }
2153
+ return true;
2154
+ }
2155
+ );
1744
2156
  export {
1745
2157
  StormcloudVideoPlayer,
1746
2158
  StormcloudVideoPlayerComponent,