stormcloud-video-player 0.3.54 → 0.3.56

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.cjs CHANGED
@@ -512,6 +512,15 @@ __export(index_exports, {
512
512
  randomString: function randomString1() {
513
513
  return randomString;
514
514
  },
515
+ sendAdDetectTracking: function sendAdDetectTracking1() {
516
+ return sendAdDetectTracking;
517
+ },
518
+ sendAdImpressionTracking: function sendAdImpressionTracking1() {
519
+ return sendAdImpressionTracking;
520
+ },
521
+ sendAdLoadedTracking: function sendAdLoadedTracking1() {
522
+ return sendAdLoadedTracking;
523
+ },
515
524
  sendHeartbeat: function sendHeartbeat1() {
516
525
  return sendHeartbeat;
517
526
  },
@@ -2826,9 +2835,6 @@ function sendInitialTracking(licenseKey) {
2826
2835
  headers = {
2827
2836
  "Content-Type": "application/json"
2828
2837
  };
2829
- if (licenseKey) {
2830
- headers["Authorization"] = "Bearer ".concat(licenseKey);
2831
- }
2832
2838
  return [
2833
2839
  4,
2834
2840
  fetch("https://adstorm.co/api-adstorm-dev/adstorm/player-tracking/track", {
@@ -2934,6 +2940,234 @@ function sendHeartbeat(licenseKey) {
2934
2940
  });
2935
2941
  })();
2936
2942
  }
2943
+ var TRACK_API_URL = "https://adstorm.co/api-adstorm-dev/adstorm/player-tracking/track";
2944
+ function mapToAdTrackingSource(source, adPlayerType) {
2945
+ if (source === "prebid" || source === "ima" || source === "hls") {
2946
+ return source;
2947
+ }
2948
+ if (source === "preload" || source === "ssp") {
2949
+ return source === "ssp" ? "prebid" : "ima";
2950
+ }
2951
+ return adPlayerType === "hls" ? "hls" : "ima";
2952
+ }
2953
+ function postAdTracking(licenseKey, body) {
2954
+ return _async_to_generator(function() {
2955
+ var headers, response;
2956
+ return _ts_generator(this, function(_state) {
2957
+ switch(_state.label){
2958
+ case 0:
2959
+ headers = {
2960
+ "Content-Type": "application/json"
2961
+ };
2962
+ if (licenseKey) {
2963
+ headers["Authorization"] = "Bearer ".concat(licenseKey);
2964
+ }
2965
+ return [
2966
+ 4,
2967
+ fetch(TRACK_API_URL, {
2968
+ method: "POST",
2969
+ headers: headers,
2970
+ body: JSON.stringify(body)
2971
+ })
2972
+ ];
2973
+ case 1:
2974
+ response = _state.sent();
2975
+ if (!response.ok) {
2976
+ throw new Error("HTTP error! status: ".concat(response.status));
2977
+ }
2978
+ return [
2979
+ 4,
2980
+ response.json()
2981
+ ];
2982
+ case 2:
2983
+ _state.sent();
2984
+ return [
2985
+ 2
2986
+ ];
2987
+ }
2988
+ });
2989
+ })();
2990
+ }
2991
+ function sendAdDetectTracking(licenseKey, payload) {
2992
+ return _async_to_generator(function() {
2993
+ var _payload_source, _payload_timestamp, clientInfo, browserId, adDetectInfo, body, error;
2994
+ return _ts_generator(this, function(_state) {
2995
+ switch(_state.label){
2996
+ case 0:
2997
+ _state.trys.push([
2998
+ 0,
2999
+ 3,
3000
+ ,
3001
+ 4
3002
+ ]);
3003
+ clientInfo = getClientInfo();
3004
+ return [
3005
+ 4,
3006
+ getBrowserID(clientInfo)
3007
+ ];
3008
+ case 1:
3009
+ browserId = _state.sent();
3010
+ adDetectInfo = _object_spread({
3011
+ source: (_payload_source = payload.source) !== null && _payload_source !== void 0 ? _payload_source : "scte35",
3012
+ timestamp: (_payload_timestamp = payload.timestamp) !== null && _payload_timestamp !== void 0 ? _payload_timestamp : /* @__PURE__ */ new Date().toISOString()
3013
+ }, payload.durationSeconds != null && {
3014
+ durationSeconds: payload.durationSeconds
3015
+ }, payload.ptsSeconds != null && {
3016
+ ptsSeconds: payload.ptsSeconds
3017
+ }, payload.detectedAtFragmentSn != null && {
3018
+ detectedAtFragmentSn: payload.detectedAtFragmentSn
3019
+ });
3020
+ body = _object_spread_props(_object_spread({
3021
+ browserId: browserId
3022
+ }, clientInfo, licenseKey && {
3023
+ licenseKey: licenseKey
3024
+ }), {
3025
+ adDetectInfo: adDetectInfo
3026
+ });
3027
+ return [
3028
+ 4,
3029
+ postAdTracking(licenseKey, body)
3030
+ ];
3031
+ case 2:
3032
+ _state.sent();
3033
+ return [
3034
+ 3,
3035
+ 4
3036
+ ];
3037
+ case 3:
3038
+ error = _state.sent();
3039
+ console.error("[StormcloudVideoPlayer] Error sending ad-detect tracking:", error);
3040
+ return [
3041
+ 3,
3042
+ 4
3043
+ ];
3044
+ case 4:
3045
+ return [
3046
+ 2
3047
+ ];
3048
+ }
3049
+ });
3050
+ })();
3051
+ }
3052
+ function sendAdLoadedTracking(licenseKey, payload, adPlayerType) {
3053
+ return _async_to_generator(function() {
3054
+ var clientInfo, browserId, source, adLoadedInfo, body, error;
3055
+ return _ts_generator(this, function(_state) {
3056
+ switch(_state.label){
3057
+ case 0:
3058
+ _state.trys.push([
3059
+ 0,
3060
+ 3,
3061
+ ,
3062
+ 4
3063
+ ]);
3064
+ clientInfo = getClientInfo();
3065
+ return [
3066
+ 4,
3067
+ getBrowserID(clientInfo)
3068
+ ];
3069
+ case 1:
3070
+ browserId = _state.sent();
3071
+ source = mapToAdTrackingSource(payload.source, adPlayerType);
3072
+ adLoadedInfo = _object_spread({
3073
+ source: source,
3074
+ timestamp: /* @__PURE__ */ new Date().toISOString()
3075
+ }, payload.vastUrl != null && {
3076
+ vastUrl: payload.vastUrl
3077
+ }, payload.durationSeconds != null && {
3078
+ durationSeconds: payload.durationSeconds
3079
+ });
3080
+ body = _object_spread_props(_object_spread({
3081
+ browserId: browserId
3082
+ }, clientInfo, licenseKey && {
3083
+ licenseKey: licenseKey
3084
+ }), {
3085
+ adLoadedInfo: adLoadedInfo
3086
+ });
3087
+ return [
3088
+ 4,
3089
+ postAdTracking(licenseKey, body)
3090
+ ];
3091
+ case 2:
3092
+ _state.sent();
3093
+ return [
3094
+ 3,
3095
+ 4
3096
+ ];
3097
+ case 3:
3098
+ error = _state.sent();
3099
+ console.error("[StormcloudVideoPlayer] Error sending ad-loaded tracking:", error);
3100
+ return [
3101
+ 3,
3102
+ 4
3103
+ ];
3104
+ case 4:
3105
+ return [
3106
+ 2
3107
+ ];
3108
+ }
3109
+ });
3110
+ })();
3111
+ }
3112
+ function sendAdImpressionTracking(licenseKey, payload, adPlayerType) {
3113
+ return _async_to_generator(function() {
3114
+ var clientInfo, browserId, source, adImpressionInfo, body, error;
3115
+ return _ts_generator(this, function(_state) {
3116
+ switch(_state.label){
3117
+ case 0:
3118
+ _state.trys.push([
3119
+ 0,
3120
+ 3,
3121
+ ,
3122
+ 4
3123
+ ]);
3124
+ clientInfo = getClientInfo();
3125
+ return [
3126
+ 4,
3127
+ getBrowserID(clientInfo)
3128
+ ];
3129
+ case 1:
3130
+ browserId = _state.sent();
3131
+ source = mapToAdTrackingSource(payload.source, adPlayerType);
3132
+ adImpressionInfo = _object_spread({
3133
+ source: source,
3134
+ adIndex: payload.adIndex,
3135
+ timestamp: /* @__PURE__ */ new Date().toISOString()
3136
+ }, payload.durationSeconds != null && {
3137
+ durationSeconds: payload.durationSeconds
3138
+ });
3139
+ body = _object_spread_props(_object_spread({
3140
+ browserId: browserId
3141
+ }, clientInfo, licenseKey && {
3142
+ licenseKey: licenseKey
3143
+ }), {
3144
+ adImpressionInfo: adImpressionInfo
3145
+ });
3146
+ return [
3147
+ 4,
3148
+ postAdTracking(licenseKey, body)
3149
+ ];
3150
+ case 2:
3151
+ _state.sent();
3152
+ return [
3153
+ 3,
3154
+ 4
3155
+ ];
3156
+ case 3:
3157
+ error = _state.sent();
3158
+ console.error("[StormcloudVideoPlayer] Error sending ad-impression tracking:", error);
3159
+ return [
3160
+ 3,
3161
+ 4
3162
+ ];
3163
+ case 4:
3164
+ return [
3165
+ 2
3166
+ ];
3167
+ }
3168
+ });
3169
+ })();
3170
+ }
2937
3171
  // src/utils/polyfills.ts
2938
3172
  function polyfillURLSearchParams() {
2939
3173
  if (typeof URLSearchParams !== "undefined") {
@@ -3193,6 +3427,8 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3193
3427
  this.inAdBreak = false;
3194
3428
  this.ptsDriftEmaMs = 0;
3195
3429
  this.adPodQueue = [];
3430
+ this.vmapBreaks = [];
3431
+ this.consumedVmapBreakIds = /* @__PURE__ */ new Set();
3196
3432
  this.lastHeartbeatTime = 0;
3197
3433
  this.currentAdIndex = 0;
3198
3434
  this.totalAdsInBreak = 0;
@@ -3234,6 +3470,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3234
3470
  this.maxPreloadPoolSize = 2;
3235
3471
  this.preloadPoolActive = false;
3236
3472
  this.preloadPoolLoopRunning = false;
3473
+ this.adDetectSentForCurrentBreak = false;
3237
3474
  this.continuousFetchLoopRunning = false;
3238
3475
  initializePolyfills();
3239
3476
  var browserOverrides = getBrowserConfigOverrides();
@@ -3703,6 +3940,9 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3703
3940
  value: function attachImaEventListeners() {
3704
3941
  var _this = this;
3705
3942
  this.ima.on("all_ads_completed", function() {
3943
+ sendAdImpressionTracking(_this.config.licenseKey, {
3944
+ adIndex: _this.currentAdIndex
3945
+ }, _this.config.adPlayerType).catch(function() {});
3706
3946
  var remaining = _this.getRemainingAdMs();
3707
3947
  _this.consecutiveFailures = 0;
3708
3948
  if (_this.config.debugAdTiming) {
@@ -3765,6 +4005,9 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3765
4005
  }
3766
4006
  });
3767
4007
  this.ima.on("content_resume", function() {
4008
+ sendAdImpressionTracking(_this.config.licenseKey, {
4009
+ adIndex: _this.currentAdIndex
4010
+ }, _this.config.adPlayerType).catch(function() {});
3768
4011
  if (!_this.video.muted) {
3769
4012
  _this.video.muted = true;
3770
4013
  _this.video.volume = 0;
@@ -4148,6 +4391,13 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4148
4391
  }
4149
4392
  return;
4150
4393
  }
4394
+ if (!this.adDetectSentForCurrentBreak) {
4395
+ this.adDetectSentForCurrentBreak = true;
4396
+ var detectPayload = {};
4397
+ if (marker.durationSeconds != null) detectPayload.durationSeconds = marker.durationSeconds;
4398
+ if (marker.ptsSeconds != null) detectPayload.ptsSeconds = marker.ptsSeconds;
4399
+ sendAdDetectTracking(this.config.licenseKey, detectPayload).catch(function() {});
4400
+ }
4151
4401
  var hasPrefetchedAds = this.pendingAdBreak && this.pendingAdBreak.vastUrls.length > 0;
4152
4402
  this.inAdBreak = true;
4153
4403
  var durationMs = marker.durationSeconds != null ? marker.durationSeconds * 1e3 : ((_this_pendingAdBreak = this.pendingAdBreak) === null || _this_pendingAdBreak === void 0 ? void 0 : _this_pendingAdBreak.marker.durationSeconds) != null ? this.pendingAdBreak.marker.durationSeconds * 1e3 : void 0;
@@ -4507,6 +4757,18 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4507
4757
  return _ts_generator(this, function(_state) {
4508
4758
  switch(_state.label){
4509
4759
  case 0:
4760
+ if (!this.config.vmapUrl) return [
4761
+ 3,
4762
+ 2
4763
+ ];
4764
+ return [
4765
+ 4,
4766
+ this.fetchAndParseVmap(this.config.vmapUrl)
4767
+ ];
4768
+ case 1:
4769
+ _state.sent();
4770
+ _state.label = 2;
4771
+ case 2:
4510
4772
  vastMode = this.config.vastMode || "default";
4511
4773
  if (this.config.debugAdTiming) {
4512
4774
  console.log("[StormcloudVideoPlayer] VAST mode:", vastMode);
@@ -4552,7 +4814,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4552
4814
  headers: headers
4553
4815
  })
4554
4816
  ];
4555
- case 1:
4817
+ case 3:
4556
4818
  response = _state.sent();
4557
4819
  if (!response.ok) {
4558
4820
  if (this.config.debugAdTiming) {
@@ -4566,7 +4828,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4566
4828
  4,
4567
4829
  response.json()
4568
4830
  ];
4569
- case 2:
4831
+ case 4:
4570
4832
  data = _state.sent();
4571
4833
  imaPayload = (_data_response = data.response) === null || _data_response === void 0 ? void 0 : (_data_response_ima = _data_response.ima) === null || _data_response_ima === void 0 ? void 0 : (_data_response_ima_publisherdeskima = _data_response_ima["publisherdesk.ima"]) === null || _data_response_ima_publisherdeskima === void 0 ? void 0 : _data_response_ima_publisherdeskima.payload;
4572
4834
  if (imaPayload) {
@@ -4595,32 +4857,197 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4595
4857
  }
4596
4858
  },
4597
4859
  {
4598
- key: "getCurrentAdIndex",
4599
- value: function getCurrentAdIndex() {
4600
- return this.currentAdIndex;
4860
+ key: "fetchAndParseVmap",
4861
+ value: function fetchAndParseVmap(vmapUrl) {
4862
+ return _async_to_generator(function() {
4863
+ var response, vmapXml, error;
4864
+ return _ts_generator(this, function(_state) {
4865
+ switch(_state.label){
4866
+ case 0:
4867
+ if (!vmapUrl.trim()) {
4868
+ return [
4869
+ 2
4870
+ ];
4871
+ }
4872
+ _state.label = 1;
4873
+ case 1:
4874
+ _state.trys.push([
4875
+ 1,
4876
+ 4,
4877
+ ,
4878
+ 5
4879
+ ]);
4880
+ return [
4881
+ 4,
4882
+ fetch(vmapUrl)
4883
+ ];
4884
+ case 2:
4885
+ response = _state.sent();
4886
+ if (!response.ok) {
4887
+ throw new Error("Failed to fetch VMAP (".concat(response.status, ")"));
4888
+ }
4889
+ return [
4890
+ 4,
4891
+ response.text()
4892
+ ];
4893
+ case 3:
4894
+ vmapXml = _state.sent();
4895
+ this.vmapBreaks = this.parseVmapToBreaks(vmapXml);
4896
+ this.consumedVmapBreakIds.clear();
4897
+ if (this.config.debugAdTiming) {
4898
+ console.log("[StormcloudVideoPlayer] Loaded ".concat(this.vmapBreaks.length, " VMAP ad break(s) from:"), vmapUrl);
4899
+ }
4900
+ return [
4901
+ 3,
4902
+ 5
4903
+ ];
4904
+ case 4:
4905
+ error = _state.sent();
4906
+ this.vmapBreaks = [];
4907
+ this.consumedVmapBreakIds.clear();
4908
+ if (this.config.debugAdTiming) {
4909
+ console.warn("[StormcloudVideoPlayer] Failed to load VMAP:", error);
4910
+ }
4911
+ return [
4912
+ 3,
4913
+ 5
4914
+ ];
4915
+ case 5:
4916
+ return [
4917
+ 2
4918
+ ];
4919
+ }
4920
+ });
4921
+ }).call(this);
4601
4922
  }
4602
4923
  },
4603
4924
  {
4604
- key: "getTotalAdsInBreak",
4605
- value: function getTotalAdsInBreak() {
4606
- return this.totalAdsInBreak;
4925
+ key: "parseVmapToBreaks",
4926
+ value: function parseVmapToBreaks(vmapXml) {
4927
+ var _this = this;
4928
+ if (typeof DOMParser === "undefined") {
4929
+ return [];
4930
+ }
4931
+ var doc = new DOMParser().parseFromString(vmapXml, "application/xml");
4932
+ if (doc.querySelector("parsererror")) {
4933
+ if (this.config.debugAdTiming) {
4934
+ console.warn("[StormcloudVideoPlayer] Invalid VMAP XML received");
4935
+ }
4936
+ return [];
4937
+ }
4938
+ var adBreakNodes = Array.from(doc.querySelectorAll("AdBreak, vmap\\:AdBreak"));
4939
+ var parsed = [];
4940
+ adBreakNodes.forEach(function(node, index) {
4941
+ var timeOffsetRaw = (node.getAttribute("timeOffset") || "").trim();
4942
+ var startTimeMs = _this.parseVmapTimeOffsetToMs(timeOffsetRaw);
4943
+ if (startTimeMs == null) {
4944
+ return;
4945
+ }
4946
+ var adTagNode = node.querySelector("AdTagURI, vmap\\:AdTagURI");
4947
+ var adTagUrl = ((adTagNode === null || adTagNode === void 0 ? void 0 : adTagNode.textContent) || "").trim();
4948
+ if (!adTagUrl) {
4949
+ return;
4950
+ }
4951
+ var breakId = node.getAttribute("breakId") || "vmap-break-".concat(index, "-").concat(timeOffsetRaw || "unknown");
4952
+ parsed.push({
4953
+ id: breakId,
4954
+ startTimeMs: startTimeMs,
4955
+ vastTagUrl: adTagUrl
4956
+ });
4957
+ });
4958
+ parsed.sort(function(a, b) {
4959
+ var aStart = a.startTimeMs < 0 ? Number.MAX_SAFE_INTEGER : a.startTimeMs;
4960
+ var bStart = b.startTimeMs < 0 ? Number.MAX_SAFE_INTEGER : b.startTimeMs;
4961
+ return aStart - bStart;
4962
+ });
4963
+ return parsed;
4607
4964
  }
4608
4965
  },
4609
4966
  {
4610
- key: "generateVastUrlsWithCorrelators",
4611
- value: function generateVastUrlsWithCorrelators(baseUrl, count) {
4612
- var urls = [];
4613
- var baseTimestamp = Date.now();
4614
- for(var i = 0; i < count; i++){
4615
- var timestamp = baseTimestamp + i;
4616
- var random = Math.floor(Math.random() * 1e12);
4617
- var uniqueCorrelator = "".concat(timestamp, "_").concat(random, "_").concat(i);
4618
- var urlWithCorrelator = void 0;
4619
- var correlatorRegex = /([?&])correlator=([^&]*)/;
4620
- if (correlatorRegex.test(baseUrl)) {
4621
- urlWithCorrelator = baseUrl.replace(correlatorRegex, "$1correlator=".concat(uniqueCorrelator));
4622
- } else if (baseUrl.includes("?")) {
4623
- urlWithCorrelator = "".concat(baseUrl, "&correlator=").concat(uniqueCorrelator);
4967
+ key: "parseVmapTimeOffsetToMs",
4968
+ value: function parseVmapTimeOffsetToMs(timeOffset) {
4969
+ if (!timeOffset) {
4970
+ return void 0;
4971
+ }
4972
+ var normalized = timeOffset.trim().toLowerCase();
4973
+ if (normalized === "start") {
4974
+ return 0;
4975
+ }
4976
+ if (normalized === "end") {
4977
+ return -1;
4978
+ }
4979
+ var hms = timeOffset.match(/^(\d{1,2}):(\d{2}):(\d{2})(?:\.(\d{1,3}))?$/);
4980
+ if (hms) {
4981
+ var _hms = _sliced_to_array(hms, 5), hh = _hms[1], mm = _hms[2], ss = _hms[3], tmp = _hms[4], ms = tmp === void 0 ? "0" : tmp;
4982
+ var hours = Number(hh);
4983
+ var minutes = Number(mm);
4984
+ var seconds = Number(ss);
4985
+ var millis = Number(ms.padEnd(3, "0").slice(0, 3));
4986
+ return (hours * 3600 + minutes * 60 + seconds) * 1e3 + millis;
4987
+ }
4988
+ var percent = timeOffset.match(/^(\d+(?:\.\d+)?)%$/);
4989
+ if (percent) {
4990
+ var ratio = Number(percent[1]) / 100;
4991
+ var durationSec = this.video.duration;
4992
+ if (Number.isFinite(durationSec) && durationSec > 0) {
4993
+ return Math.floor(durationSec * 1e3 * ratio);
4994
+ }
4995
+ return void 0;
4996
+ }
4997
+ return void 0;
4998
+ }
4999
+ },
5000
+ {
5001
+ key: "getAdBreakKey",
5002
+ value: function getAdBreakKey(adBreak) {
5003
+ if (adBreak.id) {
5004
+ return adBreak.id;
5005
+ }
5006
+ return "".concat(adBreak.startTimeMs, "-").concat(adBreak.vastTagUrl || "");
5007
+ }
5008
+ },
5009
+ {
5010
+ key: "resolveBreakStartMs",
5011
+ value: function resolveBreakStartMs(adBreak) {
5012
+ if (adBreak.startTimeMs >= 0) {
5013
+ return adBreak.startTimeMs;
5014
+ }
5015
+ if (adBreak.startTimeMs === -1) {
5016
+ var durationSec = this.video.duration;
5017
+ if (Number.isFinite(durationSec) && durationSec > 0) {
5018
+ return Math.floor(durationSec * 1e3);
5019
+ }
5020
+ }
5021
+ return void 0;
5022
+ }
5023
+ },
5024
+ {
5025
+ key: "getCurrentAdIndex",
5026
+ value: function getCurrentAdIndex() {
5027
+ return this.currentAdIndex;
5028
+ }
5029
+ },
5030
+ {
5031
+ key: "getTotalAdsInBreak",
5032
+ value: function getTotalAdsInBreak() {
5033
+ return this.totalAdsInBreak;
5034
+ }
5035
+ },
5036
+ {
5037
+ key: "generateVastUrlsWithCorrelators",
5038
+ value: function generateVastUrlsWithCorrelators(baseUrl, count) {
5039
+ var urls = [];
5040
+ var baseTimestamp = Date.now();
5041
+ for(var i = 0; i < count; i++){
5042
+ var timestamp = baseTimestamp + i;
5043
+ var random = Math.floor(Math.random() * 1e12);
5044
+ var uniqueCorrelator = "".concat(timestamp, "_").concat(random, "_").concat(i);
5045
+ var urlWithCorrelator = void 0;
5046
+ var correlatorRegex = /([?&])correlator=([^&]*)/;
5047
+ if (correlatorRegex.test(baseUrl)) {
5048
+ urlWithCorrelator = baseUrl.replace(correlatorRegex, "$1correlator=".concat(uniqueCorrelator));
5049
+ } else if (baseUrl.includes("?")) {
5050
+ urlWithCorrelator = "".concat(baseUrl, "&correlator=").concat(uniqueCorrelator);
4624
5051
  } else {
4625
5052
  urlWithCorrelator = "".concat(baseUrl, "?correlator=").concat(uniqueCorrelator);
4626
5053
  }
@@ -4684,10 +5111,10 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4684
5111
  var scheduled = this.findCurrentOrNextBreak(this.video.currentTime * 1e3);
4685
5112
  var tags = this.selectVastTagsForBreak(scheduled);
4686
5113
  var baseVastUrl;
4687
- if (this.apiVastTagUrl) {
4688
- baseVastUrl = this.apiVastTagUrl;
4689
- } else if (tags && tags.length > 0 && tags[0]) {
5114
+ if (tags && tags.length > 0 && tags[0]) {
4690
5115
  baseVastUrl = tags[0];
5116
+ } else if (this.apiVastTagUrl) {
5117
+ baseVastUrl = this.apiVastTagUrl;
4691
5118
  } else {
4692
5119
  if (this.config.debugAdTiming) {
4693
5120
  console.warn("[StormcloudVideoPlayer] No VAST URL available for prefetch");
@@ -4705,6 +5132,12 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4705
5132
  isFetching: false,
4706
5133
  fetchStartTime: Date.now()
4707
5134
  });
5135
+ this.adDetectSentForCurrentBreak = true;
5136
+ var detectPayload = {};
5137
+ if (marker.durationSeconds != null) detectPayload.durationSeconds = marker.durationSeconds;
5138
+ if (marker.ptsSeconds != null) detectPayload.ptsSeconds = marker.ptsSeconds;
5139
+ if (fragmentSn !== void 0) detectPayload.detectedAtFragmentSn = fragmentSn;
5140
+ sendAdDetectTracking(this.config.licenseKey, detectPayload).catch(function() {});
4708
5141
  if (this.config.debugAdTiming) {
4709
5142
  console.log("[PREFETCH] \uD83D\uDD04 Starting ad prefetch for upcoming ad break");
4710
5143
  console.log("[PREFETCH] \uD83D\uDCCB Pre-generated ".concat(generatedUrls.length, " VAST URLs"));
@@ -5131,11 +5564,14 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5131
5564
  switch(_state.label){
5132
5565
  case 0:
5133
5566
  scheduled = this.findCurrentOrNextBreak(this.video.currentTime * 1e3);
5567
+ if (scheduled) {
5568
+ this.consumedVmapBreakIds.add(this.getAdBreakKey(scheduled));
5569
+ }
5134
5570
  tags = this.selectVastTagsForBreak(scheduled);
5135
- if (this.apiVastTagUrl) {
5136
- baseVastUrl = this.apiVastTagUrl;
5137
- } else if (tags && tags.length > 0 && tags[0]) {
5571
+ if (tags && tags.length > 0 && tags[0]) {
5138
5572
  baseVastUrl = tags[0];
5573
+ } else if (this.apiVastTagUrl) {
5574
+ baseVastUrl = this.apiVastTagUrl;
5139
5575
  } else {
5140
5576
  this.clearPendingAdBreak();
5141
5577
  return [
@@ -5180,6 +5616,10 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5180
5616
  firstAdUrl = preloaded.vastUrl;
5181
5617
  preloadedController = preloaded.imaController;
5182
5618
  usePreloadedAd = true;
5619
+ sendAdLoadedTracking(this.config.licenseKey, {
5620
+ source: "preload",
5621
+ vastUrl: firstAdUrl
5622
+ }, this.config.adPlayerType).catch(function() {});
5183
5623
  if (this.config.debugAdTiming) {
5184
5624
  console.log("[CONTINUOUS-FETCH] \uD83D\uDE80 Using preloaded ad from pool (preloaded in advance, ready immediately!)");
5185
5625
  console.log("[CONTINUOUS-FETCH] Pool still has ".concat(this.preloadPool.length, " preloaded ads ready"));
@@ -5269,6 +5709,10 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5269
5709
  ];
5270
5710
  case 5:
5271
5711
  _state.sent();
5712
+ sendAdLoadedTracking(this.config.licenseKey, {
5713
+ source: "ssp",
5714
+ vastUrl: firstAdUrl
5715
+ }, this.config.adPlayerType).catch(function() {});
5272
5716
  if (this.config.debugAdTiming) {
5273
5717
  console.log("[CONTINUOUS-FETCH] \u2705 First ad request successful, starting playback");
5274
5718
  }
@@ -5665,6 +6109,10 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5665
6109
  if (this.config.debugAdTiming) {
5666
6110
  console.log("[CONTINUOUS-FETCH] \uD83C\uDFAF Using preloaded ad from pool (".concat(this.preloadPool.length, " remaining in pool)"));
5667
6111
  }
6112
+ sendAdLoadedTracking(this.config.licenseKey, {
6113
+ source: "preload",
6114
+ vastUrl: preloaded.vastUrl
6115
+ }, this.config.adPlayerType).catch(function() {});
5668
6116
  _state.label = 1;
5669
6117
  case 1:
5670
6118
  _state.trys.push([
@@ -6002,15 +6450,22 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6002
6450
  {
6003
6451
  key: "findCurrentOrNextBreak",
6004
6452
  value: function findCurrentOrNextBreak(nowMs) {
6005
- var schedule = [];
6453
+ var schedule = this.vmapBreaks;
6006
6454
  var candidate;
6007
6455
  var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
6008
6456
  try {
6009
6457
  for(var _iterator = schedule[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
6010
6458
  var b = _step.value;
6011
- var _this_config_driftToleranceMs;
6459
+ var _this_config_driftToleranceMs, _this_resolveBreakStartMs;
6460
+ if (this.consumedVmapBreakIds.has(this.getAdBreakKey(b))) {
6461
+ continue;
6462
+ }
6463
+ var breakStartMs = this.resolveBreakStartMs(b);
6464
+ if (breakStartMs == null) {
6465
+ continue;
6466
+ }
6012
6467
  var tol = (_this_config_driftToleranceMs = this.config.driftToleranceMs) !== null && _this_config_driftToleranceMs !== void 0 ? _this_config_driftToleranceMs : 1e3;
6013
- if (b.startTimeMs <= nowMs + tol && (candidate == null || b.startTimeMs > (candidate.startTimeMs || 0))) {
6468
+ if (breakStartMs <= nowMs + tol && (candidate == null || breakStartMs > ((_this_resolveBreakStartMs = this.resolveBreakStartMs(candidate)) !== null && _this_resolveBreakStartMs !== void 0 ? _this_resolveBreakStartMs : 0))) {
6014
6469
  candidate = b;
6015
6470
  }
6016
6471
  }
@@ -6034,11 +6489,16 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6034
6489
  {
6035
6490
  key: "onTimeUpdate",
6036
6491
  value: function onTimeUpdate(currentTimeSec) {
6037
- if (this.ima.isAdPlaying()) return;
6492
+ var _this = this;
6493
+ if (this.ima.isAdPlaying() || this.inAdBreak) return;
6038
6494
  var nowMs = currentTimeSec * 1e3;
6039
6495
  var breakToPlay = this.findBreakForTime(nowMs);
6040
6496
  if (breakToPlay) {
6041
- this.handleMidAdJoin(breakToPlay, nowMs);
6497
+ void this.handleMidAdJoin(breakToPlay, nowMs).catch(function(error) {
6498
+ if (_this.config.debugAdTiming) {
6499
+ console.warn("[StormcloudVideoPlayer] Mid-roll VMAP join failed gracefully:", error);
6500
+ }
6501
+ });
6042
6502
  }
6043
6503
  }
6044
6504
  },
@@ -6046,40 +6506,76 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6046
6506
  key: "handleMidAdJoin",
6047
6507
  value: function handleMidAdJoin(adBreak, nowMs) {
6048
6508
  return _async_to_generator(function() {
6049
- var _adBreak_durationMs, durationMs, endMs, remainingMs, tags, first, rest;
6509
+ var _adBreak_durationMs, _this_config_driftToleranceMs, key, breakStartMs, durationMs, endMs, tol, inWindow, remainingMs, tags, first, rest, error;
6050
6510
  return _ts_generator(this, function(_state) {
6051
6511
  switch(_state.label){
6052
6512
  case 0:
6513
+ key = this.getAdBreakKey(adBreak);
6514
+ if (this.consumedVmapBreakIds.has(key)) {
6515
+ return [
6516
+ 2
6517
+ ];
6518
+ }
6519
+ breakStartMs = this.resolveBreakStartMs(adBreak);
6520
+ if (breakStartMs == null) {
6521
+ return [
6522
+ 2
6523
+ ];
6524
+ }
6053
6525
  durationMs = (_adBreak_durationMs = adBreak.durationMs) !== null && _adBreak_durationMs !== void 0 ? _adBreak_durationMs : 0;
6054
- endMs = adBreak.startTimeMs + durationMs;
6055
- if (!(durationMs > 0 && nowMs > adBreak.startTimeMs && nowMs < endMs)) return [
6526
+ endMs = breakStartMs + durationMs;
6527
+ tol = (_this_config_driftToleranceMs = this.config.driftToleranceMs) !== null && _this_config_driftToleranceMs !== void 0 ? _this_config_driftToleranceMs : 1e3;
6528
+ inWindow = durationMs > 0 ? nowMs > breakStartMs && nowMs < endMs : nowMs + tol >= breakStartMs;
6529
+ if (!inWindow) return [
6056
6530
  3,
6057
- 2
6531
+ 4
6058
6532
  ];
6059
- remainingMs = endMs - nowMs;
6533
+ this.consumedVmapBreakIds.add(key);
6534
+ remainingMs = durationMs > 0 ? Math.max(0, endMs - nowMs) : 0;
6060
6535
  tags = this.selectVastTagsForBreak(adBreak) || (this.apiVastTagUrl ? [
6061
6536
  this.apiVastTagUrl
6062
6537
  ] : void 0);
6063
6538
  if (!(tags && tags.length > 0)) return [
6064
6539
  3,
6065
- 2
6540
+ 4
6066
6541
  ];
6067
6542
  first = tags[0];
6068
6543
  rest = tags.slice(1);
6069
6544
  this.adPodQueue = rest;
6070
6545
  this.ima.updateOriginalMutedState(this.video.muted, this.video.volume);
6546
+ _state.label = 1;
6547
+ case 1:
6548
+ _state.trys.push([
6549
+ 1,
6550
+ 3,
6551
+ ,
6552
+ 4
6553
+ ]);
6071
6554
  return [
6072
6555
  4,
6073
6556
  this.playSingleAd(first)
6074
6557
  ];
6075
- case 1:
6558
+ case 2:
6076
6559
  _state.sent();
6077
6560
  this.inAdBreak = true;
6078
6561
  this.expectedAdBreakDurationMs = remainingMs;
6079
6562
  this.currentAdBreakStartWallClockMs = Date.now();
6080
6563
  this.scheduleAdStopCountdown(remainingMs);
6081
- _state.label = 2;
6082
- case 2:
6564
+ return [
6565
+ 3,
6566
+ 4
6567
+ ];
6568
+ case 3:
6569
+ error = _state.sent();
6570
+ this.adPodQueue = [];
6571
+ if (this.config.debugAdTiming) {
6572
+ console.warn("[StormcloudVideoPlayer] Mid-roll VMAP ad request failed:", error);
6573
+ }
6574
+ return [
6575
+ 3,
6576
+ 4
6577
+ ];
6578
+ case 4:
6083
6579
  return [
6084
6580
  2
6085
6581
  ];
@@ -6369,6 +6865,10 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6369
6865
  ];
6370
6866
  case 3:
6371
6867
  _state.sent();
6868
+ sendAdLoadedTracking(this.config.licenseKey, {
6869
+ source: "ssp",
6870
+ vastUrl: vastTagUrl
6871
+ }, this.config.adPlayerType).catch(function() {});
6372
6872
  this.clearAdRequestWatchdog();
6373
6873
  if (this.activeAdRequestToken !== requestToken) {
6374
6874
  return [
@@ -6583,6 +7083,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6583
7083
  }
6584
7084
  this.adRequestQueue = [];
6585
7085
  this.inAdBreak = false;
7086
+ this.adDetectSentForCurrentBreak = false;
6586
7087
  this.expectedAdBreakDurationMs = void 0;
6587
7088
  this.currentAdBreakStartWallClockMs = void 0;
6588
7089
  this.clearAdStartTimer();
@@ -6780,13 +7281,22 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6780
7281
  {
6781
7282
  key: "findBreakForTime",
6782
7283
  value: function findBreakForTime(nowMs) {
6783
- var schedule = [];
7284
+ var _this_config_driftToleranceMs;
7285
+ var schedule = this.vmapBreaks;
7286
+ var tol = (_this_config_driftToleranceMs = this.config.driftToleranceMs) !== null && _this_config_driftToleranceMs !== void 0 ? _this_config_driftToleranceMs : 1e3;
6784
7287
  var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
6785
7288
  try {
6786
7289
  for(var _iterator = schedule[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
6787
7290
  var b = _step.value;
6788
- var end = (b.startTimeMs || 0) + (b.durationMs || 0);
6789
- if (nowMs >= (b.startTimeMs || 0) && (b.durationMs ? nowMs < end : true)) {
7291
+ if (this.consumedVmapBreakIds.has(this.getAdBreakKey(b))) {
7292
+ continue;
7293
+ }
7294
+ var breakStartMs = this.resolveBreakStartMs(b);
7295
+ if (breakStartMs == null) {
7296
+ continue;
7297
+ }
7298
+ var end = breakStartMs + (b.durationMs || 0);
7299
+ if (nowMs >= breakStartMs && (b.durationMs ? nowMs < end : nowMs <= breakStartMs + tol)) {
6790
7300
  return b;
6791
7301
  }
6792
7302
  }
@@ -7018,12 +7528,14 @@ var CRITICAL_PROPS = [
7018
7528
  "src",
7019
7529
  "allowNativeHls",
7020
7530
  "licenseKey",
7531
+ "vmapUrl",
7021
7532
  "lowLatencyMode",
7022
7533
  "driftToleranceMs",
7023
7534
  "vastMode"
7024
7535
  ];
7536
+ var CONTROLS_HIDE_DELAY = 3e3;
7025
7537
  var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
7026
- 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, adPlayerType = props.adPlayerType, minSegmentsBeforePlay = props.minSegmentsBeforePlay, restVideoAttrs = _object_without_properties(props, [
7538
+ 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, adPlayerType = props.adPlayerType, minSegmentsBeforePlay = props.minSegmentsBeforePlay, restVideoAttrs = _object_without_properties(props, [
7027
7539
  "src",
7028
7540
  "autoplay",
7029
7541
  "muted",
@@ -7050,12 +7562,15 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
7050
7562
  "licenseKey",
7051
7563
  "vastMode",
7052
7564
  "vastTagUrl",
7565
+ "vmapUrl",
7053
7566
  "adPlayerType",
7054
7567
  "minSegmentsBeforePlay"
7055
7568
  ]);
7056
7569
  var videoRef = (0, import_react.useRef)(null);
7057
7570
  var playerRef = (0, import_react.useRef)(null);
7058
7571
  var bufferingTimeoutRef = (0, import_react.useRef)(null);
7572
+ var controlsTimerRef = (0, import_react.useRef)(null);
7573
+ var wrapperRef = (0, import_react.useRef)(null);
7059
7574
  var _import_react_default_useState = _sliced_to_array(import_react.default.useState({
7060
7575
  showAds: false,
7061
7576
  currentIndex: 0,
@@ -7075,8 +7590,9 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
7075
7590
  var _import_react_default_useState12 = _sliced_to_array(import_react.default.useState(false), 2), isBuffering = _import_react_default_useState12[0], setIsBuffering = _import_react_default_useState12[1];
7076
7591
  var _import_react_default_useState13 = _sliced_to_array(import_react.default.useState(false), 2), showCenterPlay = _import_react_default_useState13[0], setShowCenterPlay = _import_react_default_useState13[1];
7077
7592
  var _import_react_default_useState14 = _sliced_to_array(import_react.default.useState(false), 2), showLicenseWarning = _import_react_default_useState14[0], setShowLicenseWarning = _import_react_default_useState14[1];
7078
- var _import_react_default_useState15 = _sliced_to_array(import_react.default.useState(typeof window !== "undefined" ? window.innerWidth : 1920), 2), viewportWidth = _import_react_default_useState15[0], setViewportWidth = _import_react_default_useState15[1];
7079
- var _import_react_default_useState16 = _sliced_to_array(import_react.default.useState(typeof window !== "undefined" ? window.innerHeight > window.innerWidth : false), 2), isPortrait = _import_react_default_useState16[0], setIsPortrait = _import_react_default_useState16[1];
7593
+ var _import_react_default_useState15 = _sliced_to_array(import_react.default.useState(true), 2), controlsVisible = _import_react_default_useState15[0], setControlsVisible = _import_react_default_useState15[1];
7594
+ var _import_react_default_useState16 = _sliced_to_array(import_react.default.useState(typeof window !== "undefined" ? window.innerWidth : 1920), 2), viewportWidth = _import_react_default_useState16[0], setViewportWidth = _import_react_default_useState16[1];
7595
+ var _import_react_default_useState17 = _sliced_to_array(import_react.default.useState(typeof window !== "undefined" ? window.innerHeight > window.innerWidth : false), 2), isPortrait = _import_react_default_useState17[0], setIsPortrait = _import_react_default_useState17[1];
7080
7596
  var getResponsiveScale = function getResponsiveScale() {
7081
7597
  if (viewportWidth < 480) return 0.7;
7082
7598
  if (viewportWidth < 768) return 0.8;
@@ -7084,6 +7600,33 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
7084
7600
  return 1;
7085
7601
  };
7086
7602
  var responsiveScale = getResponsiveScale();
7603
+ var resetControlsTimer = (0, import_react.useCallback)(function() {
7604
+ if (controlsTimerRef.current) {
7605
+ clearTimeout(controlsTimerRef.current);
7606
+ }
7607
+ setControlsVisible(true);
7608
+ controlsTimerRef.current = window.setTimeout(function() {
7609
+ if (!showVolumeSlider && !showSpeedMenu) {
7610
+ setControlsVisible(false);
7611
+ }
7612
+ }, CONTROLS_HIDE_DELAY);
7613
+ }, [
7614
+ showVolumeSlider,
7615
+ showSpeedMenu
7616
+ ]);
7617
+ var handleWrapperMouseMove = (0, import_react.useCallback)(function() {
7618
+ resetControlsTimer();
7619
+ }, [
7620
+ resetControlsTimer
7621
+ ]);
7622
+ var handleWrapperMouseLeave = (0, import_react.useCallback)(function() {
7623
+ if (!showVolumeSlider && !showSpeedMenu) {
7624
+ setControlsVisible(false);
7625
+ }
7626
+ }, [
7627
+ showVolumeSlider,
7628
+ showSpeedMenu
7629
+ ]);
7087
7630
  var formatTime = function formatTime(seconds) {
7088
7631
  if (!isFinite(seconds)) return "0:00:00";
7089
7632
  var hours = Math.floor(seconds / 3600);
@@ -7109,6 +7652,7 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
7109
7652
  setShowCenterPlay(true);
7110
7653
  }
7111
7654
  }
7655
+ resetControlsTimer();
7112
7656
  };
7113
7657
  var handleCenterPlayClick = function handleCenterPlayClick() {
7114
7658
  if (videoRef.current && videoRef.current.paused) {
@@ -7134,6 +7678,7 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
7134
7678
  videoRef.current.currentTime = newTime;
7135
7679
  }
7136
7680
  }
7681
+ resetControlsTimer();
7137
7682
  };
7138
7683
  var handleVolumeChange = function handleVolumeChange(newVolume) {
7139
7684
  if (playerRef.current && isFinite(newVolume)) {
@@ -7157,6 +7702,7 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
7157
7702
  src,
7158
7703
  allowNativeHls,
7159
7704
  licenseKey,
7705
+ vmapUrl,
7160
7706
  lowLatencyMode,
7161
7707
  driftToleranceMs,
7162
7708
  vastMode
@@ -7199,6 +7745,7 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
7199
7745
  if (licenseKey !== void 0) cfg.licenseKey = licenseKey;
7200
7746
  if (vastMode !== void 0) cfg.vastMode = vastMode;
7201
7747
  if (vastTagUrl !== void 0) cfg.vastTagUrl = vastTagUrl;
7748
+ if (vmapUrl !== void 0) cfg.vmapUrl = vmapUrl;
7202
7749
  if (adPlayerType !== void 0) cfg.adPlayerType = adPlayerType;
7203
7750
  if (minSegmentsBeforePlay !== void 0) cfg.minSegmentsBeforePlay = minSegmentsBeforePlay;
7204
7751
  var player = new StormcloudVideoPlayer(cfg);
@@ -7289,7 +7836,6 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
7289
7836
  (0, import_react.useEffect)(function() {
7290
7837
  if (!playerRef.current || !videoRef.current) return;
7291
7838
  var updateStates = function updateStates() {
7292
- var _videoRef_current;
7293
7839
  if (playerRef.current && videoRef.current) {
7294
7840
  setIsMuted(playerRef.current.isMuted());
7295
7841
  setIsPlaying(!videoRef.current.paused);
@@ -7302,12 +7848,11 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
7302
7848
  var rateValue = videoRef.current.playbackRate;
7303
7849
  setPlaybackRate(isFinite(rateValue) && rateValue > 0 ? rateValue : 1);
7304
7850
  }
7305
- setIsFullscreen(document.fullscreenElement === ((_videoRef_current = videoRef.current) === null || _videoRef_current === void 0 ? void 0 : _videoRef_current.parentElement));
7851
+ setIsFullscreen(document.fullscreenElement === wrapperRef.current);
7306
7852
  };
7307
7853
  var interval = setInterval(updateStates, 200);
7308
7854
  var handleFullscreenChange = function handleFullscreenChange() {
7309
- var _videoRef_current;
7310
- setIsFullscreen(document.fullscreenElement === ((_videoRef_current = videoRef.current) === null || _videoRef_current === void 0 ? void 0 : _videoRef_current.parentElement));
7855
+ setIsFullscreen(document.fullscreenElement === wrapperRef.current);
7311
7856
  };
7312
7857
  document.addEventListener("fullscreenchange", handleFullscreenChange);
7313
7858
  return function() {
@@ -7435,13 +7980,25 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
7435
7980
  }, [
7436
7981
  debugAdTiming
7437
7982
  ]);
7983
+ (0, import_react.useEffect)(function() {
7984
+ return function() {
7985
+ if (controlsTimerRef.current) {
7986
+ clearTimeout(controlsTimerRef.current);
7987
+ }
7988
+ };
7989
+ }, []);
7990
+ var progressPercent = duration > 0 ? currentTime / duration * 100 : 0;
7991
+ var VolumeIcon = isMuted || volume === 0 ? import_fa.FaVolumeMute : volume < 0.5 ? import_fa.FaVolumeDown : import_fa.FaVolumeUp;
7438
7992
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, {
7439
7993
  children: [
7440
7994
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", {
7441
- children: "\n @keyframes spin {\n from {\n transform: rotate(0deg);\n }\n to {\n transform: rotate(360deg);\n }\n }\n \n .stormcloud-loading-hidden .stormcloud-loading-indicator {\n display: none !important;\n }\n \n .stormcloud-video-wrapper: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 \n .stormcloud-video-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 \n *:fullscreen {\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 }\n "
7995
+ 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 "
7442
7996
  }),
7443
7997
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
7444
- className: "stormcloud-video-wrapper ".concat(wrapperClassName || ""),
7998
+ ref: wrapperRef,
7999
+ className: "sc-wrapper ".concat(wrapperClassName || ""),
8000
+ onMouseMove: handleWrapperMouseMove,
8001
+ onMouseLeave: handleWrapperMouseLeave,
7445
8002
  style: _object_spread({
7446
8003
  display: "flex",
7447
8004
  alignItems: "center",
@@ -7456,7 +8013,7 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
7456
8013
  maxWidth: isFullscreen ? "100vw" : "100%",
7457
8014
  maxHeight: isFullscreen ? "100vh" : "none",
7458
8015
  zIndex: isFullscreen ? 999999 : void 0,
7459
- backgroundColor: isFullscreen ? "#000" : void 0,
8016
+ backgroundColor: "#000",
7460
8017
  borderRadius: isFullscreen ? 0 : void 0,
7461
8018
  boxShadow: isFullscreen ? "none" : void 0
7462
8019
  }, wrapperStyle),
@@ -7482,16 +8039,16 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
7482
8039
  children: children
7483
8040
  })),
7484
8041
  (isLoading || isBuffering) && !hideLoadingIndicator && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_fa.FaSpinner, {
7485
- className: "stormcloud-loading-indicator",
7486
- size: 42,
7487
- color: "white",
8042
+ className: "sc-loading-indicator",
8043
+ size: 40,
8044
+ color: "rgba(255, 255, 255, 0.85)",
7488
8045
  style: {
7489
8046
  position: "absolute",
7490
- top: "calc(50% - 21px)",
7491
- left: "calc(50% - 21px)",
8047
+ top: "calc(50% - 20px)",
8048
+ left: "calc(50% - 20px)",
7492
8049
  zIndex: 20,
7493
- animation: "spin 1s linear infinite",
7494
- filter: "drop-shadow(0 3px 6px rgba(0, 0, 0, 0.8))"
8050
+ animation: "sc-spin 0.9s linear infinite",
8051
+ filter: "drop-shadow(0 2px 8px rgba(0, 0, 0, 0.6))"
7495
8052
  }
7496
8053
  }),
7497
8054
  showLicenseWarning && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
@@ -7501,13 +8058,13 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
7501
8058
  left: "50%",
7502
8059
  transform: "translate(-50%, -50%)",
7503
8060
  zIndex: 25,
7504
- background: "linear-gradient(135deg, rgba(220, 38, 38, 0.95) 0%, rgba(185, 28, 28, 0.9) 100%)",
8061
+ background: "rgba(220, 38, 38, 0.92)",
8062
+ backdropFilter: "blur(24px)",
7505
8063
  color: "white",
7506
- padding: "24px 32px",
7507
- borderRadius: "16px",
7508
- backdropFilter: "blur(20px)",
7509
- border: "2px solid rgba(255, 255, 255, 0.2)",
7510
- boxShadow: "0 20px 60px rgba(0, 0, 0, 0.6), inset 0 2px 0 rgba(255, 255, 255, 0.2)",
8064
+ padding: "28px 36px",
8065
+ borderRadius: "14px",
8066
+ border: "1px solid rgba(255, 255, 255, 0.15)",
8067
+ boxShadow: "0 24px 64px rgba(0, 0, 0, 0.5)",
7511
8068
  textAlign: "center",
7512
8069
  maxWidth: "400px",
7513
8070
  margin: "0 16px"
@@ -7515,20 +8072,18 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
7515
8072
  children: [
7516
8073
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
7517
8074
  style: {
7518
- fontSize: "20px",
7519
- fontWeight: "bold",
7520
- marginBottom: "12px",
7521
- color: "#ffffff",
7522
- textShadow: "0 2px 4px rgba(0, 0, 0, 0.5)"
8075
+ fontSize: "18px",
8076
+ fontWeight: "700",
8077
+ marginBottom: "10px",
8078
+ letterSpacing: "-0.02em"
7523
8079
  },
7524
8080
  children: "License Key Required"
7525
8081
  }),
7526
8082
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
7527
8083
  style: {
7528
- fontSize: "14px",
7529
- lineHeight: "1.5",
7530
- color: "rgba(255, 255, 255, 0.9)",
7531
- textShadow: "0 1px 2px rgba(0, 0, 0, 0.3)"
8084
+ fontSize: "13px",
8085
+ lineHeight: "1.6",
8086
+ color: "rgba(255, 255, 255, 0.85)"
7532
8087
  },
7533
8088
  children: [
7534
8089
  "Please provide a valid license key to use the Stormcloud Video Player.",
@@ -7547,573 +8102,419 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
7547
8102
  transform: "translate(-50%, -50%)",
7548
8103
  zIndex: 15,
7549
8104
  cursor: "pointer",
7550
- background: "linear-gradient(135deg, rgba(0, 0, 0, 0.9) 0%, rgba(20, 20, 20, 0.8) 100%)",
8105
+ background: "rgba(0, 0, 0, 0.55)",
8106
+ backdropFilter: "blur(8px)",
7551
8107
  borderRadius: "50%",
7552
- width: "100px",
7553
- height: "100px",
8108
+ width: "".concat(92 * responsiveScale, "px"),
8109
+ height: "".concat(92 * responsiveScale, "px"),
7554
8110
  display: "flex",
7555
8111
  alignItems: "center",
7556
8112
  justifyContent: "center",
7557
- backdropFilter: "blur(20px)",
7558
- border: "3px solid rgba(255, 255, 255, 0.8)",
7559
- boxShadow: "0 12px 40px rgba(0, 0, 0, 0.8), inset 0 2px 0 rgba(255, 255, 255, 0.3)",
7560
- transition: "all 0.3s cubic-bezier(0.4, 0, 0.2, 1)"
8113
+ transition: "background 0.2s ease, transform 0.2s ease",
8114
+ animation: "sc-fade-in 0.2s ease"
7561
8115
  },
7562
8116
  onMouseEnter: function onMouseEnter(e) {
7563
- var target = e.currentTarget;
7564
- target.style.transform = "translate(-50%, -50%)";
7565
- target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.95) 0%, rgba(40, 40, 40, 0.9) 100%)";
7566
- target.style.boxShadow = "0 16px 48px rgba(0, 0, 0, 0.9), inset 0 2px 0 rgba(255, 255, 255, 0.4)";
7567
- target.style.borderColor = "rgba(255, 255, 255, 0.9)";
8117
+ e.currentTarget.style.background = "rgba(0, 0, 0, 0.72)";
8118
+ e.currentTarget.style.transform = "translate(-50%, -50%) scale(1.06)";
7568
8119
  },
7569
8120
  onMouseLeave: function onMouseLeave(e) {
7570
- var target = e.currentTarget;
7571
- target.style.transform = "translate(-50%, -50%)";
7572
- target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.9) 0%, rgba(20, 20, 20, 0.8) 100%)";
7573
- target.style.boxShadow = "0 12px 40px rgba(0, 0, 0, 0.8), inset 0 2px 0 rgba(255, 255, 255, 0.3)";
7574
- target.style.borderColor = "rgba(255, 255, 255, 0.8)";
8121
+ e.currentTarget.style.background = "rgba(0, 0, 0, 0.55)";
8122
+ e.currentTarget.style.transform = "translate(-50%, -50%) scale(1)";
7575
8123
  },
7576
8124
  title: "Play",
7577
8125
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_fa.FaPlay, {
7578
- size: 36,
8126
+ size: Math.max(24, 32 * responsiveScale),
7579
8127
  color: "white",
7580
8128
  style: {
7581
- marginLeft: "6px",
7582
- filter: "drop-shadow(0 2px 4px rgba(0, 0, 0, 0.8))"
8129
+ marginLeft: "4px"
7583
8130
  }
7584
8131
  })
7585
8132
  }),
7586
- shouldShowEnhancedControls && !showLicenseWarning ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, {
7587
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
7588
- style: {
7589
- position: "absolute",
7590
- bottom: 0,
7591
- left: 0,
7592
- right: 0,
7593
- background: "linear-gradient(180deg, transparent 0%, rgba(0, 0, 0, 0.8) 100%)",
7594
- padding: "20px 16px 16px",
7595
- zIndex: 10
7596
- },
7597
- children: [
7598
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
7599
- style: {
7600
- width: "100%",
7601
- height: "8px",
7602
- background: "linear-gradient(90deg, rgba(255, 255, 255, 0.2) 0%, rgba(255, 255, 255, 0.1) 100%)",
7603
- borderRadius: "8px",
7604
- marginBottom: "16px",
7605
- cursor: "pointer",
7606
- position: "relative",
7607
- backdropFilter: "blur(5px)",
7608
- border: "1px solid rgba(255, 255, 255, 0.1)",
7609
- boxShadow: "inset 0 2px 4px rgba(0, 0, 0, 0.2)"
7610
- },
7611
- onClick: handleTimelineSeek,
7612
- children: [
7613
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
7614
- style: {
7615
- height: "100%",
7616
- background: "linear-gradient(90deg, rgba(139, 92, 246, 0.9) 0%, rgba(59, 130, 246, 0.8) 50%, rgba(34, 197, 94, 0.9) 100%)",
7617
- borderRadius: "8px",
7618
- width: "".concat(duration > 0 ? currentTime / duration * 100 : 0, "%"),
7619
- transition: "width 0.2s cubic-bezier(0.4, 0, 0.2, 1)",
7620
- boxShadow: "0 2px 8px rgba(139, 92, 246, 0.4)"
7621
- }
7622
- }),
7623
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
7624
- style: {
7625
- position: "absolute",
7626
- top: "-6px",
7627
- right: "".concat(duration > 0 ? 100 - currentTime / duration * 100 : 100, "%"),
7628
- width: "20px",
7629
- height: "20px",
7630
- background: "linear-gradient(135deg, rgba(255, 255, 255, 0.95) 0%, rgba(240, 240, 240, 0.9) 100%)",
7631
- borderRadius: "50%",
7632
- border: "3px solid rgba(139, 92, 246, 0.8)",
7633
- boxShadow: "0 4px 16px rgba(139, 92, 246, 0.4), inset 0 1px 0 rgba(255, 255, 255, 0.8)",
7634
- transform: "translateX(50%)",
7635
- transition: "all 0.2s cubic-bezier(0.4, 0, 0.2, 1)"
7636
- }
7637
- })
7638
- ]
7639
- }),
7640
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
7641
- style: {
7642
- display: "flex",
7643
- alignItems: "center",
7644
- justifyContent: "space-between",
7645
- color: "white",
7646
- flexWrap: viewportWidth < 768 ? "wrap" : "nowrap",
7647
- gap: "".concat(8 * responsiveScale, "px")
7648
- },
7649
- children: [
7650
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
7651
- style: {
7652
- display: "flex",
7653
- alignItems: "center",
7654
- gap: "".concat(12 * responsiveScale, "px"),
7655
- flexWrap: viewportWidth < 480 ? "wrap" : "nowrap"
7656
- },
7657
- children: [
7658
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", {
7659
- onClick: handlePlayPause,
8133
+ shouldShowEnhancedControls && !showLicenseWarning ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
8134
+ className: "sc-controls-bar",
8135
+ style: {
8136
+ position: "absolute",
8137
+ bottom: 0,
8138
+ left: 0,
8139
+ right: 0,
8140
+ background: "linear-gradient(0deg, rgba(0, 0, 0, 0.8) 0%, rgba(0, 0, 0, 0.35) 60%, transparent 100%)",
8141
+ padding: "".concat(20 * responsiveScale, "px ").concat(12 * responsiveScale, "px ").concat(8 * responsiveScale, "px"),
8142
+ zIndex: 10,
8143
+ opacity: controlsVisible || adStatus.showAds ? 1 : 0,
8144
+ transform: controlsVisible || adStatus.showAds ? "translateY(0)" : "translateY(6px)",
8145
+ pointerEvents: controlsVisible || adStatus.showAds ? "auto" : "none"
8146
+ },
8147
+ children: [
8148
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
8149
+ className: "sc-progress-track",
8150
+ style: {
8151
+ width: "100%",
8152
+ height: "3px",
8153
+ background: "rgba(255, 255, 255, 0.2)",
8154
+ borderRadius: "1.5px",
8155
+ marginBottom: "".concat(8 * responsiveScale, "px"),
8156
+ cursor: "pointer",
8157
+ position: "relative",
8158
+ transition: "height 0.1s ease"
8159
+ },
8160
+ onClick: handleTimelineSeek,
8161
+ onMouseEnter: function onMouseEnter(e) {
8162
+ e.currentTarget.style.height = "5px";
8163
+ },
8164
+ onMouseLeave: function onMouseLeave(e) {
8165
+ e.currentTarget.style.height = "3px";
8166
+ },
8167
+ children: [
8168
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
8169
+ style: {
8170
+ position: "absolute",
8171
+ top: 0,
8172
+ left: 0,
8173
+ bottom: 0,
8174
+ background: adStatus.showAds ? "#f5c518" : "#ff0000",
8175
+ borderRadius: "1.5px",
8176
+ width: "".concat(progressPercent, "%"),
8177
+ transition: "width 0.15s linear"
8178
+ }
8179
+ }),
8180
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
8181
+ className: "sc-progress-thumb",
8182
+ style: {
8183
+ position: "absolute",
8184
+ top: "50%",
8185
+ left: "".concat(progressPercent, "%"),
8186
+ transform: "translate(-50%, -50%) scale(0)",
8187
+ width: "13px",
8188
+ height: "13px",
8189
+ background: adStatus.showAds ? "#f5c518" : "#ff0000",
8190
+ borderRadius: "50%",
8191
+ boxShadow: "0 0 4px rgba(0, 0, 0, 0.3)",
8192
+ transition: "transform 0.1s ease, left 0.15s linear"
8193
+ }
8194
+ })
8195
+ ]
8196
+ }),
8197
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
8198
+ style: {
8199
+ display: "flex",
8200
+ alignItems: "center",
8201
+ justifyContent: "space-between",
8202
+ color: "white",
8203
+ gap: "".concat(8 * responsiveScale, "px")
8204
+ },
8205
+ children: [
8206
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
8207
+ style: {
8208
+ display: "flex",
8209
+ alignItems: "center",
8210
+ gap: "".concat(8 * responsiveScale, "px")
8211
+ },
8212
+ children: [
8213
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", {
8214
+ className: "sc-ctrl-btn",
8215
+ onClick: handlePlayPause,
8216
+ style: {
8217
+ padding: "".concat(8 * responsiveScale, "px"),
8218
+ borderRadius: "50%",
8219
+ minWidth: "".concat(36 * responsiveScale, "px"),
8220
+ minHeight: "".concat(36 * responsiveScale, "px")
8221
+ },
8222
+ title: isPlaying ? "Pause" : "Play",
8223
+ children: isPlaying ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_fa.FaPause, {
8224
+ size: Math.max(14, 18 * responsiveScale)
8225
+ }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_fa.FaPlay, {
8226
+ size: Math.max(14, 18 * responsiveScale),
7660
8227
  style: {
7661
- background: "linear-gradient(135deg, rgba(0, 0, 0, 0.75) 0%, rgba(0, 0, 0, 0.65) 100%)",
7662
- backdropFilter: "blur(12px)",
7663
- border: "".concat(2 * responsiveScale, "px solid rgba(255, 255, 255, 0.3)"),
7664
- color: "#ffffff",
7665
- cursor: "pointer",
7666
- padding: "".concat(10 * responsiveScale, "px"),
7667
- borderRadius: "".concat(16 * responsiveScale, "px"),
7668
- display: "flex",
7669
- alignItems: "center",
7670
- justifyContent: "center",
7671
- transition: "all 0.3s cubic-bezier(0.4, 0, 0.2, 1)",
7672
- boxShadow: "0 8px 32px rgba(0, 0, 0, 0.4), 0 4px 16px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.3)",
7673
- minWidth: "".concat(48 * responsiveScale, "px"),
7674
- minHeight: "".concat(48 * responsiveScale, "px")
7675
- },
7676
- onMouseEnter: function onMouseEnter(e) {
7677
- var target = e.target;
7678
- target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.85) 0%, rgba(0, 0, 0, 0.75) 100%)";
7679
- target.style.boxShadow = "0 12px 48px rgba(0, 0, 0, 0.6), 0 6px 24px rgba(0, 0, 0, 0.4), inset 0 2px 0 rgba(255, 255, 255, 0.4)";
7680
- },
7681
- onMouseLeave: function onMouseLeave(e) {
7682
- var target = e.target;
7683
- target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.75) 0%, rgba(0, 0, 0, 0.65) 100%)";
7684
- target.style.boxShadow = "0 8px 32px rgba(0, 0, 0, 0.4), 0 4px 16px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.3)";
7685
- },
7686
- title: isPlaying ? "Pause" : "Play",
7687
- children: isPlaying ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_fa.FaPause, {
7688
- size: Math.max(16, 20 * responsiveScale),
8228
+ marginLeft: "2px"
8229
+ }
8230
+ })
8231
+ }),
8232
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
8233
+ style: {
8234
+ display: "flex",
8235
+ alignItems: "center"
8236
+ },
8237
+ onMouseEnter: function onMouseEnter() {
8238
+ return setShowVolumeSlider(true);
8239
+ },
8240
+ onMouseLeave: function onMouseLeave() {
8241
+ return setShowVolumeSlider(false);
8242
+ },
8243
+ children: [
8244
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", {
8245
+ className: "sc-ctrl-btn",
8246
+ onClick: function onClick() {
8247
+ if (playerRef.current) playerRef.current.toggleMute();
8248
+ onVolumeToggle === null || onVolumeToggle === void 0 ? void 0 : onVolumeToggle();
8249
+ resetControlsTimer();
8250
+ },
7689
8251
  style: {
7690
- filter: "drop-shadow(0 0 0 transparent)"
7691
- }
7692
- }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_fa.FaPlay, {
7693
- size: Math.max(16, 20 * responsiveScale),
8252
+ padding: "".concat(8 * responsiveScale, "px"),
8253
+ borderRadius: "50%",
8254
+ minWidth: "".concat(36 * responsiveScale, "px"),
8255
+ minHeight: "".concat(36 * responsiveScale, "px")
8256
+ },
8257
+ title: isMuted ? "Unmute" : "Mute",
8258
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(VolumeIcon, {
8259
+ size: Math.max(14, 18 * responsiveScale)
8260
+ })
8261
+ }),
8262
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
7694
8263
  style: {
7695
- filter: "drop-shadow(0 0 0 transparent)"
7696
- }
7697
- })
7698
- }),
7699
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
7700
- style: {
7701
- position: "relative",
7702
- display: "flex",
7703
- alignItems: "center",
7704
- padding: "8px",
7705
- margin: "-8px"
7706
- },
7707
- onMouseEnter: function onMouseEnter() {
7708
- return setShowVolumeSlider(true);
7709
- },
7710
- onMouseLeave: function onMouseLeave() {
7711
- return setShowVolumeSlider(false);
7712
- },
7713
- children: [
7714
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", {
7715
- onClick: function onClick() {
7716
- if (playerRef.current) {
7717
- playerRef.current.toggleMute();
7718
- }
7719
- if (onVolumeToggle) {
7720
- onVolumeToggle();
7721
- }
7722
- },
8264
+ width: showVolumeSlider ? "".concat(62 * responsiveScale, "px") : "0px",
8265
+ overflow: "hidden",
8266
+ transition: "width 0.2s cubic-bezier(0.4, 0, 0.2, 1)",
8267
+ display: "flex",
8268
+ alignItems: "center",
8269
+ paddingLeft: showVolumeSlider ? "2px" : "0",
8270
+ paddingRight: showVolumeSlider ? "4px" : "0"
8271
+ },
8272
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
7723
8273
  style: {
7724
- background: "linear-gradient(135deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.6) 100%)",
7725
- backdropFilter: "blur(10px)",
7726
- border: "".concat(2 * responsiveScale, "px solid rgba(255, 255, 255, 0.3)"),
7727
- color: "#ffffff",
8274
+ position: "relative",
8275
+ width: "".concat(56 * responsiveScale, "px"),
8276
+ height: "3px",
7728
8277
  cursor: "pointer",
7729
- padding: "".concat(8 * responsiveScale, "px"),
7730
- borderRadius: "".concat(16 * responsiveScale, "px"),
7731
- display: "flex",
7732
- alignItems: "center",
7733
- justifyContent: "center",
7734
- transition: "all 0.3s cubic-bezier(0.4, 0, 0.2, 1)",
7735
- boxShadow: "0 6px 28px rgba(0, 0, 0, 0.4), 0 3px 12px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.25)",
7736
- minWidth: "".concat(44 * responsiveScale, "px"),
7737
- minHeight: "".concat(44 * responsiveScale, "px")
8278
+ borderRadius: "1.5px"
7738
8279
  },
7739
- onMouseEnter: function onMouseEnter(e) {
7740
- var target = e.target;
7741
- target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.8) 0%, rgba(0, 0, 0, 0.7) 100%)";
7742
- target.style.boxShadow = "0 10px 36px rgba(0, 0, 0, 0.6), 0 5px 16px rgba(0, 0, 0, 0.4), inset 0 2px 0 rgba(255, 255, 255, 0.35)";
8280
+ onMouseDown: function onMouseDown(e) {
8281
+ e.preventDefault();
8282
+ var el = e.currentTarget;
8283
+ var move = function move(ev) {
8284
+ var r2 = el.getBoundingClientRect();
8285
+ handleVolumeChange(Math.max(0, Math.min(1, (ev.clientX - r2.left) / r2.width)));
8286
+ };
8287
+ var up = function up1() {
8288
+ document.removeEventListener("mousemove", move);
8289
+ document.removeEventListener("mouseup", up);
8290
+ };
8291
+ document.addEventListener("mousemove", move);
8292
+ document.addEventListener("mouseup", up);
8293
+ var r = el.getBoundingClientRect();
8294
+ handleVolumeChange(Math.max(0, Math.min(1, (e.clientX - r.left) / r.width)));
7743
8295
  },
7744
- onMouseLeave: function onMouseLeave(e) {
7745
- var target = e.target;
7746
- target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.6) 100%)";
7747
- target.style.boxShadow = "0 6px 28px rgba(0, 0, 0, 0.4), 0 3px 12px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.25)";
8296
+ onClick: function onClick(e) {
8297
+ e.stopPropagation();
8298
+ var r = e.currentTarget.getBoundingClientRect();
8299
+ handleVolumeChange(Math.max(0, Math.min(1, (e.clientX - r.left) / r.width)));
7748
8300
  },
7749
- title: isMuted ? "Unmute" : "Mute",
7750
- children: isMuted || volume === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_fa.FaVolumeMute, {
7751
- size: Math.max(14, 16 * responsiveScale),
7752
- style: {
7753
- filter: "drop-shadow(0 0 0 transparent)"
7754
- }
7755
- }) : volume < 0.5 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_fa.FaVolumeDown, {
7756
- size: Math.max(14, 16 * responsiveScale),
7757
- style: {
7758
- filter: "drop-shadow(0 0 0 transparent)"
7759
- }
7760
- }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_fa.FaVolumeUp, {
7761
- size: Math.max(14, 16 * responsiveScale),
7762
- style: {
7763
- filter: "drop-shadow(0 0 0 transparent)"
7764
- }
7765
- })
7766
- }),
7767
- showVolumeSlider && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, {
7768
8301
  children: [
7769
8302
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
7770
8303
  style: {
7771
8304
  position: "absolute",
7772
- bottom: "100%",
7773
- left: "50%",
7774
- transform: "translateX(-50%)",
7775
- width: "60px",
7776
- height: "20px",
7777
- marginBottom: "-16px",
7778
- zIndex: 9
7779
- },
7780
- onMouseEnter: function onMouseEnter() {
7781
- return setShowVolumeSlider(true);
7782
- },
7783
- onMouseLeave: function onMouseLeave() {
7784
- return setShowVolumeSlider(false);
8305
+ inset: 0,
8306
+ background: "rgba(255, 255, 255, 0.2)",
8307
+ borderRadius: "1.5px"
7785
8308
  }
7786
8309
  }),
7787
8310
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
7788
8311
  style: {
7789
8312
  position: "absolute",
7790
- bottom: "100%",
7791
- left: "50%",
7792
- transform: "translateX(-50%)",
7793
- marginBottom: "4px",
7794
- background: "linear-gradient(135deg, rgba(0, 0, 0, 0.88) 0%, rgba(20, 20, 20, 0.92) 100%)",
7795
- backdropFilter: "blur(15px)",
7796
- padding: "10px 14px",
7797
- borderRadius: "14px",
7798
- border: "1px solid rgba(255, 255, 255, 0.15)",
7799
- display: "flex",
7800
- flexDirection: "column",
7801
- alignItems: "center",
7802
- justifyContent: "center",
7803
- height: "128px",
7804
- boxShadow: "0 12px 40px rgba(0, 0, 0, 0.5), 0 4px 12px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.15)",
7805
- zIndex: 10,
7806
- transition: "transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out, border-color 0.2s ease-in-out"
7807
- },
7808
- onMouseEnter: function onMouseEnter(e) {
7809
- setShowVolumeSlider(true);
7810
- e.currentTarget.style.boxShadow = "0 16px 48px rgba(0, 0, 0, 0.6), 0 6px 16px rgba(0, 0, 0, 0.4), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 0 24px rgba(59, 130, 246, 0.3)";
7811
- e.currentTarget.style.borderColor = "rgba(59, 130, 246, 0.4)";
7812
- },
7813
- onMouseLeave: function onMouseLeave(e) {
7814
- setShowVolumeSlider(false);
7815
- e.currentTarget.style.boxShadow = "0 12px 40px rgba(0, 0, 0, 0.5), 0 4px 12px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.15)";
7816
- e.currentTarget.style.borderColor = "rgba(255, 255, 255, 0.15)";
7817
- },
7818
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
7819
- style: {
7820
- position: "relative",
7821
- width: "8px",
7822
- height: "104px",
7823
- cursor: "pointer",
7824
- transition: "transform 0.2s ease-in-out"
7825
- },
7826
- onMouseEnter: function onMouseEnter(e) {},
7827
- onMouseLeave: function onMouseLeave(e) {},
7828
- onMouseDown: function onMouseDown(e) {
7829
- e.preventDefault();
7830
- var sliderElement = e.currentTarget;
7831
- var handleMouseMove = function handleMouseMove(moveEvent) {
7832
- if (!sliderElement) return;
7833
- var rect2 = sliderElement.getBoundingClientRect();
7834
- var y2 = moveEvent.clientY - rect2.top;
7835
- var percentage2 = 1 - Math.max(0, Math.min(1, y2 / rect2.height));
7836
- handleVolumeChange(percentage2);
7837
- };
7838
- var handleMouseUp = function handleMouseUp1() {
7839
- document.removeEventListener("mousemove", handleMouseMove);
7840
- document.removeEventListener("mouseup", handleMouseUp);
7841
- };
7842
- document.addEventListener("mousemove", handleMouseMove);
7843
- document.addEventListener("mouseup", handleMouseUp);
7844
- var rect = sliderElement.getBoundingClientRect();
7845
- var y = e.clientY - rect.top;
7846
- var percentage = 1 - Math.max(0, Math.min(1, y / rect.height));
7847
- handleVolumeChange(percentage);
7848
- },
7849
- onClick: function onClick(e) {
7850
- e.stopPropagation();
7851
- var rect = e.currentTarget.getBoundingClientRect();
7852
- var y = e.clientY - rect.top;
7853
- var percentage = 1 - Math.max(0, Math.min(1, y / rect.height));
7854
- handleVolumeChange(percentage);
7855
- },
7856
- children: [
7857
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
7858
- style: {
7859
- position: "absolute",
7860
- bottom: "0",
7861
- left: "0",
7862
- width: "100%",
7863
- height: "100%",
7864
- background: "linear-gradient(180deg, rgba(255, 255, 255, 0.4) 0%, rgba(255, 255, 255, 0.15) 100%)",
7865
- borderRadius: "4px",
7866
- boxShadow: "inset 0 1px 3px rgba(0, 0, 0, 0.2)"
7867
- }
7868
- }),
7869
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
7870
- style: {
7871
- position: "absolute",
7872
- bottom: "0",
7873
- left: "0",
7874
- width: "100%",
7875
- height: "".concat((isMuted ? 0 : volume) * 100, "%"),
7876
- background: "linear-gradient(180deg, rgba(96, 165, 250, 1) 0%, rgba(59, 130, 246, 0.95) 50%, rgba(37, 99, 235, 0.9) 100%)",
7877
- borderRadius: "4px",
7878
- transition: "height 0.15s ease-out, box-shadow 0.2s ease-in-out",
7879
- boxShadow: "0 0 8px rgba(59, 130, 246, 0.5), inset 0 1px 0 rgba(255, 255, 255, 0.3)"
7880
- }
7881
- }),
7882
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
7883
- style: {
7884
- position: "absolute",
7885
- bottom: "calc(".concat((isMuted ? 0 : volume) * 100, "% - 7px)"),
7886
- left: "50%",
7887
- transform: "translateX(-50%)",
7888
- width: "14px",
7889
- height: "14px",
7890
- background: "linear-gradient(135deg, #ffffff 0%, #f0f9ff 100%)",
7891
- borderRadius: "50%",
7892
- boxShadow: "0 2px 6px rgba(0, 0, 0, 0.3), 0 0 0 2px rgba(59, 130, 246, 0.3), 0 0 12px rgba(59, 130, 246, 0.4)",
7893
- transition: "bottom 0.15s ease-out, transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out, width 0.2s ease-in-out, height 0.2s ease-in-out",
7894
- cursor: "grab"
7895
- },
7896
- onMouseEnter: function onMouseEnter(e) {
7897
- e.currentTarget.style.boxShadow = "0 3px 10px rgba(0, 0, 0, 0.4), 0 0 0 3px rgba(59, 130, 246, 0.5), 0 0 20px rgba(59, 130, 246, 0.6)";
7898
- e.currentTarget.style.cursor = "grab";
7899
- },
7900
- onMouseLeave: function onMouseLeave(e) {
7901
- e.currentTarget.style.boxShadow = "0 2px 6px rgba(0, 0, 0, 0.3), 0 0 0 2px rgba(59, 130, 246, 0.3), 0 0 12px rgba(59, 130, 246, 0.4)";
7902
- },
7903
- onMouseDown: function onMouseDown(e) {
7904
- e.currentTarget.style.cursor = "grabbing";
7905
- },
7906
- onMouseUp: function onMouseUp(e) {
7907
- e.currentTarget.style.cursor = "grab";
7908
- }
7909
- })
7910
- ]
7911
- })
8313
+ top: 0,
8314
+ left: 0,
8315
+ bottom: 0,
8316
+ width: "".concat((isMuted ? 0 : volume) * 100, "%"),
8317
+ background: "#fff",
8318
+ borderRadius: "1.5px",
8319
+ transition: "width 0.1s ease-out"
8320
+ }
8321
+ }),
8322
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
8323
+ style: {
8324
+ position: "absolute",
8325
+ top: "50%",
8326
+ left: "".concat((isMuted ? 0 : volume) * 100, "%"),
8327
+ transform: "translate(-50%, -50%)",
8328
+ width: "12px",
8329
+ height: "12px",
8330
+ background: "#fff",
8331
+ borderRadius: "50%",
8332
+ boxShadow: "0 0 3px rgba(0, 0, 0, 0.3)",
8333
+ transition: "left 0.1s ease-out"
8334
+ }
7912
8335
  })
