stormcloud-video-player 0.8.2 → 0.8.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/dist/stormcloud-vp.min.js +3 -1
  2. package/lib/index.cjs +536 -341
  3. package/lib/index.cjs.map +1 -1
  4. package/lib/index.d.cts +37 -2
  5. package/lib/index.d.ts +37 -2
  6. package/lib/index.js +477 -342
  7. package/lib/index.js.map +1 -1
  8. package/lib/player/StormcloudVideoPlayer.cjs +266 -206
  9. package/lib/player/StormcloudVideoPlayer.cjs.map +1 -1
  10. package/lib/player/StormcloudVideoPlayer.d.cts +5 -2
  11. package/lib/players/FilePlayer.cjs.map +1 -1
  12. package/lib/players/HlsPlayer.cjs +266 -206
  13. package/lib/players/HlsPlayer.cjs.map +1 -1
  14. package/lib/players/HlsPlayer.d.cts +1 -1
  15. package/lib/players/index.cjs +266 -206
  16. package/lib/players/index.cjs.map +1 -1
  17. package/lib/sdk/hlsAdPlayer.cjs.map +1 -1
  18. package/lib/sdk/hlsAdPlayer.d.cts +1 -1
  19. package/lib/sdk/pal.cjs.map +1 -1
  20. package/lib/{types-DDwAfBLt.d.cts → types-BmF_60m2.d.cts} +2 -0
  21. package/lib/ui/StormcloudVideoPlayer.cjs +450 -341
  22. package/lib/ui/StormcloudVideoPlayer.cjs.map +1 -1
  23. package/lib/ui/StormcloudVideoPlayer.d.cts +1 -1
  24. package/lib/utils/browserCompat.cjs.map +1 -1
  25. package/lib/utils/mqttClient.cjs +245 -0
  26. package/lib/utils/mqttClient.cjs.map +1 -0
  27. package/lib/utils/mqttClient.d.cts +13 -0
  28. package/lib/utils/mqttConfig.cjs +141 -0
  29. package/lib/utils/mqttConfig.cjs.map +1 -0
  30. package/lib/utils/mqttConfig.d.cts +20 -0
  31. package/lib/utils/polyfills.cjs.map +1 -1
  32. package/lib/utils/tracking.cjs +182 -170
  33. package/lib/utils/tracking.cjs.map +1 -1
  34. package/lib/utils/tracking.d.cts +1 -1
  35. package/package.json +3 -1
  36. package/src/certs/emqxsl-ca.crt +22 -0
package/lib/index.js CHANGED
@@ -1355,6 +1355,123 @@ function createPalNonceManager() {
1355
1355
  }
1356
1356
  };
1357
1357
  }
1358
+ // src/utils/mqttConfig.ts
1359
+ var MQTT_CA_CERT_FILE = "src/certs/emqxsl-ca.crt";
1360
+ var DEFAULT_MQTT_CONFIG = {
1361
+ enabled: true,
1362
+ brokerAddress: "vecbae77.ala.us-east-1.emqxsl.com",
1363
+ brokerPort: 8883,
1364
+ wsPort: 8084,
1365
+ username: "for-sonifi",
1366
+ password: "sonifi-mqtt",
1367
+ topicPrefix: "adstorm/players",
1368
+ qos: 1
1369
+ };
1370
+ var mqttConfig = _object_spread({}, DEFAULT_MQTT_CONFIG);
1371
+ function applyMQTTConfig(overrides) {
1372
+ Object.assign(mqttConfig, overrides);
1373
+ }
1374
+ function isMQTTEnabled() {
1375
+ return mqttConfig.enabled;
1376
+ }
1377
+ function buildMQTTBrokerUrl() {
1378
+ if (mqttConfig.brokerUrl) return mqttConfig.brokerUrl;
1379
+ return "wss://".concat(mqttConfig.brokerAddress, ":").concat(mqttConfig.wsPort, "/mqtt");
1380
+ }
1381
+ function buildPlayerTopic(licenseKey, channel) {
1382
+ return "".concat(mqttConfig.topicPrefix, "/").concat(licenseKey, "/").concat(channel);
1383
+ }
1384
+ // src/utils/mqttClient.ts
1385
+ import mqtt from "mqtt";
1386
+ var LOG = "[StormcloudVideoPlayer][MQTT]";
1387
+ var client = null;
1388
+ var status = "disconnected";
1389
+ function getMQTTStatus() {
1390
+ return status;
1391
+ }
1392
+ function isMQTTConnected() {
1393
+ return status === "connected" && client !== null && client.connected;
1394
+ }
1395
+ function isMQTTConfigured() {
1396
+ return isMQTTEnabled();
1397
+ }
1398
+ function configureMQTT(overrides) {
1399
+ applyMQTTConfig(overrides);
1400
+ disconnectMQTT();
1401
+ }
1402
+ function initMQTTClient() {
1403
+ if (client || !isMQTTEnabled()) return;
1404
+ var url = buildMQTTBrokerUrl();
1405
+ status = "connecting";
1406
+ var clientId = "stormcloud-vp-".concat(Math.random().toString(36).slice(2, 9));
1407
+ try {
1408
+ client = mqtt.connect(url, {
1409
+ clientId: clientId,
1410
+ username: mqttConfig.username,
1411
+ password: mqttConfig.password,
1412
+ keepalive: 60,
1413
+ clean: true,
1414
+ reconnectPeriod: 5e3,
1415
+ connectTimeout: 1e4,
1416
+ queueQoSZero: false
1417
+ });
1418
+ } catch (err) {
1419
+ status = "error";
1420
+ console.warn("".concat(LOG, " connect() threw:"), err);
1421
+ return;
1422
+ }
1423
+ client.on("connect", function() {
1424
+ status = "connected";
1425
+ console.info("".concat(LOG, " connected to ").concat(url));
1426
+ });
1427
+ client.on("reconnect", function() {
1428
+ status = "connecting";
1429
+ console.info("".concat(LOG, " reconnecting…"));
1430
+ });
1431
+ client.on("offline", function() {
1432
+ status = "disconnected";
1433
+ console.warn("".concat(LOG, " offline"));
1434
+ });
1435
+ client.on("error", function(err) {
1436
+ status = "error";
1437
+ console.warn("".concat(LOG, " error:"), err.message);
1438
+ });
1439
+ client.on("close", function() {
1440
+ if (status === "connected") {
1441
+ status = "disconnected";
1442
+ }
1443
+ });
1444
+ }
1445
+ function ensureMQTTClient() {
1446
+ if (isMQTTEnabled() && !client) {
1447
+ initMQTTClient();
1448
+ }
1449
+ }
1450
+ function publishMQTT(topic, payload) {
1451
+ if (!isMQTTEnabled()) {
1452
+ return false;
1453
+ }
1454
+ ensureMQTTClient();
1455
+ if (!client) {
1456
+ return false;
1457
+ }
1458
+ try {
1459
+ client.publish(topic, JSON.stringify(payload), {
1460
+ qos: mqttConfig.qos
1461
+ });
1462
+ return true;
1463
+ } catch (err) {
1464
+ console.warn("".concat(LOG, " publish failed on ").concat(topic, ":"), err);
1465
+ return false;
1466
+ }
1467
+ }
1468
+ function disconnectMQTT() {
1469
+ if (client) {
1470
+ client.end(true);
1471
+ client = null;
1472
+ status = "disconnected";
1473
+ }
1474
+ }
1358
1475
  // src/utils/tracking.ts
1359
1476
  var cachedBrowserId = null;