7913
8336
  ]
7914
8337
  })
7915
- ]
7916
- }),
7917
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
7918
- style: {
7919
- fontSize: "".concat(14 * responsiveScale, "px"),
7920
- fontFamily: "monospace",
7921
- color: "rgba(255, 255, 255, 0.9)",
7922
- display: viewportWidth < 480 ? "none" : "block"
7923
- },
7924
- children: [
7925
- formatTime(currentTime),
7926
- " / ",
7927
- formatTime(duration)
7928
- ]
7929
- })
7930
- ]
7931
- }),
7932
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
7933
- style: {
7934
- display: "flex",
7935
- alignItems: "center",
7936
- gap: "".concat(12 * responsiveScale, "px")
7937
- },
7938
- children: [
7939
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
7940
- style: {
7941
- position: "relative",
7942
- display: viewportWidth < 600 ? "none" : "block"
7943
- },
7944
- children: [
7945
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("button", {
7946
- onClick: function onClick() {
7947
- return setShowSpeedMenu(!showSpeedMenu);
7948
- },
7949
- style: {
7950
- background: "linear-gradient(135deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.6) 100%)",
7951
- backdropFilter: "blur(10px)",
7952
- border: "".concat(2 * responsiveScale, "px solid rgba(255, 255, 255, 0.3)"),
7953
- color: "#ffffff",
7954
- cursor: "pointer",
7955
- padding: "".concat(8 * responsiveScale, "px ").concat(14 * responsiveScale, "px"),
7956
- borderRadius: "".concat(14 * responsiveScale, "px"),
7957
- fontSize: "".concat(14 * responsiveScale, "px"),
7958
- fontFamily: "monospace",
7959
- fontWeight: "700",
7960
- transition: "all 0.3s cubic-bezier(0.4, 0, 0.2, 1)",
7961
- boxShadow: "0 6px 24px rgba(0, 0, 0, 0.4), 0 3px 12px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.25)",
7962
- minWidth: "".concat(56 * responsiveScale, "px"),
7963
- minHeight: "".concat(40 * responsiveScale, "px")
7964
- },
7965
- onMouseEnter: function onMouseEnter(e) {
7966
- var target = e.target;
7967
- target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.8) 0%, rgba(0, 0, 0, 0.7) 100%)";
7968
- target.style.boxShadow = "0 10px 32px rgba(0, 0, 0, 0.6), 0 5px 16px rgba(0, 0, 0, 0.4), inset 0 2px 0 rgba(255, 255, 255, 0.35)";
7969
- },
7970
- onMouseLeave: function onMouseLeave(e) {
7971
- var target = e.target;
7972
- target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.6) 100%)";
7973
- target.style.boxShadow = "0 6px 24px rgba(0, 0, 0, 0.4), 0 3px 12px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.25)";
7974
- },
7975
- title: "Playback Speed",
7976
- children: [
7977
- playbackRate,
7978
- "x"
7979
- ]
7980
- }),
7981
- showSpeedMenu && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
7982
- style: {
7983
- position: "absolute",
7984
- bottom: "100%",
7985
- right: 0,
7986
- marginBottom: "12px",
7987
- background: "linear-gradient(135deg, rgba(0, 0, 0, 0.9) 0%, rgba(20, 20, 20, 0.95) 100%)",
7988
- backdropFilter: "blur(20px)",
7989
- borderRadius: "12px",
7990
- border: "1px solid rgba(255, 255, 255, 0.1)",
7991
- overflow: "hidden",
7992
- minWidth: "90px",
7993
- boxShadow: "0 16px 48px rgba(0, 0, 0, 0.5), inset 0 1px 0 rgba(255, 255, 255, 0.1)"
7994
- },
7995
- children: [
7996
- 0.25,
7997
- 0.5,
7998
- 0.75,
7999
- 1,
8000
- 1.25,
8001
- 1.5,
8002
- 1.75,
8003
- 2
8004
- ].map(function(speed) {
8005
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("button", {
8006
- onClick: function onClick() {
8007
- return handlePlaybackRateChange(speed);
8008
- },
8009
- style: {
8010
- display: "block",
8011
- width: "100%",
8012
- padding: "10px 16px",
8013
- background: playbackRate === speed ? "linear-gradient(135deg, rgba(99, 102, 241, 0.8) 0%, rgba(139, 92, 246, 0.6) 100%)" : "transparent",
8014
- border: "none",
8015
- color: "white",
8016
- cursor: "pointer",
8017
- fontSize: "13px",
8018
- fontFamily: "monospace",
8019
- fontWeight: "600",
8020
- textAlign: "center",
8021
- transition: "all 0.2s cubic-bezier(0.4, 0, 0.2, 1)",
8022
- borderBottom: speed !== 2 ? "1px solid rgba(255, 255, 255, 0.05)" : "none"
8023
- },
8024
- onMouseEnter: function onMouseEnter(e) {
8025
- if (playbackRate !== speed) {
8026
- e.target.style.background = "linear-gradient(135deg, rgba(255, 255, 255, 0.15) 0%, rgba(255, 255, 255, 0.05) 100%)";
8027
- }
8028
- },
8029
- onMouseLeave: function onMouseLeave(e) {
8030
- if (playbackRate !== speed) {
8031
- e.target.style.background = "transparent";
8032
- }
8033
- },
8034
- children: [
8035
- speed,
8036
- "x"
8037
- ]
8038
- }, speed);
8039
- })
8040
- })
8041
- ]
8042
- }),
8043
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", {
8044
- onClick: function onClick() {
8045
- if (onFullscreenToggle) {
8046
- onFullscreenToggle();
8047
- } else if (playerRef.current) {
8048
- playerRef.current.toggleFullscreen().catch(function(err) {
8049
- console.error("Fullscreen error:", err);
8050
- });
8051
- }
8052
- },
8053
- style: {
8054
- background: "linear-gradient(135deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.6) 100%)",
8055
- backdropFilter: "blur(10px)",
8056
- border: "".concat(2 * responsiveScale, "px solid rgba(255, 255, 255, 0.3)"),
8057
- color: "#ffffff",
8058
- cursor: "pointer",
8059
- padding: "".concat(8 * responsiveScale, "px"),
8060
- borderRadius: "".concat(16 * responsiveScale, "px"),
8061
- display: "flex",
8062
- alignItems: "center",
8063
- justifyContent: "center",
8064
- transition: "all 0.3s cubic-bezier(0.4, 0, 0.2, 1)",
8065
- boxShadow: "0 6px 28px rgba(0, 0, 0, 0.4), 0 3px 12px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.25)",
8066
- minWidth: "".concat(44 * responsiveScale, "px"),
8067
- minHeight: "".concat(44 * responsiveScale, "px")
8068
- },
8069
- onMouseEnter: function onMouseEnter(e) {
8070
- var target = e.target;
8071
- target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.8) 0%, rgba(0, 0, 0, 0.7) 100%)";
8072
- target.style.boxShadow = "0 10px 36px rgba(0, 0, 0, 0.6), 0 5px 16px rgba(0, 0, 0, 0.4), inset 0 2px 0 rgba(255, 255, 255, 0.35)";
8073
- },
8074
- onMouseLeave: function onMouseLeave(e) {
8075
- var target = e.target;
8076
- target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.6) 100%)";
8077
- target.style.boxShadow = "0 6px 28px rgba(0, 0, 0, 0.4), 0 3px 12px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.25)";
8078
- },
8079
- title: isFullscreen ? "Exit Fullscreen" : "Enter Fullscreen",
8080
- children: isFullscreen ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_fa.FaCompress, {
8081
- size: Math.max(14, 16 * responsiveScale),
8338
+ })
8339
+ ]
8340
+ }),
8341
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
8342
+ style: {
8343
+ fontSize: "".concat(13 * responsiveScale, "px"),
8344
+ fontFamily: "Roboto, 'Segoe UI', Arial, sans-serif",
8345
+ color: "rgba(255, 255, 255, 0.9)",
8346
+ display: viewportWidth < 480 ? "none" : "block",
8347
+ fontVariantNumeric: "tabular-nums",
8348
+ userSelect: "none",
8349
+ marginLeft: "".concat(4 * responsiveScale, "px")
8350
+ },
8351
+ children: [
8352
+ formatTime(currentTime),
8353
+ " ",
8354
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
8082
8355
  style: {
8083
- filter: "drop-shadow(0 0 0 transparent)"
8084
- }
8085
- }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_fa.FaExpand, {
8086
- size: Math.max(14, 16 * responsiveScale),
8356
+ color: "rgba(255,255,255,0.5)"
8357
+ },
8358
+ children: "/"
8359
+ }),
8360
+ " ",
8361
+ formatTime(duration)
8362
+ ]
8363
+ })
8364
+ ]
8365
+ }),
8366
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
8367
+ style: {
8368
+ display: "flex",
8369
+ alignItems: "center",
8370
+ gap: "".concat(8 * responsiveScale, "px")
8371
+ },
8372
+ children: [
8373
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
8374
+ style: {
8375
+ position: "relative",
8376
+ display: viewportWidth < 600 ? "none" : "block"
8377
+ },
8378
+ children: [
8379
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("button", {
8380
+ className: "sc-ctrl-btn",
8381
+ onClick: function onClick() {
8382
+ setShowSpeedMenu(!showSpeedMenu);
8383
+ resetControlsTimer();
8384
+ },
8087
8385
  style: {
8088
- filter: "drop-shadow(0 0 0 transparent)"
8089
- }
8386
+ padding: "".concat(6 * responsiveScale, "px ").concat(10 * responsiveScale, "px"),
8387
+ borderRadius: "".concat(6 * responsiveScale, "px"),
8388
+ fontSize: "".concat(13 * responsiveScale, "px"),
8389
+ fontFamily: "'SF Mono', 'Cascadia Code', monospace",
8390
+ fontWeight: "600",
8391
+ minHeight: "".concat(32 * responsiveScale, "px")
8392
+ },
8393
+ title: "Playback Speed",
8394
+ children: [
8395
+ playbackRate,
8396
+ "x"
8397
+ ]
8398
+ }),
8399
+ showSpeedMenu && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
8400
+ style: {
8401
+ position: "absolute",
8402
+ bottom: "100%",
8403
+ right: 0,
8404
+ marginBottom: "8px",
8405
+ background: "rgba(0, 0, 0, 0.8)",
8406
+ backdropFilter: "blur(24px)",
8407
+ WebkitBackdropFilter: "blur(24px)",
8408
+ borderRadius: "10px",
8409
+ border: "1px solid rgba(255, 255, 255, 0.1)",
8410
+ overflow: "hidden",
8411
+ minWidth: "80px",
8412
+ boxShadow: "0 12px 40px rgba(0, 0, 0, 0.5)",
8413
+ animation: "sc-fade-in 0.15s ease"
8414
+ },
8415
+ children: [
8416
+ 0.25,
8417
+ 0.5,
8418
+ 0.75,
8419
+ 1,
8420
+ 1.25,
8421
+ 1.5,
8422
+ 1.75,
8423
+ 2
8424
+ ].map(function(speed) {
8425
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("button", {
8426
+ onClick: function onClick() {
8427
+ return handlePlaybackRateChange(speed);
8428
+ },
8429
+ style: {
8430
+ display: "block",
8431
+ width: "100%",
8432
+ padding: "".concat(8 * responsiveScale, "px ").concat(14 * responsiveScale, "px"),
8433
+ background: playbackRate === speed ? "rgba(255, 255, 255, 0.12)" : "transparent",
8434
+ border: "none",
8435
+ color: playbackRate === speed ? "#fff" : "rgba(255, 255, 255, 0.7)",
8436
+ cursor: "pointer",
8437
+ fontSize: "".concat(12 * responsiveScale, "px"),
8438
+ fontFamily: "'SF Mono', monospace",
8439
+ fontWeight: playbackRate === speed ? "700" : "500",
8440
+ textAlign: "center",
8441
+ transition: "background 0.15s ease, color 0.15s ease"
8442
+ },
8443
+ onMouseEnter: function onMouseEnter(e) {
8444
+ if (playbackRate !== speed) {
8445
+ e.target.style.background = "rgba(255, 255, 255, 0.08)";
8446
+ e.target.style.color = "#fff";
8447
+ }
8448
+ },
8449
+ onMouseLeave: function onMouseLeave(e) {
8450
+ if (playbackRate !== speed) {
8451
+ e.target.style.background = "transparent";
8452
+ e.target.style.color = "rgba(255, 255, 255, 0.7)";
8453
+ }
8454
+ },
8455
+ children: [
8456
+ speed,
8457
+ "x"
8458
+ ]
8459
+ }, speed);
8460
+ })
8090
8461
  })
8462
+ ]
8463
+ }),
8464
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", {
8465
+ className: "sc-ctrl-btn",
8466
+ onClick: function onClick() {
8467
+ if (onFullscreenToggle) {
8468
+ onFullscreenToggle();
8469
+ } else if (wrapperRef.current) {
8470
+ if (!document.fullscreenElement) {
8471
+ wrapperRef.current.requestFullscreen().catch(function() {});
8472
+ } else {
8473
+ document.exitFullscreen().catch(function() {});
8474
+ }
8475
+ }
8476
+ resetControlsTimer();
8477
+ },
8478
+ style: {
8479
+ padding: "".concat(8 * responsiveScale, "px"),
8480
+ borderRadius: "50%",
8481
+ minWidth: "".concat(36 * responsiveScale, "px"),
8482
+ minHeight: "".concat(36 * responsiveScale, "px")
8483
+ },
8484
+ title: isFullscreen ? "Exit Fullscreen" : "Enter Fullscreen",
8485
+ children: isFullscreen ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_fa.FaCompress, {
8486
+ size: Math.max(14, 18 * responsiveScale)
8487
+ }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_fa.FaExpand, {
8488
+ size: Math.max(14, 18 * responsiveScale)
8091
8489
  })
8092
- ]
8093
- })
8094
- ]
8095
- })
8096
- ]
8097
- })
8490
+ })
8491
+ ]
8492
+ })
8493
+ ]
8494
+ })
8495
+ ]
8098
8496
  }) : showCustomControls && !showLicenseWarning && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