1360
1477
  function getClientInfo() {
@@ -1501,7 +1618,7 @@ function getClientInfo() {
1501
1618
  }
1502
1619
  function getBrowserID(clientInfo) {
1503
1620
  return _async_to_generator(function() {
1504
- var fingerprintString, encodedData, utf8, buffer, i, hashBuffer, hashArray, hashHex, error, hash, i1, char, fallbackHash, timestamp, random;
1621
+ var _crypto_subtle, fingerprintString, encodedData, utf8, buffer, i, hashBuffer, hashHex, unused, hash, i1, char, fallbackHash, timestamp, random;
1505
1622
  return _ts_generator(this, function(_state) {
1506
1623
  switch(_state.label){
1507
1624
  case 0:
@@ -1512,7 +1629,7 @@ function getBrowserID(clientInfo) {
1512
1629
  ];
1513
1630
  }
1514
1631
  fingerprintString = JSON.stringify(clientInfo);
1515
- if (!(typeof crypto !== "undefined" && crypto.subtle && crypto.subtle.digest)) return [
1632
+ if (!(typeof crypto !== "undefined" && ((_crypto_subtle = crypto.subtle) === null || _crypto_subtle === void 0 ? void 0 : _crypto_subtle.digest))) return [
1516
1633
  3,
1517
1634
  5
1518
1635
  ];
@@ -1550,8 +1667,7 @@ function getBrowserID(clientInfo) {
1550
1667
  ];
1551
1668
  case 3:
1552
1669
  hashBuffer = _state.sent();
1553
- hashArray = Array.from(new Uint8Array(hashBuffer));
1554
- hashHex = hashArray.map(function(b) {
1670
+ hashHex = Array.from(new Uint8Array(hashBuffer)).map(function(b) {
1555
1671
  return b.toString(16).padStart(2, "0");
1556
1672
  }).join("");
1557
1673
  cachedBrowserId = hashHex;
@@ -1560,8 +1676,8 @@ function getBrowserID(clientInfo) {
1560
1676
  hashHex
1561
1677
  ];
1562
1678
  case 4:
1563
- error = _state.sent();
1564
- console.warn("[StormcloudVideoPlayer] crypto.subtle.digest not supported, using fallback hash");
1679
+ unused = _state.sent();
1680
+ console.warn("[StormcloudVideoPlayer] crypto.subtle not supported, using fallback hash");
1565
1681
  return [
1566
1682
  3,
1567
1683
  5
@@ -1585,177 +1701,91 @@ function getBrowserID(clientInfo) {
1585
1701
  });
1586
1702
  })();
1587
1703
  }
1588
- var PLAYER_TRACKING_BASE_URL = "https://adstorm.co/api-adstorm-dev/adstorm/player-tracking";
1589
- var TRACK_URL = "".concat(PLAYER_TRACKING_BASE_URL, "/metrics/ingest");
1590
- var HEARTBEAT_URL = "".concat(PLAYER_TRACKING_BASE_URL, "/heartbeat");
1591
- var IMPRESSIONS_URL = "".concat(PLAYER_TRACKING_BASE_URL, "/impressions/ingest");
1592
- function buildHeaders(licenseKey) {
1593
- var headers = {
1594
- "Content-Type": "application/json"
1595
- };
1596
- if (licenseKey) {
1597
- headers["Authorization"] = "Bearer ".concat(licenseKey);
1598
- }
1599
- return headers;
1600
- }
1601
- function sendTrackRequest(licenseKey, body) {
1602
- return _async_to_generator(function() {
1603
- var response;
1604
- return _ts_generator(this, function(_state) {
1605
- switch(_state.label){
1606
- case 0:
1607
- return [
1608
- 4,
1609
- fetch(TRACK_URL, {
1610
- method: "POST",
1611
- headers: buildHeaders(licenseKey),
1612
- body: JSON.stringify(body)
1613
- })
1614
- ];
1615
- case 1:
1616
- response = _state.sent();
1617
- if (!response.ok) {
1618
- throw new Error("HTTP error! status: ".concat(response.status));
1619
- }
1620
- return [
1621
- 4,
1622
- response.json()
1623
- ];
1624
- case 2:
1625
- _state.sent();
1626
- return [
1627
- 2
1628
- ];
1629
- }
1630
- });
1631
- })();
1704
+ function canPublish(licenseKey) {
1705
+ return Boolean(isMQTTEnabled() && licenseKey);
1632
1706
  }
1633
- function postJson(url, licenseKey, body) {
1707
+ function buildPlayerMetricEvent() {
1634
1708
  return _async_to_generator(function() {
1635
- var response;
1636
- return _ts_generator(this, function(_state) {
1637
- switch(_state.label){
1638
- case 0:
1639
- return [
1640
- 4,
1641
- fetch(url, {
1642
- method: "POST",
1643
- headers: buildHeaders(licenseKey),
1644
- body: JSON.stringify(body)
1645
- })
1646
- ];
1647
- case 1:
1648
- response = _state.sent();
1649
- if (!response.ok) {
1650
- throw new Error("HTTP error! status: ".concat(response.status));
1651
- }
1652
- return [
1653
- 4,
1654
- response.json()
1655
- ];
1656
- case 2:
1657
- _state.sent();
1658
- return [
1659
- 2
1660
- ];
1661
- }
1662
- });
1663
- })();
1664
- }
1665
- function buildPlayerMetricEvent(_0) {
1666
- return _async_to_generator(function(licenseKey) {
1667
- var context, flags, _flags_captureAt, clientInfo, browserId, captureAt;
1709
+ var context, flags, _flags_captureAt, _flags_adLoaded, _flags_adDetect, clientInfo, playerId, captureAt;
1668
1710
  var _arguments = arguments;
1669
1711
  return _ts_generator(this, function(_state) {
1670
1712
  switch(_state.label){
1671
1713
  case 0:
1672
- context = _arguments.length > 1 && _arguments[1] !== void 0 ? _arguments[1] : {}, flags = _arguments.length > 2 && _arguments[2] !== void 0 ? _arguments[2] : {};
1714
+ context = _arguments.length > 0 && _arguments[0] !== void 0 ? _arguments[0] : {}, flags = _arguments.length > 1 && _arguments[1] !== void 0 ? _arguments[1] : {};
1673
1715
  clientInfo = getClientInfo();
1674
1716
  return [
1675
1717
  4,
1676
1718
  getBrowserID(clientInfo)
1677
1719
  ];
1678
1720
  case 1:
1679
- browserId = _state.sent();
1721
+ playerId = _state.sent();
1680
1722
  captureAt = (_flags_captureAt = flags.captureAt) !== null && _flags_captureAt !== void 0 ? _flags_captureAt : /* @__PURE__ */ new Date().toISOString();
1681
1723
  return [
1682
1724
  2,
1683
- {
1684
- player_id: browserId,
1685
- browserId: browserId,
1725
+ _object_spread({
1726
+ player_id: playerId,
1686
1727
  device_type: clientInfo.deviceType,
1687
- deviceType: clientInfo.deviceType,
1688
- input_stream_type: context.inputStreamType,
1689
- os: clientInfo.os,
1690
- ad_loaded: flags.adLoaded,
1691
- ad_detect: flags.adDetect,
1692
- license_key: licenseKey,
1693
- capture_at: captureAt,
1694
- timestamp: captureAt
1695
- }
1728
+ os: clientInfo.os.toLowerCase(),
1729
+ ad_loaded: (_flags_adLoaded = flags.adLoaded) !== null && _flags_adLoaded !== void 0 ? _flags_adLoaded : false,
1730
+ ad_detect: (_flags_adDetect = flags.adDetect) !== null && _flags_adDetect !== void 0 ? _flags_adDetect : false,
1731
+ capture_at: captureAt
1732
+ }, context.inputStreamType ? {
1733
+ input_stream_type: context.inputStreamType
1734
+ } : {})
1696
1735
  ];
1697
1736
  }
1698
1737
  });
1699
1738
  }).apply(this, arguments);
1700
1739
  }
1740
+ function publishTracking(licenseKey, channel, body) {
1741
+ ensureMQTTClient();
1742
+ publishMQTT(buildPlayerTopic(licenseKey, channel), body);
1743
+ }
1701
1744
  function sendInitialTracking(_0) {
1702
1745
  return _async_to_generator(function(licenseKey) {
1703
- var context, clientInfo, browserId, trackingData, error;
1746
+ var context, metricEvent, error;
1704
1747
  var _arguments = arguments;
1705
1748
  return _ts_generator(this, function(_state) {
1706
1749
  switch(_state.label){
1707
1750
  case 0:
1708
1751
  context = _arguments.length > 1 && _arguments[1] !== void 0 ? _arguments[1] : {};
1752
+ if (!canPublish(licenseKey)) return [
1753
+ 2
1754
+ ];
1709
1755
  _state.label = 1;
1710
1756
  case 1:
1711
1757
  _state.trys.push([
1712
1758
  1,
1713
- 4,
1759
+ 3,
1714
1760
  ,
1715
- 5
1761
+ 4
1716
1762
  ]);
1717
- clientInfo = getClientInfo();
1718
1763
  return [
1719
1764
  4,
1720
- getBrowserID(clientInfo)
1721
- ];
1722
- case 2:
1723
- browserId = _state.sent();
1724
- trackingData = _object_spread({
1725
- browserId: browserId
1726
- }, clientInfo);
1727
- return [
1728
- 4,
1729
- sendTrackRequest(licenseKey, {
1730
- events: [
1731
- {
1732
- player_id: browserId,
1733
- device_type: clientInfo.deviceType,
1734
- input_stream_type: context.inputStreamType,
1735
- os: clientInfo.os,
1736
- ad_loaded: false,
1737
- ad_detect: false,
1738
- license_key: licenseKey,
1739
- capture_at: /* @__PURE__ */ new Date().toISOString()
1740
- }
1741
- ],
1742
- trackingData: trackingData
1765
+ buildPlayerMetricEvent(context, {
1766
+ adLoaded: false,
1767
+ adDetect: false
1743
1768
  })
1744
1769
  ];
1745
- case 3:
1746
- _state.sent();
1770
+ case 2:
1771
+ metricEvent = _state.sent();
1772
+ publishTracking(licenseKey, "metrics", {
1773
+ events: [
1774
+ metricEvent
1775
+ ]
1776
+ });
1747
1777
  return [
1748
1778
  3,
1749
- 5
1779
+ 4
1750
1780
  ];
1751
- case 4:
1781
+ case 3:
1752
1782
  error = _state.sent();
1753
1783
  console.error("[StormcloudVideoPlayer] Error sending initial tracking data:", error);
1754
1784
  return [
1755
1785
  3,
1756
- 5
1786
+ 4
1757
1787
  ];
1758
- case 5:
1788
+ case 4:
1759
1789
  return [
1760
1790
  2
1761
1791
  ];
@@ -1859,53 +1889,48 @@ function sendAdImpressionTracking(_0, _1) {
1859
1889
  switch(_state.label){
1860
1890
  case 0:
1861
1891
  context = _arguments.length > 2 && _arguments[2] !== void 0 ? _arguments[2] : {};
1892
+ if (!canPublish(licenseKey)) return [
1893
+ 2
1894
+ ];
1862
1895
  _state.label = 1;
1863
1896
  case 1:
1864
1897
  _state.trys.push([
1865
1898
  1,
1866
- 4,
1899
+ 3,
1867
1900
  ,
1868
- 5
1901
+ 4
1869
1902
  ]);
1870
1903
  return [
1871
1904
  4,
1872
- buildPlayerMetricEvent(licenseKey, context, {
1905
+ buildPlayerMetricEvent(context, {
1873
1906
  captureAt: adImpressionInfo.timestamp
1874
1907
  })
1875
1908
  ];
1876
1909
  case 2:
1877
1910
  metricEvent = _state.sent();
1878
- return [
1879
- 4,
1880
- Promise.all([
1881
- postJson(HEARTBEAT_URL, licenseKey, metricEvent),
1882
- postJson(IMPRESSIONS_URL, licenseKey, {
1883
- events: [
1884
- {
1885
- player_id: metricEvent.player_id,
1886
- ad_played_count: 1,
1887
- ad_url: adImpressionInfo.adUrl,
1888
- license_key: licenseKey,
1889
- capture_at: adImpressionInfo.timestamp
1890
- }
1891
- ]
1892
- })
1893
- ])
1894
- ];
1895
- case 3:
1896
- _state.sent();
1911
+ publishTracking(licenseKey, "heartbeat", metricEvent);
1912
+ publishTracking(licenseKey, "impressions", {
1913
+ events: [
1914
+ {
1915
+ player_id: metricEvent.player_id,
1916
+ ad_played_count: 1,
1917
+ ad_url: adImpressionInfo.adUrl,
1918
+ capture_at: adImpressionInfo.timestamp
1919
+ }
1920
+ ]
1921
+ });
1897
1922
  return [
1898
1923
  3,
1899
- 5
1924
+ 4
1900
1925
  ];
1901
- case 4:
1926
+ case 3:
1902
1927
  error = _state.sent();
1903
1928
  console.error("[StormcloudVideoPlayer] Error sending ad impression tracking:", error);
1904
1929
  return [
1905
1930
  3,
1906
- 5
1931
+ 4
1907
1932
  ];
1908
- case 5:
1933
+ case 4:
1909
1934
  return [
1910
1935
  2
1911
1936
  ];
@@ -1921,38 +1946,36 @@ function sendHeartbeat(_0) {
1921
1946
  switch(_state.label){
1922
1947
  case 0:
1923
1948
  context = _arguments.length > 1 && _arguments[1] !== void 0 ? _arguments[1] : {}, flags = _arguments.length > 2 && _arguments[2] !== void 0 ? _arguments[2] : {};
1949
+ if (!canPublish(licenseKey)) return [
1950
+ 2
1951
+ ];
1924
1952
  _state.label = 1;
1925
1953
  case 1:
1926
1954
  _state.trys.push([
1927
1955
  1,
1928
- 4,
1956
+ 3,
1929
1957
  ,
1930
- 5
1958
+ 4
1931
1959
  ]);
1932
1960
  return [
1933
1961
  4,
1934
- buildPlayerMetricEvent(licenseKey, context, flags)
1962
+ buildPlayerMetricEvent(context, flags)
1935
1963
  ];
1936
1964
  case 2:
1937
1965
  heartbeatData = _state.sent();
1938
- return [
1939
- 4,
1940
- postJson(HEARTBEAT_URL, licenseKey, heartbeatData)
1941
- ];
1942
- case 3:
1943
- _state.sent();
1966
+ publishTracking(licenseKey, "heartbeat", heartbeatData);
1944
1967
  return [
1945
1968
  3,
1946
- 5
1969
+ 4
1947
1970
  ];
1948
- case 4:
1971
+ case 3:
1949
1972
  error = _state.sent();
1950
1973
  console.error("[StormcloudVideoPlayer] Error sending heartbeat:", error);
1951
1974
  return [
1952
1975
  3,
1953
- 5
1976
+ 4
1954
1977
  ];
1955
- case 5:
1978
+ case 4:
1956
1979
  return [
1957
1980
  2
1958
1981
  ];
@@ -2491,7 +2514,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
2491
2514
  key: "load",
2492
2515
  value: function load() {
2493
2516
  return _async_to_generator(function() {
2494
- var _this, _this_config_lowLatencyMode, error, _this_config_lowLatencyMode1, _this_video_play;
2517
+ var _this, _this_config_lowLatencyMode, error, _this_config_isLiveStream, _this_config_lowLatencyMode1, _this_video_play;
2495
2518
  return _ts_generator(this, function(_state) {
2496
2519
  switch(_state.label){
2497
2520
  case 0:
@@ -2542,7 +2565,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
2542
2565
  this.nativeHlsMode = true;
2543
2566
  this.videoSrcProtection = this.config.src;
2544
2567
  this.video.src = this.config.src;
2545
- this.isLiveStream = (_this_config_lowLatencyMode1 = this.config.lowLatencyMode) !== null && _this_config_lowLatencyMode1 !== void 0 ? _this_config_lowLatencyMode1 : false;
2568
+ this.isLiveStream = (_this_config_isLiveStream = this.config.isLiveStream) !== null && _this_config_isLiveStream !== void 0 ? _this_config_isLiveStream : (_this_config_lowLatencyMode1 = this.config.lowLatencyMode) !== null && _this_config_lowLatencyMode1 !== void 0 ? _this_config_lowLatencyMode1 : false;
2546
2569
  if (this.config.debugAdTiming) {
2547
2570
  console.log("[StormcloudVideoPlayer] Using native HLS playback - VOD mode:", {
2548
2571
  isLive: this.isLiveStream,
@@ -2593,15 +2616,15 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
2593
2616
  });
2594
2617
  this.hls.on(Hls2.Events.MANIFEST_PARSED, function(_, data) {
2595
2618
  return _async_to_generator(function() {
2596
- var _ref, _this_config_minSegmentsBeforePlay, _this_hls_levels, _this_hls, prerollKey, adBehavior, minSegments, _this_video_play;
2619
+ var _this_config_isLiveStream, _ref, _this_config_minSegmentsBeforePlay, _this_hls_levels, _this_hls, prerollKey, adBehavior, minSegments, _this_video_play;
2597
2620
  return _ts_generator(this, function(_state) {
2598
2621
  switch(_state.label){
2599
2622
  case 0:
2600
- this.isLiveStream = (_ref = (_this_hls = this.hls) === null || _this_hls === void 0 ? void 0 : (_this_hls_levels = _this_hls.levels) === null || _this_hls_levels === void 0 ? void 0 : _this_hls_levels.some(function(level) {
2623
+ this.isLiveStream = (_this_config_isLiveStream = this.config.isLiveStream) !== null && _this_config_isLiveStream !== void 0 ? _this_config_isLiveStream : (_ref = (_this_hls = this.hls) === null || _this_hls === void 0 ? void 0 : (_this_hls_levels = _this_hls.levels) === null || _this_hls_levels === void 0 ? void 0 : _this_hls_levels.some(function(level) {
2601
2624
  var _level_details, _level_details1;
2602
2625
  return (level === null || level === void 0 ? void 0 : (_level_details = level.details) === null || _level_details === void 0 ? void 0 : _level_details.live) === true || (level === null || level === void 0 ? void 0 : (_level_details1 = level.details) === null || _level_details1 === void 0 ? void 0 : _level_details1.type) === "LIVE";
2603
2626
  })) !== null && _ref !== void 0 ? _ref : false;
2604
- if (!this.isLiveStream && this.vmapBreaks.length === 0 && this.apiVastTagUrl) {
2627
+ if (!this.isVmapEnabled() && !this.isLiveStream && this.vmapBreaks.length === 0 && this.apiVastTagUrl) {
2605
2628
  prerollKey = "synthetic-vod-preroll";
2606
2629
  if (!this.consumedVmapBreakIds.has(prerollKey)) {
2607
2630
  this.vmapBreaks = [
@@ -3186,12 +3209,14 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3186
3209
  _this.palNonce.sendPlaybackStart();
3187
3210
  }
3188
3211
  });
3189
- this.video.addEventListener("ended", function() {
3212
+ this.endedHandler = function() {
3190
3213
  if (_this.palPlaybackStarted) {
3191
3214
  _this.palPlaybackStarted = false;
3192
3215
  _this.palNonce.sendPlaybackEnd();
3193
3216
  }
3194
- });
3217
+ _this.onVideoEnded();
3218
+ };
3219
+ this.video.addEventListener("ended", this.endedHandler);
3195
3220
  this.video.addEventListener("mousedown", function(e) {
3196
3221
  _this.palNonce.sendAdTouch(e);
3197
3222
  });
@@ -4513,6 +4538,13 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4513
4538
  }
4514
4539
  }
4515
4540
  },
4541
+ {
4542
+ key: "isVmapEnabled",
4543
+ value: function isVmapEnabled() {
4544
+ var _this_config_vmapUrl;
4545
+ return !!(this.config.isVmap && ((_this_config_vmapUrl = this.config.vmapUrl) === null || _this_config_vmapUrl === void 0 ? void 0 : _this_config_vmapUrl.trim()));
4546
+ }
4547
+ },
4516
4548
  {
4517
4549
  key: "fetchAdConfiguration",
4518
4550
  value: function fetchAdConfiguration() {
@@ -4521,7 +4553,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4521
4553
  return _ts_generator(this, function(_state) {
4522
4554
  switch(_state.label){
4523
4555
  case 0:
4524
- if (!this.config.vmapUrl) return [
4556
+ if (!this.isVmapEnabled()) return [
4525
4557
  3,
4526
4558
  2
4527
4559
  ];
@@ -4531,7 +4563,12 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4531
4563
  ];
4532
4564
  case 1:
4533
4565
  _state.sent();
4534
- _state.label = 2;
4566
+ if (this.config.debugAdTiming) {
4567
+ console.log("[StormcloudVideoPlayer] VMAP mode enabled");
4568
+ }
4569
+ return [
4570
+ 2
4571
+ ];
4535
4572
  case 2:
4536
4573
  vastMode = this.config.vastMode || "default";
4537
4574
  if (this.config.debugAdTiming) {
@@ -4699,7 +4736,16 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4699
4736
  }
4700
4737
  return [];
4701
4738
  }
4702
- var adBreakNodes = Array.from(doc.querySelectorAll("AdBreak, vmap\\:AdBreak"));
4739
+ var VMAP_NS = "http://www.iab.net/videosuite/vmap";
4740
+ var adBreakNodes = Array.from(doc.getElementsByTagNameNS(VMAP_NS, "AdBreak"));
4741
+ if (adBreakNodes.length === 0) {
4742
+ adBreakNodes = Array.from(doc.querySelectorAll("AdBreak, vmap\\:AdBreak"));
4743
+ }
4744
+ if (adBreakNodes.length === 0) {
4745
+ adBreakNodes = Array.from(doc.getElementsByTagName("*")).filter(function(el) {
4746
+ return el.localName === "AdBreak";
4747
+ });
4748
+ }
4703
4749
  var parsed = [];
4704
4750
  adBreakNodes.forEach(function(node, index) {
4705
4751
  var timeOffsetRaw = (node.getAttribute("timeOffset") || "").trim();
@@ -4707,7 +4753,11 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4707
4753
  if (startTimeMs == null) {
4708
4754
  return;
4709
4755
  }
4710
- var adTagNode = node.querySelector("AdTagURI, vmap\\:AdTagURI");
4756
+ var adTagNode = node.getElementsByTagNameNS(VMAP_NS, "AdTagURI")[0];
4757
+ if (!adTagNode) {
4758
+ var _node_querySelector;
4759
+ adTagNode = (_node_querySelector = node.querySelector("AdTagURI, vmap\\:AdTagURI")) !== null && _node_querySelector !== void 0 ? _node_querySelector : void 0;
4760
+ }
4711
4761
  var adTagUrl = ((adTagNode === null || adTagNode === void 0 ? void 0 : adTagNode.textContent) || "").trim();
4712
4762
  if (!adTagUrl) {
4713
4763
  return;
@@ -6264,23 +6314,49 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6264
6314
  key: "onTimeUpdate",
6265
6315
  value: function onTimeUpdate(currentTimeSec) {
6266
6316
  var _this = this;
6317
+ if (!this.isVmapEnabled() || this.vmapBreaks.length === 0) {
6318
+ return;
6319
+ }
6267
6320
  if (this.adPlayer.isAdPlaying() || this.inAdBreak) return;
6268
6321
  var nowMs = currentTimeSec * 1e3;
6269
6322
  var breakToPlay = this.findBreakForTime(nowMs);
6270
6323
  if (breakToPlay) {
6271
- void this.handleMidAdJoin(breakToPlay, nowMs).catch(function(error) {
6324
+ void this.handleVmapAdBreak(breakToPlay, nowMs).catch(function(error) {
6325
+ if (_this.config.debugAdTiming) {
6326
+ console.warn("[StormcloudVideoPlayer] VMAP ad break failed gracefully:", error);
6327
+ }
6328
+ });
6329
+ }
6330
+ }
6331
+ },
6332
+ {
6333
+ key: "onVideoEnded",
6334
+ value: function onVideoEnded() {
6335
+ var _this = this;
6336
+ if (!this.isVmapEnabled() || this.vmapBreaks.length === 0) {
6337
+ return;
6338
+ }
6339
+ if (this.adPlayer.isAdPlaying() || this.inAdBreak) {
6340
+ return;
6341
+ }
6342
+ var durationMs = Number.isFinite(this.video.duration) ? Math.floor(this.video.duration * 1e3) : 0;
6343
+ var postroll = this.vmapBreaks.find(function(b) {
6344
+ return b.startTimeMs === -1 && !_this.consumedVmapBreakIds.has(_this.getAdBreakKey(b));
6345
+ });
6346
+ if (postroll) {
6347
+ void this.handleVmapAdBreak(postroll, durationMs).catch(function(error) {
6272
6348
  if (_this.config.debugAdTiming) {
6273
- console.warn("[StormcloudVideoPlayer] Mid-roll VMAP join failed gracefully:", error);
6349
+ console.warn("[StormcloudVideoPlayer] VMAP post-roll failed gracefully:", error);
6274
6350
  }
6275
6351
  });
6276
6352
  }
6277
6353
  }
6278
6354
  },
6279
6355
  {
6280
- key: "handleMidAdJoin",
6281
- value: function handleMidAdJoin(adBreak, nowMs) {
6356
+ key: "handleVmapAdBreak",
6357
+ value: function handleVmapAdBreak(adBreak, nowMs) {
6282
6358
  return _async_to_generator(function() {
6283
- var _adBreak_durationMs, _this_config_driftToleranceMs, key, breakStartMs, durationMs, endMs, tol, inWindow, remainingMs, tags, first, rest, error;
6359
+ var _adBreak_durationMs, key, breakStartMs, durationMs, endMs, inWindow, tags, first, rest, error;
6284
6360
  return _ts_generator(this, function(_state) {
6285
6361
  switch(_state.label){
6286
6362
  case 0:
@@ -6298,25 +6374,28 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6298
6374
  }
6299
6375
  durationMs = (_adBreak_durationMs = adBreak.durationMs) !== null && _adBreak_durationMs !== void 0 ? _adBreak_durationMs : 0;
6300
6376
  endMs = breakStartMs + durationMs;
6301
- tol = (_this_config_driftToleranceMs = this.config.driftToleranceMs) !== null && _this_config_driftToleranceMs !== void 0 ? _this_config_driftToleranceMs : 1e3;
6302
- inWindow = durationMs > 0 ? nowMs > breakStartMs && nowMs < endMs : nowMs + tol >= breakStartMs;
6377
+ inWindow = durationMs > 0 ? nowMs >= breakStartMs && nowMs < endMs : nowMs >= breakStartMs;
6303
6378
  if (!inWindow) return [
6304
6379
  3,
6305
6380
  4
6306
6381
  ];
6307
6382
  this.consumedVmapBreakIds.add(key);
6308
- remainingMs = durationMs > 0 ? Math.max(0, endMs - nowMs) : 0;
6309
- tags = this.selectVastTagsForBreak(adBreak) || (this.apiVastTagUrl ? [
6310
- this.apiVastTagUrl
6311
- ] : void 0);
6312
- if (!(tags && tags.length > 0)) return [
6313
- 3,
6314
- 4
6315
- ];
6383
+ tags = this.selectVastTagsForBreak(adBreak);
6384
+ if (!tags || tags.length === 0) {
6385
+ return [
6386
+ 2
6387
+ ];
6388
+ }
6316
6389
  first = tags[0];
6317
6390
  rest = tags.slice(1);
6318
6391
  this.adPodQueue = rest;
6319
6392
  this.adPlayer.updateOriginalMutedState(this.video.muted, this.video.volume);
6393
+ this.showAds = true;
6394
+ this.inAdBreak = true;
6395
+ this.currentAdBreakStartWallClockMs = Date.now();
6396
+ if (!this.video.paused) {
6397
+ this.video.pause();
6398
+ }
6320
6399
  _state.label = 1;
6321
6400
  case 1:
6322
6401
  _state.trys.push([
@@ -6331,10 +6410,6 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6331
6410
  ];
6332
6411
  case 2:
6333
6412
  _state.sent();
6334
- this.inAdBreak = true;
6335
- this.expectedAdBreakDurationMs = remainingMs;
6336
- this.currentAdBreakStartWallClockMs = Date.now();
6337
- this.scheduleAdStopCountdown(remainingMs);
6338
6413
  return [
6339
6414
  3,
6340
6415
  4
@@ -6342,8 +6417,10 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6342
6417
  case 3:
6343
6418
  error = _state.sent();
6344
6419
  this.adPodQueue = [];
6420
+ this.inAdBreak = false;
6421
+ this.showAds = false;
6345
6422
  if (this.config.debugAdTiming) {
6346
- console.warn("[StormcloudVideoPlayer] Mid-roll VMAP ad request failed:", error);
6423
+ console.warn("[StormcloudVideoPlayer] VMAP ad request failed:", error);
6347
6424
  }
6348
6425
  return [
6349
6426
  3,
@@ -7055,9 +7132,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7055
7132
  {
7056
7133
  key: "findBreakForTime",
7057
7134
  value: function findBreakForTime(nowMs) {
7058
- var _this_config_driftToleranceMs;
7059
7135
  var schedule = this.vmapBreaks;
7060
- var tol = (_this_config_driftToleranceMs = this.config.driftToleranceMs) !== null && _this_config_driftToleranceMs !== void 0 ? _this_config_driftToleranceMs : 1e3;
7061
7136
  var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
7062
7137
  try {
7063
7138
  for(var _iterator = schedule[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
@@ -7069,9 +7144,14 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7069
7144
  if (breakStartMs == null) {
7070
7145
  continue;
7071
7146
  }
7072
- var end = breakStartMs + (b.durationMs || 0);
7073
- var effectiveTol = breakStartMs === 0 ? Math.max(tol, 3e4) : tol;
7074
- if (nowMs >= breakStartMs && (b.durationMs ? nowMs < end : nowMs <= breakStartMs + effectiveTol)) {
7147
+ if (b.durationMs) {
7148
+ var end = breakStartMs + b.durationMs;
7149
+ if (nowMs >= breakStartMs && nowMs < end) {
7150
+ return b;
7151
+ }
7152
+ continue;
7153
+ }
7154
+ if (nowMs >= breakStartMs) {
7075
7155
  return b;
7076
7156
  }
7077
7157
  }
@@ -7279,6 +7359,10 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7279
7359
  this.video.removeEventListener("timeupdate", this.timeUpdateHandler);
7280
7360
  delete this.timeUpdateHandler;
7281
7361
  }
7362
+ if (this.endedHandler) {
7363
+ this.video.removeEventListener("ended", this.endedHandler);
7364
+ delete this.endedHandler;
7365
+ }
7282
7366
  if (this.emptiedHandler) {
7283
7367
  this.video.removeEventListener("emptied", this.emptiedHandler);
7284
7368
  delete this.emptiedHandler;
@@ -7307,7 +7391,9 @@ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
7307
7391
  var CRITICAL_PROPS = [
7308
7392
  "src",
7309
7393
  "allowNativeHls",
7394
+ "isLiveStream",
7310
7395
  "licenseKey",
7396
+ "isVmap",
7311
7397
  "vmapUrl",
7312
7398
  "lowLatencyMode",
7313
7399
  "driftToleranceMs",
@@ -7316,12 +7402,13 @@ var CRITICAL_PROPS = [
7316
7402
  var CONTROLS_HIDE_DELAY = 3e3;
7317
7403
  var DEFAULT_PLAYER_ASPECT_RATIO = 16 / 9;
7318
7404
  var StormcloudVideoPlayerComponent = React.memo(function(props) {
7319
- 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, vastMode = props.vastMode, vastTagUrl = props.vastTagUrl, vmapUrl = props.vmapUrl, minSegmentsBeforePlay = props.minSegmentsBeforePlay, restVideoAttrs = _object_without_properties(props, [
7405
+ var src = props.src, autoplay = props.autoplay, muted = props.muted, lowLatencyMode = props.lowLatencyMode, allowNativeHls = props.allowNativeHls, isLiveStream = props.isLiveStream, 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, vastMode = props.vastMode, vastTagUrl = props.vastTagUrl, isVmap = props.isVmap, vmapUrl = props.vmapUrl, minSegmentsBeforePlay = props.minSegmentsBeforePlay, restVideoAttrs = _object_without_properties(props, [
7320
7406
  "src",
7321
7407
  "autoplay",
7322
7408
  "muted",
7323
7409
  "lowLatencyMode",
7324
7410
  "allowNativeHls",
7411
+ "isLiveStream",
7325
7412
  "driftToleranceMs",
7326
7413
  "immediateManifestAds",
7327
7414
  "debugAdTiming",
@@ -7343,6 +7430,7 @@ var StormcloudVideoPlayerComponent = React.memo(function(props) {
7343
7430
  "licenseKey",
7344
7431
  "vastMode",
7345
7432
  "vastTagUrl",
7433
+ "isVmap",
7346
7434
  "vmapUrl",
7347
7435
  "minSegmentsBeforePlay"
7348
7436
  ]);
@@ -7475,7 +7563,7 @@ var StormcloudVideoPlayerComponent = React.memo(function(props) {
7475
7563
  setShowSpeedMenu(false);
7476
7564
  };
7477
7565
  var isHlsStream = (src === null || src === void 0 ? void 0 : src.toLowerCase().includes(".m3u8")) || (src === null || src === void 0 ? void 0 : src.toLowerCase().includes("/hls/"));
7478
- var shouldShowEnhancedControls = showCustomControls && (isHlsStream ? allowNativeHls : true);
7566
+ var shouldShowEnhancedControls = showCustomControls && (isHlsStream ? allowNativeHls || isLiveStream === false : true);
7479
7567
  var criticalPropsKey = useMemo(function() {
7480
7568
  return CRITICAL_PROPS.map(function(prop) {
7481
7569
  return "".concat(prop, ":").concat(props[prop]);
@@ -7483,7 +7571,9 @@ var StormcloudVideoPlayerComponent = React.memo(function(props) {
7483
7571
  }, [
7484
7572
  src,
7485
7573
  allowNativeHls,
7574
+ isLiveStream,
7486
7575
  licenseKey,
7576
+ isVmap,
7487
7577
  vmapUrl,
7488
7578
  lowLatencyMode,
7489
7579
  driftToleranceMs,
@@ -7517,6 +7607,7 @@ var StormcloudVideoPlayerComponent = React.memo(function(props) {
7517
7607
  if (muted !== void 0) cfg.muted = muted;
7518
7608
  if (lowLatencyMode !== void 0) cfg.lowLatencyMode = lowLatencyMode;
7519
7609
  if (allowNativeHls !== void 0) cfg.allowNativeHls = allowNativeHls;
7610
+ if (isLiveStream !== void 0) cfg.isLiveStream = isLiveStream;
7520
7611
  if (driftToleranceMs !== void 0) cfg.driftToleranceMs = driftToleranceMs;
7521
7612
  if (immediateManifestAds !== void 0) cfg.immediateManifestAds = immediateManifestAds;
7522
7613
  if (debugAdTiming !== void 0) cfg.debugAdTiming = debugAdTiming;
@@ -7527,6 +7618,7 @@ var StormcloudVideoPlayerComponent = React.memo(function(props) {
7527
7618
  if (licenseKey !== void 0) cfg.licenseKey = licenseKey;
7528
7619
  if (vastMode !== void 0) cfg.vastMode = vastMode;
7529
7620
  if (vastTagUrl !== void 0) cfg.vastTagUrl = vastTagUrl;
7621
+ if (isVmap !== void 0) cfg.isVmap = isVmap;
7530
7622
  if (vmapUrl !== void 0) cfg.vmapUrl = vmapUrl;
7531
7623
  if (minSegmentsBeforePlay !== void 0) cfg.minSegmentsBeforePlay = minSegmentsBeforePlay;
7532
7624
  var player = new StormcloudVideoPlayer(cfg);
@@ -8355,161 +8447,202 @@ var StormcloudVideoPlayerComponent = React.memo(function(props) {
8355
8447
  ]
8356
8448
  })
8357
8449
  ]
8358
- }) : showCustomControls && !showLicenseWarning && /* @__PURE__ */ jsxs("div", {
8359
- className: "sc-controls-bar",
8360
- style: {
8361
- position: "absolute",
8362
- bottom: "".concat(10 * responsiveScale, "px"),
8363
- right: "".concat(10 * responsiveScale, "px"),
8364
- display: "flex",
8365
- flexDirection: isPortrait ? "column" : "row",
8366
- gap: "".concat(8 * responsiveScale, "px"),
8367
- zIndex: 10,
8368
- opacity: controlsVisible ? 1 : 0,
8369
- transform: controlsVisible ? "translateY(0)" : "translateY(4px)",
8370
- pointerEvents: controlsVisible ? "auto" : "none"
8371
- },
8450
+ }) : showCustomControls && !showLicenseWarning && /* @__PURE__ */ jsxs(Fragment, {
8372
8451
  children: [
8373
8452
  /* @__PURE__ */ jsxs("div", {
8374
8453
  style: {
8454
+ position: "absolute",
8455
+ top: "".concat(10 * responsiveScale, "px"),
8456
+ left: "".concat(10 * responsiveScale, "px"),
8375
8457
  display: "flex",
8376
8458
  alignItems: "center",
8377
- background: "rgba(0, 0, 0, 0.6)",
8378
- borderRadius: "".concat(18 * responsiveScale, "px"),
8379
- padding: "2px",
8380
- paddingRight: "".concat(8 * responsiveScale, "px")
8459
+ gap: "6px",
8460
+ zIndex: 10,
8461
+ opacity: controlsVisible ? 1 : 0,
8462
+ transition: "opacity 0.35s ease"
8381
8463
  },
8382
- onMouseEnter: function onMouseEnter() {
8383
- return setShowVolumeSlider(true);
8384
- },
8385
- onMouseLeave: function onMouseLeave() {
8386
- return setShowVolumeSlider(false);
8464
+ children: [
8465
+ /* @__PURE__ */ jsx("div", {
8466
+ style: {
8467
+ width: "8px",
8468
+ height: "8px",
8469
+ borderRadius: "50%",
8470
+ background: "#ff3b30",
8471
+ animation: "sc-pulse 1.5s ease-in-out infinite",
8472
+ flexShrink: 0
8473
+ }
8474
+ }),
8475
+ /* @__PURE__ */ jsx("span", {
8476
+ style: {
8477
+ fontSize: "".concat(12 * responsiveScale, "px"),
8478
+ fontFamily: "'SF Pro Display', 'Segoe UI', Arial, sans-serif",
8479
+ fontWeight: 700,
8480
+ letterSpacing: "0.08em",
8481
+ color: "#fff",
8482
+ textShadow: "0 1px 3px rgba(0,0,0,0.6)",
8483
+ userSelect: "none"
8484
+ },
8485
+ children: "LIVE"
8486
+ })
8487
+ ]
8488
+ }),
8489
+ /* @__PURE__ */ jsxs("div", {
8490
+ className: "sc-controls-bar",
8491
+ style: {
8492
+ position: "absolute",
8493
+ bottom: "".concat(10 * responsiveScale, "px"),
8494
+ right: "".concat(10 * responsiveScale, "px"),
8495
+ display: "flex",
8496
+ flexDirection: isPortrait ? "column" : "row",
8497
+ gap: "".concat(8 * responsiveScale, "px"),
8498
+ zIndex: 10,
8499
+ opacity: controlsVisible ? 1 : 0,
8500
+ transform: controlsVisible ? "translateY(0)" : "translateY(4px)",
8501
+ pointerEvents: controlsVisible ? "auto" : "none"
8387
8502
  },
8388
8503
  children: [
8504
+ /* @__PURE__ */ jsxs("div", {
8505
+ style: {
8506
+ display: "flex",
8507
+ alignItems: "center",
8508
+ background: "rgba(0, 0, 0, 0.6)",
8509
+ borderRadius: "".concat(18 * responsiveScale, "px"),
8510
+ padding: "2px",
8511
+ paddingRight: "".concat(8 * responsiveScale, "px")
8512
+ },
8513
+ onMouseEnter: function onMouseEnter() {
8514
+ return setShowVolumeSlider(true);
8515
+ },
8516
+ onMouseLeave: function onMouseLeave() {
8517
+ return setShowVolumeSlider(false);
8518
+ },
8519
+ children: [
8520
+ /* @__PURE__ */ jsx("button", {
8521
+ className: "sc-ctrl-btn",
8522
+ onClick: function onClick() {
8523
+ if (playerRef.current) playerRef.current.toggleMute();
8524
+ onVolumeToggle === null || onVolumeToggle === void 0 ? void 0 : onVolumeToggle();
8525
+ resetControlsTimer();
8526
+ },
8527
+ style: {
8528
+ padding: "".concat(8 * responsiveScale, "px"),
8529
+ borderRadius: "50%",
8530
+ minWidth: "".concat(36 * responsiveScale, "px"),
8531
+ minHeight: "".concat(36 * responsiveScale, "px")
8532
+ },
8533
+ title: isMuted ? "Unmute" : "Mute",
8534
+ children: /* @__PURE__ */ jsx(VolumeIcon, {
8535
+ size: Math.max(14, 18 * responsiveScale)
8536
+ })
8537
+ }),
8538
+ /* @__PURE__ */ jsx("div", {
8539
+ style: {
8540
+ width: showVolumeSlider ? "".concat(68 * responsiveScale, "px") : "0px",
8541
+ overflow: "hidden",
8542
+ transition: "width 0.2s cubic-bezier(0.4, 0, 0.2, 1)",
8543
+ display: "flex",
8544
+ alignItems: "center",
8545
+ paddingLeft: showVolumeSlider ? "".concat(3 * responsiveScale, "px") : "0",
8546
+ paddingRight: showVolumeSlider ? "".concat(10 * responsiveScale, "px") : "0"
8547
+ },
8548
+ children: /* @__PURE__ */ jsxs("div", {
8549
+ style: {
8550
+ position: "relative",
8551
+ width: "".concat(56 * responsiveScale, "px"),
8552
+ height: "3px",
8553
+ cursor: "pointer",
8554
+ borderRadius: "1.5px"
8555
+ },
8556
+ onMouseDown: function onMouseDown(e) {
8557
+ e.preventDefault();
8558
+ var el = e.currentTarget;
8559
+ var move = function move(ev) {
8560
+ var r2 = el.getBoundingClientRect();
8561
+ handleVolumeChange(Math.max(0, Math.min(1, (ev.clientX - r2.left) / r2.width)));
8562
+ };
8563
+ var up = function up1() {
8564
+ document.removeEventListener("mousemove", move);
8565
+ document.removeEventListener("mouseup", up);
8566
+ };
8567
+ document.addEventListener("mousemove", move);
8568
+ document.addEventListener("mouseup", up);
8569
+ var r = el.getBoundingClientRect();
8570
+ handleVolumeChange(Math.max(0, Math.min(1, (e.clientX - r.left) / r.width)));
8571
+ },
8572
+ onClick: function onClick(e) {
8573
+ e.stopPropagation();
8574
+ var r = e.currentTarget.getBoundingClientRect();
8575
+ handleVolumeChange(Math.max(0, Math.min(1, (e.clientX - r.left) / r.width)));
8576
+ },
8577
+ children: [
8578
+ /* @__PURE__ */ jsx("div", {
8579
+ style: {
8580
+ position: "absolute",
8581
+ inset: 0,
8582
+ background: "rgba(255, 255, 255, 0.2)",
8583
+ borderRadius: "1.5px"
8584
+ }
8585
+ }),
8586
+ /* @__PURE__ */ jsx("div", {
8587
+ style: {
8588
+ position: "absolute",
8589
+ top: 0,
8590
+ left: 0,
8591
+ bottom: 0,
8592
+ width: "".concat((isMuted ? 0 : volume) * 100, "%"),
8593
+ background: "#fff",
8594
+ borderRadius: "1.5px",
8595
+ transition: "width 0.1s ease-out"
8596
+ }
8597
+ }),
8598
+ /* @__PURE__ */ jsx("div", {
8599
+ style: {
8600
+ position: "absolute",
8601
+ top: "50%",
8602
+ left: "".concat((isMuted ? 0 : volume) * 100, "%"),
8603
+ transform: "translate(-50%, -50%)",
8604
+ width: "12px",
8605
+ height: "12px",
8606
+ background: "#fff",
8607
+ borderRadius: "50%",
8608
+ boxShadow: "0 0 3px rgba(0, 0, 0, 0.3)",
8609
+ transition: "left 0.1s ease-out"
8610
+ }
8611
+ })
8612
+ ]
8613
+ })
8614
+ })
8615
+ ]
8616
+ }),
8389
8617
  /* @__PURE__ */ jsx("button", {
8390
8618
  className: "sc-ctrl-btn",
8391
8619
  onClick: function onClick() {
8392
- if (playerRef.current) playerRef.current.toggleMute();
8393
- onVolumeToggle === null || onVolumeToggle === void 0 ? void 0 : onVolumeToggle();
8620
+ if (onFullscreenToggle) {
8621
+ onFullscreenToggle();
8622
+ } else if (wrapperRef.current) {
8623
+ if (!document.fullscreenElement) {
8624
+ wrapperRef.current.requestFullscreen().catch(function() {});
8625
+ } else {
8626
+ document.exitFullscreen().catch(function() {});
8627
+ }
8628
+ }
8394
8629
  resetControlsTimer();
8395
8630
  },
8396
8631
  style: {
8397
8632
  padding: "".concat(8 * responsiveScale, "px"),
8398
8633
  borderRadius: "50%",
8399
8634
  minWidth: "".concat(36 * responsiveScale, "px"),
8400
- minHeight: "".concat(36 * responsiveScale, "px")
8635
+ minHeight: "".concat(36 * responsiveScale, "px"),
8636
+ background: "rgba(0, 0, 0, 0.6)"
8401
8637
  },
8402
- title: isMuted ? "Unmute" : "Mute",
8403
- children: /* @__PURE__ */ jsx(VolumeIcon, {
8638
+ title: isFullscreen ? "Exit Fullscreen" : "Enter Fullscreen",
8639
+ children: isFullscreen ? /* @__PURE__ */ jsx(FaCompress, {
8640
+ size: Math.max(14, 18 * responsiveScale)
8641
+ }) : /* @__PURE__ */ jsx(FaExpand, {
8404
8642
  size: Math.max(14, 18 * responsiveScale)
8405
- })
8406
- }),
8407
- /* @__PURE__ */ jsx("div", {
8408
- style: {
8409
- width: showVolumeSlider ? "".concat(68 * responsiveScale, "px") : "0px",
8410
- overflow: "hidden",
8411
- transition: "width 0.2s cubic-bezier(0.4, 0, 0.2, 1)",
8412
- display: "flex",
8413
- alignItems: "center",
8414
- paddingLeft: showVolumeSlider ? "".concat(3 * responsiveScale, "px") : "0",
8415
- paddingRight: showVolumeSlider ? "".concat(10 * responsiveScale, "px") : "0"
8416
- },
8417
- children: /* @__PURE__ */ jsxs("div", {
8418
- style: {
8419
- position: "relative",
8420
- width: "".concat(56 * responsiveScale, "px"),
8421
- height: "3px",
8422
- cursor: "pointer",
8423
- borderRadius: "1.5px"
8424
- },
8425
- onMouseDown: function onMouseDown(e) {
8426
- e.preventDefault();
8427
- var el = e.currentTarget;
8428
- var move = function move(ev) {
8429
- var r2 = el.getBoundingClientRect();
8430
- handleVolumeChange(Math.max(0, Math.min(1, (ev.clientX - r2.left) / r2.width)));
8431
- };
8432
- var up = function up1() {
8433
- document.removeEventListener("mousemove", move);
8434
- document.removeEventListener("mouseup", up);
8435
- };
8436
- document.addEventListener("mousemove", move);
8437
- document.addEventListener("mouseup", up);
8438
- var r = el.getBoundingClientRect();
8439
- handleVolumeChange(Math.max(0, Math.min(1, (e.clientX - r.left) / r.width)));
8440
- },
8441
- onClick: function onClick(e) {
8442
- e.stopPropagation();
8443
- var r = e.currentTarget.getBoundingClientRect();
8444
- handleVolumeChange(Math.max(0, Math.min(1, (e.clientX - r.left) / r.width)));
8445
- },
8446
- children: [
8447
- /* @__PURE__ */ jsx("div", {
8448
- style: {
8449
- position: "absolute",
8450
- inset: 0,
8451
- background: "rgba(255, 255, 255, 0.2)",
8452
- borderRadius: "1.5px"
8453
- }
8454
- }),
8455
- /* @__PURE__ */ jsx("div", {
8456
- style: {
8457
- position: "absolute",
8458
- top: 0,
8459
- left: 0,
8460
- bottom: 0,
8461
- width: "".concat((isMuted ? 0 : volume) * 100, "%"),
8462
- background: "#fff",
8463
- borderRadius: "1.5px",
8464
- transition: "width 0.1s ease-out"
8465
- }
8466
- }),
8467
- /* @__PURE__ */ jsx("div", {
8468
- style: {
8469
- position: "absolute",
8470
- top: "50%",
8471
- left: "".concat((isMuted ? 0 : volume) * 100, "%"),
8472
- transform: "translate(-50%, -50%)",
8473
- width: "12px",
8474
- height: "12px",
8475
- background: "#fff",
8476
- borderRadius: "50%",
8477
- boxShadow: "0 0 3px rgba(0, 0, 0, 0.3)",
8478
- transition: "left 0.1s ease-out"
8479
- }
8480
- })
8481
- ]
8482
8643
  })
8483
8644
  })
8484
8645
  ]
8485
- }),
8486
- /* @__PURE__ */ jsx("button", {
8487
- className: "sc-ctrl-btn",
8488
- onClick: function onClick() {
8489
- if (onFullscreenToggle) {
8490
- onFullscreenToggle();
8491
- } else if (wrapperRef.current) {
8492
- if (!document.fullscreenElement) {
8493
- wrapperRef.current.requestFullscreen().catch(function() {});
8494
- } else {
8495
- document.exitFullscreen().catch(function() {});
8496
- }
8497
- }
8498
- resetControlsTimer();
8499
- },
8500
- style: {
8501
- padding: "".concat(8 * responsiveScale, "px"),
8502
- borderRadius: "50%",
8503
- minWidth: "".concat(36 * responsiveScale, "px"),
8504
- minHeight: "".concat(36 * responsiveScale, "px"),
8505
- background: "rgba(0, 0, 0, 0.6)"
8506
- },
8507
- title: isFullscreen ? "Exit Fullscreen" : "Enter Fullscreen",
8508
- children: isFullscreen ? /* @__PURE__ */ jsx(FaCompress, {
8509
- size: Math.max(14, 18 * responsiveScale)
8510
- }) : /* @__PURE__ */ jsx(FaExpand, {
8511
- size: Math.max(14, 18 * responsiveScale)
8512
- })
8513
8646
  })
8514
8647
  ]
8515
8648
  }),
@@ -8648,6 +8781,7 @@ var defaultProps = {
8648
8781
  showCustomControls: false,
8649
8782
  hideLoadingIndicator: false,
8650
8783
  licenseKey: "",
8784
+ isVmap: false,
8651
8785
  vmapUrl: "",
8652
8786
  adFailsafeTimeoutMs: 1e4,
8653
8787
  minSegmentsBeforePlay: 2,
@@ -9595,6 +9729,7 @@ var SUPPORTED_PROPS = [
9595
9729
  "debugAdTiming",
9596
9730
  "showCustomControls",
9597
9731
  "licenseKey",
9732
+ "isVmap",
9598
9733
  "vmapUrl",
9599
9734
  "adFailsafeTimeoutMs",
9600
9735
  "minSegmentsBeforePlay",
@@ -9783,5 +9918,5 @@ var createStormcloudPlayer = function createStormcloudPlayer(playerList, fallbac
9783
9918
  };
9784
9919
  var StormcloudPlayer = createStormcloudPlayer(players_default, players_default[players_default.length - 1]);
9785
9920
  var StormcloudPlayer_default = StormcloudPlayer;
9786
- export { IS_BROWSER, IS_GLOBAL, IS_IOS, IS_SAFARI, SUPPORTS_DASH, SUPPORTS_HLS, StormcloudPlayer_default as StormcloudPlayer, StormcloudVideoPlayer, StormcloudVideoPlayerComponent, canPlay, createHlsAdPlayer, createPalNonceManager, createStormcloudPlayer, StormcloudVideoPlayerComponent as default, detectBrowser, getBrowserConfigOverrides, getBrowserID, getClientInfo, initializePolyfills, isMediaStream, lazy, logBrowserInfo, merge, omit, parseQuery, players_default as players, randomString, sendAdDetectTracking, sendAdImpressionTracking, sendAdLoadedTracking, sendHeartbeat, sendInitialTracking, supportsFeature, supportsModernJS, supportsWebKitPresentationMode };
9921
+ export { DEFAULT_MQTT_CONFIG, IS_BROWSER, IS_GLOBAL, IS_IOS, IS_SAFARI, MQTT_CA_CERT_FILE, SUPPORTS_DASH, SUPPORTS_HLS, StormcloudPlayer_default as StormcloudPlayer, StormcloudVideoPlayer, StormcloudVideoPlayerComponent, applyMQTTConfig, buildMQTTBrokerUrl, buildPlayerTopic, canPlay, configureMQTT, createHlsAdPlayer, createPalNonceManager, createStormcloudPlayer, StormcloudVideoPlayerComponent as default, detectBrowser, disconnectMQTT, ensureMQTTClient, getBrowserConfigOverrides, getBrowserID, getClientInfo, getMQTTStatus, initMQTTClient, initializePolyfills, isMQTTConfigured, isMQTTConnected, isMQTTEnabled, isMediaStream, lazy, logBrowserInfo, merge, mqttConfig, omit, parseQuery, players_default as players, publishMQTT, randomString, sendAdDetectTracking, sendAdImpressionTracking, sendAdLoadedTracking, sendHeartbeat, sendInitialTracking, supportsFeature, supportsModernJS, supportsWebKitPresentationMode };
9787
9922
  //# sourceMappingURL=index.js.map