8497
+ className: "sc-controls-bar",
8099
8498
  style: {
8100
8499
  position: "absolute",
8101
8500
  bottom: "".concat(10 * responsiveScale, "px"),
8102
8501
  right: "".concat(10 * responsiveScale, "px"),
8103
- transform: "none",
8104
8502
  display: "flex",
8105
8503
  flexDirection: isPortrait ? "column" : "row",
8106
- gap: "".concat(10 * responsiveScale, "px"),
8107
- zIndex: 10
8504
+ gap: "".concat(8 * responsiveScale, "px"),
8505
+ zIndex: 10,
8506
+ opacity: controlsVisible ? 1 : 0,
8507
+ transform: controlsVisible ? "translateY(0)" : "translateY(4px)",
8508
+ pointerEvents: controlsVisible ? "auto" : "none"
8108
8509
  },
8109
8510
  children: [
8110
8511
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
8111
8512
  style: {
8112
- position: "relative",
8113
8513
  display: "flex",
8114
8514
  alignItems: "center",
8115
- padding: "8px",
8116
- margin: "-8px"
8515
+ background: "rgba(0, 0, 0, 0.6)",
8516
+ borderRadius: "".concat(18 * responsiveScale, "px"),
8517
+ padding: "2px"
8117
8518
  },
8118
8519
  onMouseEnter: function onMouseEnter() {
8119
8520
  return setShowVolumeSlider(true);
@@ -8123,260 +8524,128 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
8123
8524
  },
8124
8525
  children: [
8125
8526
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", {
8527
+ className: "sc-ctrl-btn",
8126
8528
  onClick: function onClick() {
8127
- if (playerRef.current) {
8128
- playerRef.current.toggleMute();
8129
- }
8130
- if (onVolumeToggle) {
8131
- onVolumeToggle();
8132
- }
8133
- },
8134
- onMouseEnter: function onMouseEnter(e) {
8135
- var target = e.currentTarget;
8136
- target.style.boxShadow = "0 14px 48px rgba(0, 0, 0, 0.7), 0 0 0 3px rgba(255, 255, 255, 0.8), inset 0 2px 0 rgba(255, 255, 255, 0.4)";
8137
- target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.85) 0%, rgba(0, 0, 0, 0.75) 100%)";
8138
- },
8139
- onMouseLeave: function onMouseLeave(e) {
8140
- var target = e.currentTarget;
8141
- target.style.boxShadow = "0 10px 36px rgba(0, 0, 0, 0.6), 0 0 0 2px rgba(255, 255, 255, 0.7), inset 0 1px 0 rgba(255, 255, 255, 0.3)";
8142
- target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.75) 0%, rgba(0, 0, 0, 0.65) 100%)";
8529
+ if (playerRef.current) playerRef.current.toggleMute();
8530
+ onVolumeToggle === null || onVolumeToggle === void 0 ? void 0 : onVolumeToggle();
8531
+ resetControlsTimer();
8143
8532
  },
8144
8533
  style: {
8145
- background: "linear-gradient(135deg, rgba(0, 0, 0, 0.75) 0%, rgba(0, 0, 0, 0.65) 100%)",
8146
- color: "#ffffff",
8147
- border: "none",
8148
- borderRadius: "".concat(18 * responsiveScale, "px"),
8149
8534
  padding: "".concat(8 * responsiveScale, "px"),
8150
- cursor: "pointer",
8151
- display: "flex",
8152
- alignItems: "center",
8153
- justifyContent: "center",
8154
- backdropFilter: "blur(20px)",
8155
- boxShadow: "0 10px 36px rgba(0, 0, 0, 0.6), 0 0 0 2px rgba(255, 255, 255, 0.7), inset 0 1px 0 rgba(255, 255, 255, 0.3)",
8156
- transition: "all 0.4s cubic-bezier(0.4, 0, 0.2, 1)",
8157
- minWidth: "".concat(46 * responsiveScale, "px"),
8158
- minHeight: "".concat(46 * responsiveScale, "px")
8535
+ borderRadius: "50%",
8536
+ minWidth: "".concat(36 * responsiveScale, "px"),
8537
+ minHeight: "".concat(36 * responsiveScale, "px")
8159
8538
  },
8160
8539
  title: isMuted ? "Unmute" : "Mute",
8161
- children: isMuted || volume === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_fa.FaVolumeMute, {
8162
- size: Math.max(14, 16 * responsiveScale),
8163
- style: {
8164
- filter: "drop-shadow(0 2px 4px rgba(0, 0, 0, 0.8))",
8165
- color: "#ffffff"
8166
- }
8167
- }) : volume < 0.5 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_fa.FaVolumeDown, {
8168
- size: Math.max(14, 16 * responsiveScale),
8169
- style: {
8170
- filter: "drop-shadow(0 2px 4px rgba(0, 0, 0, 0.8))",
8171
- color: "#ffffff"
8172
- }
8173
- }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_fa.FaVolumeUp, {
8174
- size: Math.max(14, 16 * responsiveScale),
8175
- style: {
8176
- filter: "drop-shadow(0 2px 4px rgba(0, 0, 0, 0.8))",
8177
- color: "#ffffff"
8178
- }
8540
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(VolumeIcon, {
8541
+ size: Math.max(14, 18 * responsiveScale)
8179
8542
  })
8180
8543
  }),
8181
- showVolumeSlider && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, {
8182
- children: [
8183
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
8184
- style: {
8185
- position: "absolute",
8186
- bottom: "100%",
8187
- left: "50%",
8188
- transform: "translateX(-50%)",
8189
- width: "60px",
8190
- height: "20px",
8191
- marginBottom: "-16px",
8192
- zIndex: 9
8193
- },
8194
- onMouseEnter: function onMouseEnter() {
8195
- return setShowVolumeSlider(true);
8196
- },
8197
- onMouseLeave: function onMouseLeave() {
8198
- return setShowVolumeSlider(false);
8199
- }
8200
- }),
8201
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
8202
- style: {
8203
- position: "absolute",
8204
- bottom: "100%",
8205
- left: "50%",
8206
- transform: "translateX(-50%)",
8207
- marginBottom: "4px",
8208
- background: "linear-gradient(135deg, rgba(0, 0, 0, 0.96) 0%, rgba(20, 20, 20, 0.92) 100%)",
8209
- backdropFilter: "blur(20px)",
8210
- padding: "10px 14px",
8211
- borderRadius: "14px",
8212
- border: "2px solid rgba(255, 255, 255, 0.7)",
8213
- display: "flex",
8214
- flexDirection: "column",
8215
- alignItems: "center",
8216
- justifyContent: "center",
8217
- height: "128px",
8218
- boxShadow: "0 12px 40px rgba(0, 0, 0, 0.85), 0 4px 12px rgba(0, 0, 0, 0.6), inset 0 1px 0 rgba(255, 255, 255, 0.35)",
8219
- zIndex: 10,
8220
- transition: "transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out, border-color 0.2s ease-in-out"
8221
- },
8222
- onMouseEnter: function onMouseEnter(e) {
8223
- setShowVolumeSlider(true);
8224
- e.currentTarget.style.boxShadow = "0 16px 48px rgba(0, 0, 0, 0.9), 0 6px 16px rgba(0, 0, 0, 0.7), inset 0 1px 0 rgba(255, 255, 255, 0.4), 0 0 24px rgba(96, 165, 250, 0.4)";
8225
- e.currentTarget.style.borderColor = "rgba(96, 165, 250, 0.8)";
8226
- },
8227
- onMouseLeave: function onMouseLeave(e) {
8228
- setShowVolumeSlider(false);
8229
- e.currentTarget.style.boxShadow = "0 12px 40px rgba(0, 0, 0, 0.85), 0 4px 12px rgba(0, 0, 0, 0.6), inset 0 1px 0 rgba(255, 255, 255, 0.35)";
8230
- e.currentTarget.style.borderColor = "rgba(255, 255, 255, 0.7)";
8231
- },
8232
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
8544
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
8545
+ style: {
8546
+ width: showVolumeSlider ? "".concat(62 * responsiveScale, "px") : "0px",
8547
+ overflow: "hidden",
8548
+ transition: "width 0.2s cubic-bezier(0.4, 0, 0.2, 1)",
8549
+ display: "flex",
8550
+ alignItems: "center",
8551
+ paddingLeft: showVolumeSlider ? "2px" : "0",
8552
+ paddingRight: showVolumeSlider ? "6px" : "0"
8553
+ },
8554
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
8555
+ style: {
8556
+ position: "relative",
8557
+ width: "".concat(56 * responsiveScale, "px"),
8558
+ height: "3px",
8559
+ cursor: "pointer",
8560
+ borderRadius: "1.5px"
8561
+ },
8562
+ onMouseDown: function onMouseDown(e) {
8563
+ e.preventDefault();
8564
+ var el = e.currentTarget;
8565
+ var move = function move(ev) {
8566
+ var r2 = el.getBoundingClientRect();
8567
+ handleVolumeChange(Math.max(0, Math.min(1, (ev.clientX - r2.left) / r2.width)));
8568
+ };
8569
+ var up = function up1() {
8570
+ document.removeEventListener("mousemove", move);
8571
+ document.removeEventListener("mouseup", up);
8572
+ };
8573
+ document.addEventListener("mousemove", move);
8574
+ document.addEventListener("mouseup", up);
8575
+ var r = el.getBoundingClientRect();
8576
+ handleVolumeChange(Math.max(0, Math.min(1, (e.clientX - r.left) / r.width)));
8577
+ },
8578
+ onClick: function onClick(e) {
8579
+ e.stopPropagation();
8580
+ var r = e.currentTarget.getBoundingClientRect();
8581
+ handleVolumeChange(Math.max(0, Math.min(1, (e.clientX - r.left) / r.width)));
8582
+ },
8583
+ children: [
8584
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
8233
8585
  style: {
8234
- position: "relative",
8235
- width: "8px",
8236
- height: "104px",
8237
- cursor: "pointer",
8238
- transition: "transform 0.2s ease-in-out"
8239
- },
8240
- onMouseDown: function onMouseDown(e) {
8241
- e.preventDefault();
8242
- var sliderElement = e.currentTarget;
8243
- var handleMouseMove = function handleMouseMove(moveEvent) {
8244
- if (!sliderElement) return;
8245
- var rect2 = sliderElement.getBoundingClientRect();
8246
- var y2 = moveEvent.clientY - rect2.top;
8247
- var percentage2 = 1 - Math.max(0, Math.min(1, y2 / rect2.height));
8248
- handleVolumeChange(percentage2);
8249
- };
8250
- var handleMouseUp = function handleMouseUp1() {
8251
- document.removeEventListener("mousemove", handleMouseMove);
8252
- document.removeEventListener("mouseup", handleMouseUp);
8253
- };
8254
- document.addEventListener("mousemove", handleMouseMove);
8255
- document.addEventListener("mouseup", handleMouseUp);
8256
- var rect = sliderElement.getBoundingClientRect();
8257
- var y = e.clientY - rect.top;
8258
- var percentage = 1 - Math.max(0, Math.min(1, y / rect.height));
8259
- handleVolumeChange(percentage);
8260
- },
8261
- onClick: function onClick(e) {
8262
- e.stopPropagation();
8263
- var rect = e.currentTarget.getBoundingClientRect();
8264
- var y = e.clientY - rect.top;
8265
- var percentage = 1 - Math.max(0, Math.min(1, y / rect.height));
8266
- handleVolumeChange(percentage);
8267
- },
8268
- children: [
8269
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
8270
- style: {
8271
- position: "absolute",
8272
- bottom: "0",
8273
- left: "0",
8274
- width: "100%",
8275
- height: "100%",
8276
- background: "linear-gradient(180deg, rgba(255, 255, 255, 0.85) 0%, rgba(255, 255, 255, 0.5) 100%)",
8277
- borderRadius: "4px",
8278
- border: "1px solid rgba(255, 255, 255, 0.4)",
8279
- boxShadow: "inset 0 1px 3px rgba(0, 0, 0, 0.3)"
8280
- }
8281
- }),
8282
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
8283
- style: {
8284
- position: "absolute",
8285
- bottom: "0",
8286
- left: "0",
8287
- width: "100%",
8288
- height: "".concat((isMuted ? 0 : volume) * 100, "%"),
8289
- background: "linear-gradient(180deg, rgba(125, 211, 252, 1) 0%, rgba(96, 165, 250, 0.98) 50%, rgba(59, 130, 246, 0.95) 100%)",
8290
- borderRadius: "4px",
8291
- transition: "height 0.15s ease-out, box-shadow 0.2s ease-in-out",
8292
- boxShadow: "0 0 12px rgba(96, 165, 250, 0.6), inset 0 1px 0 rgba(255, 255, 255, 0.4)"
8293
- }
8294
- }),
8295
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
8296
- style: {
8297
- position: "absolute",
8298
- bottom: "calc(".concat((isMuted ? 0 : volume) * 100, "% - 8px)"),
8299
- left: "50%",
8300
- transform: "translateX(-50%)",
8301
- width: "16px",
8302
- height: "16px",
8303
- background: "linear-gradient(135deg, #ffffff 0%, #f0f9ff 100%)",
8304
- borderRadius: "50%",
8305
- border: "2px solid rgba(96, 165, 250, 0.9)",
8306
- boxShadow: "0 3px 8px rgba(0, 0, 0, 0.5), 0 0 0 2px rgba(96, 165, 250, 0.4), 0 0 16px rgba(96, 165, 250, 0.5)",
8307
- transition: "bottom 0.15s ease-out, transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out, width 0.2s ease-in-out, height 0.2s ease-in-out",
8308
- cursor: "grab"
8309
- },
8310
- onMouseEnter: function onMouseEnter(e) {
8311
- e.currentTarget.style.boxShadow = "0 4px 12px rgba(0, 0, 0, 0.6), 0 0 0 3px rgba(96, 165, 250, 0.6), 0 0 24px rgba(96, 165, 250, 0.7)";
8312
- e.currentTarget.style.cursor = "grab";
8313
- },
8314
- onMouseLeave: function onMouseLeave(e) {
8315
- e.currentTarget.style.boxShadow = "0 3px 8px rgba(0, 0, 0, 0.5), 0 0 0 2px rgba(96, 165, 250, 0.4), 0 0 16px rgba(96, 165, 250, 0.5)";
8316
- },
8317
- onMouseDown: function onMouseDown(e) {
8318
- e.currentTarget.style.cursor = "grabbing";
8319
- },
8320
- onMouseUp: function onMouseUp(e) {
8321
- e.currentTarget.style.cursor = "grab";
8322
- }
8323
- })
8324
- ]
8586
+ position: "absolute",
8587
+ inset: 0,
8588
+ background: "rgba(255, 255, 255, 0.2)",
8589
+ borderRadius: "1.5px"
8590
+ }
8591
+ }),
8592
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
8593
+ style: {
8594
+ position: "absolute",
8595
+ top: 0,
8596
+ left: 0,
8597
+ bottom: 0,
8598
+ width: "".concat((isMuted ? 0 : volume) * 100, "%"),
8599
+ background: "#fff",
8600
+ borderRadius: "1.5px",
8601
+ transition: "width 0.1s ease-out"
8602
+ }
8603
+ }),
8604
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
8605
+ style: {
8606
+ position: "absolute",
8607
+ top: "50%",
8608
+ left: "".concat((isMuted ? 0 : volume) * 100, "%"),
8609
+ transform: "translate(-50%, -50%)",
8610
+ width: "12px",
8611
+ height: "12px",
8612
+ background: "#fff",
8613
+ borderRadius: "50%",
8614
+ boxShadow: "0 0 3px rgba(0, 0, 0, 0.3)",
8615
+ transition: "left 0.1s ease-out"
8616
+ }
8325
8617
  })
8326
- })
8327
- ]
8618
+ ]
8619
+ })
8328
8620
  })
8329
8621
  ]
8330
8622
  }),
8331
8623
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", {
8624
+ className: "sc-ctrl-btn",
8332
8625
  onClick: function onClick() {
8333
8626
  if (onFullscreenToggle) {
8334
8627
  onFullscreenToggle();
8335
- } else if (playerRef.current) {
8336
- playerRef.current.toggleFullscreen().catch(function(err) {
8337
- console.error("Fullscreen error:", err);
8338
- });
8628
+ } else if (wrapperRef.current) {
8629
+ if (!document.fullscreenElement) {
8630
+ wrapperRef.current.requestFullscreen().catch(function() {});
8631
+ } else {
8632
+ document.exitFullscreen().catch(function() {});
8633
+ }
8339
8634
  }
8340
- },
8341
- onMouseEnter: function onMouseEnter(e) {
8342
- var target = e.currentTarget;
8343
- target.style.boxShadow = "0 14px 48px rgba(0, 0, 0, 0.7), 0 0 0 3px rgba(255, 255, 255, 0.8), inset 0 2px 0 rgba(255, 255, 255, 0.4)";
8344
- target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.85) 0%, rgba(0, 0, 0, 0.75) 100%)";
8345
- },
8346
- onMouseLeave: function onMouseLeave(e) {
8347
- var target = e.currentTarget;
8348
- target.style.boxShadow = "0 10px 36px rgba(0, 0, 0, 0.6), 0 0 0 2px rgba(255, 255, 255, 0.7), inset 0 1px 0 rgba(255, 255, 255, 0.3)";
8349
- target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.75) 0%, rgba(0, 0, 0, 0.65) 100%)";
8635
+ resetControlsTimer();
8350
8636
  },
8351
8637
  style: {
8352
- background: "linear-gradient(135deg, rgba(0, 0, 0, 0.75) 0%, rgba(0, 0, 0, 0.65) 100%)",
8353
- color: "#ffffff",
8354
- border: "none",
8355
- borderRadius: "".concat(18 * responsiveScale, "px"),
8356
8638
  padding: "".concat(8 * responsiveScale, "px"),
8357
- cursor: "pointer",
8358
- display: "flex",
8359
- alignItems: "center",
8360
- justifyContent: "center",
8361
- backdropFilter: "blur(20px)",
8362
- boxShadow: "0 10px 36px rgba(0, 0, 0, 0.6), 0 0 0 2px rgba(255, 255, 255, 0.7), inset 0 1px 0 rgba(255, 255, 255, 0.3)",
8363
- transition: "all 0.4s cubic-bezier(0.4, 0, 0.2, 1)",
8364
- minWidth: "".concat(46 * responsiveScale, "px"),
8365
- minHeight: "".concat(46 * responsiveScale, "px")
8639
+ borderRadius: "50%",
8640
+ minWidth: "".concat(36 * responsiveScale, "px"),
8641
+ minHeight: "".concat(36 * responsiveScale, "px"),
8642
+ background: "rgba(0, 0, 0, 0.6)"
8366
8643
  },
8367
8644
  title: isFullscreen ? "Exit Fullscreen" : "Enter Fullscreen",
8368
8645
  children: isFullscreen ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_fa.FaCompress, {
8369
- size: Math.max(14, 16 * responsiveScale),
8370
- style: {
8371
- filter: "drop-shadow(0 2px 4px rgba(0, 0, 0, 0.8))",
8372
- color: "#ffffff"
8373
- }
8646
+ size: Math.max(14, 18 * responsiveScale)
8374
8647
  }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_fa.FaExpand, {
8375
- size: Math.max(14, 16 * responsiveScale),
8376
- style: {
8377
- filter: "drop-shadow(0 2px 4px rgba(0, 0, 0, 0.8))",
8378
- color: "#ffffff"
8379
- }
8648
+ size: Math.max(14, 18 * responsiveScale)
8380
8649
  })
8381
8650
  })
8382
8651
  ]
@@ -8516,6 +8785,7 @@ var defaultProps = {
8516
8785
  showCustomControls: false,
8517
8786
  hideLoadingIndicator: false,
8518
8787
  licenseKey: "",
8788
+ vmapUrl: "",
8519
8789
  adFailsafeTimeoutMs: 1e4,
8520
8790
  minSegmentsBeforePlay: 2,
8521
8791
  onStart: noop,
@@ -9459,6 +9729,7 @@ var SUPPORTED_PROPS = [
9459
9729
  "debugAdTiming",
9460
9730
  "showCustomControls",
9461
9731
  "licenseKey",
9732
+ "vmapUrl",
9462
9733
  "adFailsafeTimeoutMs",
9463
9734
  "minSegmentsBeforePlay",
9464
9735
  "onReady",
@@ -9674,6 +9945,9 @@ var StormcloudPlayer_default = StormcloudPlayer;
9674
9945
  parseQuery: parseQuery,
9675
9946
  players: players,
9676
9947
  randomString: randomString,
9948
+ sendAdDetectTracking: sendAdDetectTracking,
9949
+ sendAdImpressionTracking: sendAdImpressionTracking,
9950
+ sendAdLoadedTracking: sendAdLoadedTracking,
9677
9951
  sendHeartbeat: sendHeartbeat,
9678
9952
  sendInitialTracking: sendInitialTracking,
9679
9953
  supportsFeature: supportsFeature,