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.
@@ -2647,9 +2647,6 @@ function sendInitialTracking(licenseKey) {
2647
2647
  headers = {
2648
2648
  "Content-Type": "application/json"
2649
2649
  };
2650
- if (licenseKey) {
2651
- headers["Authorization"] = "Bearer ".concat(licenseKey);
2652
- }
2653
2650
  return [
2654
2651
  4,
2655
2652
  fetch("https://adstorm.co/api-adstorm-dev/adstorm/player-tracking/track", {
@@ -2755,6 +2752,234 @@ function sendHeartbeat(licenseKey) {
2755
2752
  });
2756
2753
  })();
2757
2754
  }
2755
+ var TRACK_API_URL = "https://adstorm.co/api-adstorm-dev/adstorm/player-tracking/track";
2756
+ function mapToAdTrackingSource(source, adPlayerType) {
2757
+ if (source === "prebid" || source === "ima" || source === "hls") {
2758
+ return source;
2759
+ }
2760
+ if (source === "preload" || source === "ssp") {
2761
+ return source === "ssp" ? "prebid" : "ima";
2762
+ }
2763
+ return adPlayerType === "hls" ? "hls" : "ima";
2764
+ }
2765
+ function postAdTracking(licenseKey, body) {
2766
+ return _async_to_generator(function() {
2767
+ var headers, response;
2768
+ return _ts_generator(this, function(_state) {
2769
+ switch(_state.label){
2770
+ case 0:
2771
+ headers = {
2772
+ "Content-Type": "application/json"
2773
+ };
2774
+ if (licenseKey) {
2775
+ headers["Authorization"] = "Bearer ".concat(licenseKey);
2776
+ }
2777
+ return [
2778
+ 4,
2779
+ fetch(TRACK_API_URL, {
2780
+ method: "POST",
2781
+ headers: headers,
2782
+ body: JSON.stringify(body)
2783
+ })
2784
+ ];
2785
+ case 1:
2786
+ response = _state.sent();
2787
+ if (!response.ok) {
2788
+ throw new Error("HTTP error! status: ".concat(response.status));
2789
+ }
2790
+ return [
2791
+ 4,
2792
+ response.json()
2793
+ ];
2794
+ case 2:
2795
+ _state.sent();
2796
+ return [
2797
+ 2
2798
+ ];
2799
+ }
2800
+ });
2801
+ })();
2802
+ }
2803
+ function sendAdDetectTracking(licenseKey, payload) {
2804
+ return _async_to_generator(function() {
2805
+ var _payload_source, _payload_timestamp, clientInfo, browserId, adDetectInfo, body, error;
2806
+ return _ts_generator(this, function(_state) {
2807
+ switch(_state.label){
2808
+ case 0:
2809
+ _state.trys.push([
2810
+ 0,
2811
+ 3,
2812
+ ,
2813
+ 4
2814
+ ]);
2815
+ clientInfo = getClientInfo();
2816
+ return [
2817
+ 4,
2818
+ getBrowserID(clientInfo)
2819
+ ];
2820
+ case 1:
2821
+ browserId = _state.sent();
2822
+ adDetectInfo = _object_spread({
2823
+ source: (_payload_source = payload.source) !== null && _payload_source !== void 0 ? _payload_source : "scte35",
2824
+ timestamp: (_payload_timestamp = payload.timestamp) !== null && _payload_timestamp !== void 0 ? _payload_timestamp : /* @__PURE__ */ new Date().toISOString()
2825
+ }, payload.durationSeconds != null && {
2826
+ durationSeconds: payload.durationSeconds
2827
+ }, payload.ptsSeconds != null && {
2828
+ ptsSeconds: payload.ptsSeconds
2829
+ }, payload.detectedAtFragmentSn != null && {
2830
+ detectedAtFragmentSn: payload.detectedAtFragmentSn
2831
+ });
2832
+ body = _object_spread_props(_object_spread({
2833
+ browserId: browserId
2834
+ }, clientInfo, licenseKey && {
2835
+ licenseKey: licenseKey
2836
+ }), {
2837
+ adDetectInfo: adDetectInfo
2838
+ });
2839
+ return [
2840
+ 4,
2841
+ postAdTracking(licenseKey, body)
2842
+ ];
2843
+ case 2:
2844
+ _state.sent();
2845
+ return [
2846
+ 3,
2847
+ 4
2848
+ ];
2849
+ case 3:
2850
+ error = _state.sent();
2851
+ console.error("[StormcloudVideoPlayer] Error sending ad-detect tracking:", error);
2852
+ return [
2853
+ 3,
2854
+ 4
2855
+ ];
2856
+ case 4:
2857
+ return [
2858
+ 2
2859
+ ];
2860
+ }
2861
+ });
2862
+ })();
2863
+ }
2864
+ function sendAdLoadedTracking(licenseKey, payload, adPlayerType) {
2865
+ return _async_to_generator(function() {
2866
+ var clientInfo, browserId, source, adLoadedInfo, body, error;
2867
+ return _ts_generator(this, function(_state) {
2868
+ switch(_state.label){
2869
+ case 0:
2870
+ _state.trys.push([
2871
+ 0,
2872
+ 3,
2873
+ ,
2874
+ 4
2875
+ ]);
2876
+ clientInfo = getClientInfo();
2877
+ return [
2878
+ 4,
2879
+ getBrowserID(clientInfo)
2880
+ ];
2881
+ case 1:
2882
+ browserId = _state.sent();
2883
+ source = mapToAdTrackingSource(payload.source, adPlayerType);
2884
+ adLoadedInfo = _object_spread({
2885
+ source: source,
2886
+ timestamp: /* @__PURE__ */ new Date().toISOString()
2887
+ }, payload.vastUrl != null && {
2888
+ vastUrl: payload.vastUrl
2889
+ }, payload.durationSeconds != null && {
2890
+ durationSeconds: payload.durationSeconds
2891
+ });
2892
+ body = _object_spread_props(_object_spread({
2893
+ browserId: browserId
2894
+ }, clientInfo, licenseKey && {
2895
+ licenseKey: licenseKey
2896
+ }), {
2897
+ adLoadedInfo: adLoadedInfo
2898
+ });
2899
+ return [
2900
+ 4,
2901
+ postAdTracking(licenseKey, body)
2902
+ ];
2903
+ case 2:
2904
+ _state.sent();
2905
+ return [
2906
+ 3,
2907
+ 4
2908
+ ];
2909
+ case 3:
2910
+ error = _state.sent();
2911
+ console.error("[StormcloudVideoPlayer] Error sending ad-loaded tracking:", error);
2912
+ return [
2913
+ 3,
2914
+ 4
2915
+ ];
2916
+ case 4:
2917
+ return [
2918
+ 2
2919
+ ];
2920
+ }
2921
+ });
2922
+ })();
2923
+ }
2924
+ function sendAdImpressionTracking(licenseKey, payload, adPlayerType) {
2925
+ return _async_to_generator(function() {
2926
+ var clientInfo, browserId, source, adImpressionInfo, body, error;
2927
+ return _ts_generator(this, function(_state) {
2928
+ switch(_state.label){
2929
+ case 0:
2930
+ _state.trys.push([
2931
+ 0,
2932
+ 3,
2933
+ ,
2934
+ 4
2935
+ ]);
2936
+ clientInfo = getClientInfo();
2937
+ return [
2938
+ 4,
2939
+ getBrowserID(clientInfo)
2940
+ ];
2941
+ case 1:
2942
+ browserId = _state.sent();
2943
+ source = mapToAdTrackingSource(payload.source, adPlayerType);
2944
+ adImpressionInfo = _object_spread({
2945
+ source: source,
2946
+ adIndex: payload.adIndex,
2947
+ timestamp: /* @__PURE__ */ new Date().toISOString()
2948
+ }, payload.durationSeconds != null && {
2949
+ durationSeconds: payload.durationSeconds
2950
+ });
2951
+ body = _object_spread_props(_object_spread({
2952
+ browserId: browserId
2953
+ }, clientInfo, licenseKey && {
2954
+ licenseKey: licenseKey
2955
+ }), {
2956
+ adImpressionInfo: adImpressionInfo
2957
+ });
2958
+ return [
2959
+ 4,
2960
+ postAdTracking(licenseKey, body)
2961
+ ];
2962
+ case 2:
2963
+ _state.sent();
2964
+ return [
2965
+ 3,
2966
+ 4
2967
+ ];
2968
+ case 3:
2969
+ error = _state.sent();
2970
+ console.error("[StormcloudVideoPlayer] Error sending ad-impression tracking:", error);
2971
+ return [
2972
+ 3,
2973
+ 4
2974
+ ];
2975
+ case 4:
2976
+ return [
2977
+ 2
2978
+ ];
2979
+ }
2980
+ });
2981
+ })();
2982
+ }
2758
2983
  // src/utils/polyfills.ts
2759
2984
  function polyfillURLSearchParams() {
2760
2985
  if (typeof URLSearchParams !== "undefined") {
@@ -3014,6 +3239,8 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3014
3239
  this.inAdBreak = false;
3015
3240
  this.ptsDriftEmaMs = 0;
3016
3241
  this.adPodQueue = [];
3242
+ this.vmapBreaks = [];
3243
+ this.consumedVmapBreakIds = /* @__PURE__ */ new Set();
3017
3244
  this.lastHeartbeatTime = 0;
3018
3245
  this.currentAdIndex = 0;
3019
3246
  this.totalAdsInBreak = 0;
@@ -3055,6 +3282,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3055
3282
  this.maxPreloadPoolSize = 2;
3056
3283
  this.preloadPoolActive = false;
3057
3284
  this.preloadPoolLoopRunning = false;
3285
+ this.adDetectSentForCurrentBreak = false;
3058
3286
  this.continuousFetchLoopRunning = false;
3059
3287
  initializePolyfills();
3060
3288
  var browserOverrides = getBrowserConfigOverrides();
@@ -3524,6 +3752,9 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3524
3752
  value: function attachImaEventListeners() {
3525
3753
  var _this = this;
3526
3754
  this.ima.on("all_ads_completed", function() {
3755
+ sendAdImpressionTracking(_this.config.licenseKey, {
3756
+ adIndex: _this.currentAdIndex
3757
+ }, _this.config.adPlayerType).catch(function() {});
3527
3758
  var remaining = _this.getRemainingAdMs();
3528
3759
  _this.consecutiveFailures = 0;
3529
3760
  if (_this.config.debugAdTiming) {
@@ -3586,6 +3817,9 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3586
3817
  }
3587
3818
  });
3588
3819
  this.ima.on("content_resume", function() {
3820
+ sendAdImpressionTracking(_this.config.licenseKey, {
3821
+ adIndex: _this.currentAdIndex
3822
+ }, _this.config.adPlayerType).catch(function() {});
3589
3823
  if (!_this.video.muted) {
3590
3824
  _this.video.muted = true;
3591
3825
  _this.video.volume = 0;
@@ -3969,6 +4203,13 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3969
4203
  }
3970
4204
  return;
3971
4205
  }
4206
+ if (!this.adDetectSentForCurrentBreak) {
4207
+ this.adDetectSentForCurrentBreak = true;
4208
+ var detectPayload = {};
4209
+ if (marker.durationSeconds != null) detectPayload.durationSeconds = marker.durationSeconds;
4210
+ if (marker.ptsSeconds != null) detectPayload.ptsSeconds = marker.ptsSeconds;
4211
+ sendAdDetectTracking(this.config.licenseKey, detectPayload).catch(function() {});
4212
+ }
3972
4213
  var hasPrefetchedAds = this.pendingAdBreak && this.pendingAdBreak.vastUrls.length > 0;
3973
4214
  this.inAdBreak = true;
3974
4215
  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;
@@ -4328,6 +4569,18 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4328
4569
  return _ts_generator(this, function(_state) {
4329
4570
  switch(_state.label){
4330
4571
  case 0:
4572
+ if (!this.config.vmapUrl) return [
4573
+ 3,
4574
+ 2
4575
+ ];
4576
+ return [
4577
+ 4,
4578
+ this.fetchAndParseVmap(this.config.vmapUrl)
4579
+ ];
4580
+ case 1:
4581
+ _state.sent();
4582
+ _state.label = 2;
4583
+ case 2:
4331
4584
  vastMode = this.config.vastMode || "default";
4332
4585
  if (this.config.debugAdTiming) {
4333
4586
  console.log("[StormcloudVideoPlayer] VAST mode:", vastMode);
@@ -4373,7 +4626,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4373
4626
  headers: headers
4374
4627
  })
4375
4628
  ];
4376
- case 1:
4629
+ case 3:
4377
4630
  response = _state.sent();
4378
4631
  if (!response.ok) {
4379
4632
  if (this.config.debugAdTiming) {
@@ -4387,7 +4640,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4387
4640
  4,
4388
4641
  response.json()
4389
4642
  ];
4390
- case 2:
4643
+ case 4:
4391
4644
  data = _state.sent();
4392
4645
  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;
4393
4646
  if (imaPayload) {
@@ -4416,35 +4669,200 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4416
4669
  }
4417
4670
  },
4418
4671
  {
4419
- key: "getCurrentAdIndex",
4420
- value: function getCurrentAdIndex() {
4421
- return this.currentAdIndex;
4672
+ key: "fetchAndParseVmap",
4673
+ value: function fetchAndParseVmap(vmapUrl) {
4674
+ return _async_to_generator(function() {
4675
+ var response, vmapXml, error;
4676
+ return _ts_generator(this, function(_state) {
4677
+ switch(_state.label){
4678
+ case 0:
4679
+ if (!vmapUrl.trim()) {
4680
+ return [
4681
+ 2
4682
+ ];
4683
+ }
4684
+ _state.label = 1;
4685
+ case 1:
4686
+ _state.trys.push([
4687
+ 1,
4688
+ 4,
4689
+ ,
4690
+ 5
4691
+ ]);
4692
+ return [
4693
+ 4,
4694
+ fetch(vmapUrl)
4695
+ ];
4696
+ case 2:
4697
+ response = _state.sent();
4698
+ if (!response.ok) {
4699
+ throw new Error("Failed to fetch VMAP (".concat(response.status, ")"));
4700
+ }
4701
+ return [
4702
+ 4,
4703
+ response.text()
4704
+ ];
4705
+ case 3:
4706
+ vmapXml = _state.sent();
4707
+ this.vmapBreaks = this.parseVmapToBreaks(vmapXml);
4708
+ this.consumedVmapBreakIds.clear();
4709
+ if (this.config.debugAdTiming) {
4710
+ console.log("[StormcloudVideoPlayer] Loaded ".concat(this.vmapBreaks.length, " VMAP ad break(s) from:"), vmapUrl);
4711
+ }
4712
+ return [
4713
+ 3,
4714
+ 5
4715
+ ];
4716
+ case 4:
4717
+ error = _state.sent();
4718
+ this.vmapBreaks = [];
4719
+ this.consumedVmapBreakIds.clear();
4720
+ if (this.config.debugAdTiming) {
4721
+ console.warn("[StormcloudVideoPlayer] Failed to load VMAP:", error);
4722
+ }
4723
+ return [
4724
+ 3,
4725
+ 5
4726
+ ];
4727
+ case 5:
4728
+ return [
4729
+ 2
4730
+ ];
4731
+ }
4732
+ });
4733
+ }).call(this);
4422
4734
  }
4423
4735
  },
4424
4736
  {
4425
- key: "getTotalAdsInBreak",
4426
- value: function getTotalAdsInBreak() {
4427
- return this.totalAdsInBreak;
4737
+ key: "parseVmapToBreaks",
4738
+ value: function parseVmapToBreaks(vmapXml) {
4739
+ var _this = this;
4740
+ if (typeof DOMParser === "undefined") {
4741
+ return [];
4742
+ }
4743
+ var doc = new DOMParser().parseFromString(vmapXml, "application/xml");
4744
+ if (doc.querySelector("parsererror")) {
4745
+ if (this.config.debugAdTiming) {
4746
+ console.warn("[StormcloudVideoPlayer] Invalid VMAP XML received");
4747
+ }
4748
+ return [];
4749
+ }
4750
+ var adBreakNodes = Array.from(doc.querySelectorAll("AdBreak, vmap\\:AdBreak"));
4751
+ var parsed = [];
4752
+ adBreakNodes.forEach(function(node, index) {
4753
+ var timeOffsetRaw = (node.getAttribute("timeOffset") || "").trim();
4754
+ var startTimeMs = _this.parseVmapTimeOffsetToMs(timeOffsetRaw);
4755
+ if (startTimeMs == null) {
4756
+ return;
4757
+ }
4758
+ var adTagNode = node.querySelector("AdTagURI, vmap\\:AdTagURI");
4759
+ var adTagUrl = ((adTagNode === null || adTagNode === void 0 ? void 0 : adTagNode.textContent) || "").trim();
4760
+ if (!adTagUrl) {
4761
+ return;
4762
+ }
4763
+ var breakId = node.getAttribute("breakId") || "vmap-break-".concat(index, "-").concat(timeOffsetRaw || "unknown");
4764
+ parsed.push({
4765
+ id: breakId,
4766
+ startTimeMs: startTimeMs,
4767
+ vastTagUrl: adTagUrl
4768
+ });
4769
+ });
4770
+ parsed.sort(function(a, b) {
4771
+ var aStart = a.startTimeMs < 0 ? Number.MAX_SAFE_INTEGER : a.startTimeMs;
4772
+ var bStart = b.startTimeMs < 0 ? Number.MAX_SAFE_INTEGER : b.startTimeMs;
4773
+ return aStart - bStart;
4774
+ });
4775
+ return parsed;
4428
4776
  }
4429
4777
  },
4430
4778
  {
4431
- key: "generateVastUrlsWithCorrelators",
4432
- value: function generateVastUrlsWithCorrelators(baseUrl, count) {
4433
- var urls = [];
4434
- var baseTimestamp = Date.now();
4435
- for(var i = 0; i < count; i++){
4436
- var timestamp = baseTimestamp + i;
4437
- var random = Math.floor(Math.random() * 1e12);
4438
- var uniqueCorrelator = "".concat(timestamp, "_").concat(random, "_").concat(i);
4439
- var urlWithCorrelator = void 0;
4440
- var correlatorRegex = /([?&])correlator=([^&]*)/;
4441
- if (correlatorRegex.test(baseUrl)) {
4442
- urlWithCorrelator = baseUrl.replace(correlatorRegex, "$1correlator=".concat(uniqueCorrelator));
4443
- } else if (baseUrl.includes("?")) {
4444
- urlWithCorrelator = "".concat(baseUrl, "&correlator=").concat(uniqueCorrelator);
4445
- } else {
4446
- urlWithCorrelator = "".concat(baseUrl, "?correlator=").concat(uniqueCorrelator);
4447
- }
4779
+ key: "parseVmapTimeOffsetToMs",
4780
+ value: function parseVmapTimeOffsetToMs(timeOffset) {
4781
+ if (!timeOffset) {
4782
+ return void 0;
4783
+ }
4784
+ var normalized = timeOffset.trim().toLowerCase();
4785
+ if (normalized === "start") {
4786
+ return 0;
4787
+ }
4788
+ if (normalized === "end") {
4789
+ return -1;
4790
+ }
4791
+ var hms = timeOffset.match(/^(\d{1,2}):(\d{2}):(\d{2})(?:\.(\d{1,3}))?$/);
4792
+ if (hms) {
4793
+ 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;
4794
+ var hours = Number(hh);
4795
+ var minutes = Number(mm);
4796
+ var seconds = Number(ss);
4797
+ var millis = Number(ms.padEnd(3, "0").slice(0, 3));
4798
+ return (hours * 3600 + minutes * 60 + seconds) * 1e3 + millis;
4799
+ }
4800
+ var percent = timeOffset.match(/^(\d+(?:\.\d+)?)%$/);
4801
+ if (percent) {
4802
+ var ratio = Number(percent[1]) / 100;
4803
+ var durationSec = this.video.duration;
4804
+ if (Number.isFinite(durationSec) && durationSec > 0) {
4805
+ return Math.floor(durationSec * 1e3 * ratio);
4806
+ }
4807
+ return void 0;
4808
+ }
4809
+ return void 0;
4810
+ }
4811
+ },
4812
+ {
4813
+ key: "getAdBreakKey",
4814
+ value: function getAdBreakKey(adBreak) {
4815
+ if (adBreak.id) {
4816
+ return adBreak.id;
4817
+ }
4818
+ return "".concat(adBreak.startTimeMs, "-").concat(adBreak.vastTagUrl || "");
4819
+ }
4820
+ },
4821
+ {
4822
+ key: "resolveBreakStartMs",
4823
+ value: function resolveBreakStartMs(adBreak) {
4824
+ if (adBreak.startTimeMs >= 0) {
4825
+ return adBreak.startTimeMs;
4826
+ }
4827
+ if (adBreak.startTimeMs === -1) {
4828
+ var durationSec = this.video.duration;
4829
+ if (Number.isFinite(durationSec) && durationSec > 0) {
4830
+ return Math.floor(durationSec * 1e3);
4831
+ }
4832
+ }
4833
+ return void 0;
4834
+ }
4835
+ },
4836
+ {
4837
+ key: "getCurrentAdIndex",
4838
+ value: function getCurrentAdIndex() {
4839
+ return this.currentAdIndex;
4840
+ }
4841
+ },
4842
+ {
4843
+ key: "getTotalAdsInBreak",
4844
+ value: function getTotalAdsInBreak() {
4845
+ return this.totalAdsInBreak;
4846
+ }
4847
+ },
4848
+ {
4849
+ key: "generateVastUrlsWithCorrelators",
4850
+ value: function generateVastUrlsWithCorrelators(baseUrl, count) {
4851
+ var urls = [];
4852
+ var baseTimestamp = Date.now();
4853
+ for(var i = 0; i < count; i++){
4854
+ var timestamp = baseTimestamp + i;
4855
+ var random = Math.floor(Math.random() * 1e12);
4856
+ var uniqueCorrelator = "".concat(timestamp, "_").concat(random, "_").concat(i);
4857
+ var urlWithCorrelator = void 0;
4858
+ var correlatorRegex = /([?&])correlator=([^&]*)/;
4859
+ if (correlatorRegex.test(baseUrl)) {
4860
+ urlWithCorrelator = baseUrl.replace(correlatorRegex, "$1correlator=".concat(uniqueCorrelator));
4861
+ } else if (baseUrl.includes("?")) {
4862
+ urlWithCorrelator = "".concat(baseUrl, "&correlator=").concat(uniqueCorrelator);
4863
+ } else {
4864
+ urlWithCorrelator = "".concat(baseUrl, "?correlator=").concat(uniqueCorrelator);
4865
+ }
4448
4866
  urls.push(urlWithCorrelator);
4449
4867
  }
4450
4868
  return urls;
@@ -4505,10 +4923,10 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4505
4923
  var scheduled = this.findCurrentOrNextBreak(this.video.currentTime * 1e3);
4506
4924
  var tags = this.selectVastTagsForBreak(scheduled);
4507
4925
  var baseVastUrl;
4508
- if (this.apiVastTagUrl) {
4509
- baseVastUrl = this.apiVastTagUrl;
4510
- } else if (tags && tags.length > 0 && tags[0]) {
4926
+ if (tags && tags.length > 0 && tags[0]) {
4511
4927
  baseVastUrl = tags[0];
4928
+ } else if (this.apiVastTagUrl) {
4929
+ baseVastUrl = this.apiVastTagUrl;
4512
4930
  } else {
4513
4931
  if (this.config.debugAdTiming) {
4514
4932
  console.warn("[StormcloudVideoPlayer] No VAST URL available for prefetch");
@@ -4526,6 +4944,12 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4526
4944
  isFetching: false,
4527
4945
  fetchStartTime: Date.now()
4528
4946
  });
4947
+ this.adDetectSentForCurrentBreak = true;
4948
+ var detectPayload = {};
4949
+ if (marker.durationSeconds != null) detectPayload.durationSeconds = marker.durationSeconds;
4950
+ if (marker.ptsSeconds != null) detectPayload.ptsSeconds = marker.ptsSeconds;
4951
+ if (fragmentSn !== void 0) detectPayload.detectedAtFragmentSn = fragmentSn;
4952
+ sendAdDetectTracking(this.config.licenseKey, detectPayload).catch(function() {});
4529
4953
  if (this.config.debugAdTiming) {
4530
4954
  console.log("[PREFETCH] \uD83D\uDD04 Starting ad prefetch for upcoming ad break");
4531
4955
  console.log("[PREFETCH] \uD83D\uDCCB Pre-generated ".concat(generatedUrls.length, " VAST URLs"));
@@ -4952,11 +5376,14 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4952
5376
  switch(_state.label){
4953
5377
  case 0:
4954
5378
  scheduled = this.findCurrentOrNextBreak(this.video.currentTime * 1e3);
5379
+ if (scheduled) {
5380
+ this.consumedVmapBreakIds.add(this.getAdBreakKey(scheduled));
5381
+ }
4955
5382
  tags = this.selectVastTagsForBreak(scheduled);
4956
- if (this.apiVastTagUrl) {
4957
- baseVastUrl = this.apiVastTagUrl;
4958
- } else if (tags && tags.length > 0 && tags[0]) {
5383
+ if (tags && tags.length > 0 && tags[0]) {
4959
5384
  baseVastUrl = tags[0];
5385
+ } else if (this.apiVastTagUrl) {
5386
+ baseVastUrl = this.apiVastTagUrl;
4960
5387
  } else {
4961
5388
  this.clearPendingAdBreak();
4962
5389
  return [
@@ -5001,6 +5428,10 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5001
5428
  firstAdUrl = preloaded.vastUrl;
5002
5429
  preloadedController = preloaded.imaController;
5003
5430
  usePreloadedAd = true;
5431
+ sendAdLoadedTracking(this.config.licenseKey, {
5432
+ source: "preload",
5433
+ vastUrl: firstAdUrl
5434
+ }, this.config.adPlayerType).catch(function() {});
5004
5435
  if (this.config.debugAdTiming) {
5005
5436
  console.log("[CONTINUOUS-FETCH] \uD83D\uDE80 Using preloaded ad from pool (preloaded in advance, ready immediately!)");
5006
5437
  console.log("[CONTINUOUS-FETCH] Pool still has ".concat(this.preloadPool.length, " preloaded ads ready"));
@@ -5090,6 +5521,10 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5090
5521
  ];
5091
5522
  case 5:
5092
5523
  _state.sent();
5524
+ sendAdLoadedTracking(this.config.licenseKey, {
5525
+ source: "ssp",
5526
+ vastUrl: firstAdUrl
5527
+ }, this.config.adPlayerType).catch(function() {});
5093
5528
  if (this.config.debugAdTiming) {
5094
5529
  console.log("[CONTINUOUS-FETCH] \u2705 First ad request successful, starting playback");
5095
5530
  }
@@ -5486,6 +5921,10 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5486
5921
  if (this.config.debugAdTiming) {
5487
5922
  console.log("[CONTINUOUS-FETCH] \uD83C\uDFAF Using preloaded ad from pool (".concat(this.preloadPool.length, " remaining in pool)"));
5488
5923
  }
5924
+ sendAdLoadedTracking(this.config.licenseKey, {
5925
+ source: "preload",
5926
+ vastUrl: preloaded.vastUrl
5927
+ }, this.config.adPlayerType).catch(function() {});
5489
5928
  _state.label = 1;
5490
5929
  case 1:
5491
5930
  _state.trys.push([
@@ -5823,15 +6262,22 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5823
6262
  {
5824
6263
  key: "findCurrentOrNextBreak",
5825
6264
  value: function findCurrentOrNextBreak(nowMs) {
5826
- var schedule = [];
6265
+ var schedule = this.vmapBreaks;
5827
6266
  var candidate;
5828
6267
  var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
5829
6268
  try {
5830
6269
  for(var _iterator = schedule[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
5831
6270
  var b = _step.value;
5832
- var _this_config_driftToleranceMs;
6271
+ var _this_config_driftToleranceMs, _this_resolveBreakStartMs;
6272
+ if (this.consumedVmapBreakIds.has(this.getAdBreakKey(b))) {
6273
+ continue;
6274
+ }
6275
+ var breakStartMs = this.resolveBreakStartMs(b);
6276
+ if (breakStartMs == null) {
6277
+ continue;
6278
+ }
5833
6279
  var tol = (_this_config_driftToleranceMs = this.config.driftToleranceMs) !== null && _this_config_driftToleranceMs !== void 0 ? _this_config_driftToleranceMs : 1e3;
5834
- if (b.startTimeMs <= nowMs + tol && (candidate == null || b.startTimeMs > (candidate.startTimeMs || 0))) {
6280
+ if (breakStartMs <= nowMs + tol && (candidate == null || breakStartMs > ((_this_resolveBreakStartMs = this.resolveBreakStartMs(candidate)) !== null && _this_resolveBreakStartMs !== void 0 ? _this_resolveBreakStartMs : 0))) {
5835
6281
  candidate = b;
5836
6282
  }
5837
6283
  }
@@ -5855,11 +6301,16 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5855
6301
  {
5856
6302
  key: "onTimeUpdate",
5857
6303
  value: function onTimeUpdate(currentTimeSec) {
5858
- if (this.ima.isAdPlaying()) return;
6304
+ var _this = this;
6305
+ if (this.ima.isAdPlaying() || this.inAdBreak) return;
5859
6306
  var nowMs = currentTimeSec * 1e3;
5860
6307
  var breakToPlay = this.findBreakForTime(nowMs);
5861
6308
  if (breakToPlay) {
5862
- this.handleMidAdJoin(breakToPlay, nowMs);
6309
+ void this.handleMidAdJoin(breakToPlay, nowMs).catch(function(error) {
6310
+ if (_this.config.debugAdTiming) {
6311
+ console.warn("[StormcloudVideoPlayer] Mid-roll VMAP join failed gracefully:", error);
6312
+ }
6313
+ });
5863
6314
  }
5864
6315
  }
5865
6316
  },
@@ -5867,40 +6318,76 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5867
6318
  key: "handleMidAdJoin",
5868
6319
  value: function handleMidAdJoin(adBreak, nowMs) {
5869
6320
  return _async_to_generator(function() {
5870
- var _adBreak_durationMs, durationMs, endMs, remainingMs, tags, first, rest;
6321
+ var _adBreak_durationMs, _this_config_driftToleranceMs, key, breakStartMs, durationMs, endMs, tol, inWindow, remainingMs, tags, first, rest, error;
5871
6322
  return _ts_generator(this, function(_state) {
5872
6323
  switch(_state.label){
5873
6324
  case 0:
6325
+ key = this.getAdBreakKey(adBreak);
6326
+ if (this.consumedVmapBreakIds.has(key)) {
6327
+ return [
6328
+ 2
6329
+ ];
6330
+ }
6331
+ breakStartMs = this.resolveBreakStartMs(adBreak);
6332
+ if (breakStartMs == null) {
6333
+ return [
6334
+ 2
6335
+ ];
6336
+ }
5874
6337
  durationMs = (_adBreak_durationMs = adBreak.durationMs) !== null && _adBreak_durationMs !== void 0 ? _adBreak_durationMs : 0;
5875
- endMs = adBreak.startTimeMs + durationMs;
5876
- if (!(durationMs > 0 && nowMs > adBreak.startTimeMs && nowMs < endMs)) return [
6338
+ endMs = breakStartMs + durationMs;
6339
+ tol = (_this_config_driftToleranceMs = this.config.driftToleranceMs) !== null && _this_config_driftToleranceMs !== void 0 ? _this_config_driftToleranceMs : 1e3;
6340
+ inWindow = durationMs > 0 ? nowMs > breakStartMs && nowMs < endMs : nowMs + tol >= breakStartMs;
6341
+ if (!inWindow) return [
5877
6342
  3,
5878
- 2
6343
+ 4
5879
6344
  ];
5880
- remainingMs = endMs - nowMs;
6345
+ this.consumedVmapBreakIds.add(key);
6346
+ remainingMs = durationMs > 0 ? Math.max(0, endMs - nowMs) : 0;
5881
6347
  tags = this.selectVastTagsForBreak(adBreak) || (this.apiVastTagUrl ? [
5882
6348
  this.apiVastTagUrl
5883
6349
  ] : void 0);
5884
6350
  if (!(tags && tags.length > 0)) return [
5885
6351
  3,
5886
- 2
6352
+ 4
5887
6353
  ];
5888
6354
  first = tags[0];
5889
6355
  rest = tags.slice(1);
5890
6356
  this.adPodQueue = rest;
5891
6357
  this.ima.updateOriginalMutedState(this.video.muted, this.video.volume);
6358
+ _state.label = 1;
6359
+ case 1:
6360
+ _state.trys.push([
6361
+ 1,
6362
+ 3,
6363
+ ,
6364
+ 4
6365
+ ]);
5892
6366
  return [
5893
6367
  4,
5894
6368
  this.playSingleAd(first)
5895
6369
  ];
5896
- case 1:
6370
+ case 2:
5897
6371
  _state.sent();
5898
6372
  this.inAdBreak = true;
5899
6373
  this.expectedAdBreakDurationMs = remainingMs;
5900
6374
  this.currentAdBreakStartWallClockMs = Date.now();
5901
6375
  this.scheduleAdStopCountdown(remainingMs);
5902
- _state.label = 2;
5903
- case 2:
6376
+ return [
6377
+ 3,
6378
+ 4
6379
+ ];
6380
+ case 3:
6381
+ error = _state.sent();
6382
+ this.adPodQueue = [];
6383
+ if (this.config.debugAdTiming) {
6384
+ console.warn("[StormcloudVideoPlayer] Mid-roll VMAP ad request failed:", error);
6385
+ }
6386
+ return [
6387
+ 3,
6388
+ 4
6389
+ ];
6390
+ case 4:
5904
6391
  return [
5905
6392
  2
5906
6393
  ];
@@ -6190,6 +6677,10 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6190
6677
  ];
6191
6678
  case 3:
6192
6679
  _state.sent();
6680
+ sendAdLoadedTracking(this.config.licenseKey, {
6681
+ source: "ssp",
6682
+ vastUrl: vastTagUrl
6683
+ }, this.config.adPlayerType).catch(function() {});
6193
6684
  this.clearAdRequestWatchdog();
6194
6685
  if (this.activeAdRequestToken !== requestToken) {
6195
6686
  return [
@@ -6404,6 +6895,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6404
6895
  }
6405
6896
  this.adRequestQueue = [];
6406
6897
  this.inAdBreak = false;
6898
+ this.adDetectSentForCurrentBreak = false;
6407
6899
  this.expectedAdBreakDurationMs = void 0;
6408
6900
  this.currentAdBreakStartWallClockMs = void 0;
6409
6901
  this.clearAdStartTimer();
@@ -6601,13 +7093,22 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6601
7093
  {
6602
7094
  key: "findBreakForTime",
6603
7095
  value: function findBreakForTime(nowMs) {
6604
- var schedule = [];
7096
+ var _this_config_driftToleranceMs;
7097
+ var schedule = this.vmapBreaks;
7098
+ var tol = (_this_config_driftToleranceMs = this.config.driftToleranceMs) !== null && _this_config_driftToleranceMs !== void 0 ? _this_config_driftToleranceMs : 1e3;
6605
7099
  var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
6606
7100
  try {
6607
7101
  for(var _iterator = schedule[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
6608
7102
  var b = _step.value;
6609
- var end = (b.startTimeMs || 0) + (b.durationMs || 0);
6610
- if (nowMs >= (b.startTimeMs || 0) && (b.durationMs ? nowMs < end : true)) {
7103
+ if (this.consumedVmapBreakIds.has(this.getAdBreakKey(b))) {
7104
+ continue;
7105
+ }
7106
+ var breakStartMs = this.resolveBreakStartMs(b);
7107
+ if (breakStartMs == null) {
7108
+ continue;
7109
+ }
7110
+ var end = breakStartMs + (b.durationMs || 0);
7111
+ if (nowMs >= breakStartMs && (b.durationMs ? nowMs < end : nowMs <= breakStartMs + tol)) {
6611
7112
  return b;
6612
7113
  }
6613
7114
  }
@@ -6839,12 +7340,14 @@ var CRITICAL_PROPS = [
6839
7340
  "src",
6840
7341
  "allowNativeHls",
6841
7342
  "licenseKey",
7343
+ "vmapUrl",
6842
7344
  "lowLatencyMode",
6843
7345
  "driftToleranceMs",
6844
7346
  "vastMode"
6845
7347
  ];
7348
+ var CONTROLS_HIDE_DELAY = 3e3;
6846
7349
  var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
6847
- 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, [
7350
+ 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, [
6848
7351
  "src",
6849
7352
  "autoplay",
6850
7353
  "muted",
@@ -6871,12 +7374,15 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
6871
7374
  "licenseKey",
6872
7375
  "vastMode",
6873
7376
  "vastTagUrl",
7377
+ "vmapUrl",
6874
7378
  "adPlayerType",
6875
7379
  "minSegmentsBeforePlay"
6876
7380
  ]);
6877
7381
  var videoRef = (0, import_react.useRef)(null);
6878
7382
  var playerRef = (0, import_react.useRef)(null);
6879
7383
  var bufferingTimeoutRef = (0, import_react.useRef)(null);
7384
+ var controlsTimerRef = (0, import_react.useRef)(null);
7385
+ var wrapperRef = (0, import_react.useRef)(null);
6880
7386
  var _import_react_default_useState = _sliced_to_array(import_react.default.useState({
6881
7387
  showAds: false,
6882
7388
  currentIndex: 0,
@@ -6896,8 +7402,9 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
6896
7402
  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];
6897
7403
  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];
6898
7404
  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];
6899
- 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];
6900
- 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];
7405
+ 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];
7406
+ 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];
7407
+ 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];
6901
7408
  var getResponsiveScale = function getResponsiveScale() {
6902
7409
  if (viewportWidth < 480) return 0.7;
6903
7410
  if (viewportWidth < 768) return 0.8;
@@ -6905,6 +7412,33 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
6905
7412
  return 1;
6906
7413
  };
6907
7414
  var responsiveScale = getResponsiveScale();
7415
+ var resetControlsTimer = (0, import_react.useCallback)(function() {
7416
+ if (controlsTimerRef.current) {
7417
+ clearTimeout(controlsTimerRef.current);
7418
+ }
7419
+ setControlsVisible(true);
7420
+ controlsTimerRef.current = window.setTimeout(function() {
7421
+ if (!showVolumeSlider && !showSpeedMenu) {
7422
+ setControlsVisible(false);
7423
+ }
7424
+ }, CONTROLS_HIDE_DELAY);
7425
+ }, [
7426
+ showVolumeSlider,
7427
+ showSpeedMenu
7428
+ ]);
7429
+ var handleWrapperMouseMove = (0, import_react.useCallback)(function() {
7430
+ resetControlsTimer();
7431
+ }, [
7432
+ resetControlsTimer
7433
+ ]);
7434
+ var handleWrapperMouseLeave = (0, import_react.useCallback)(function() {
7435
+ if (!showVolumeSlider && !showSpeedMenu) {
7436
+ setControlsVisible(false);
7437
+ }
7438
+ }, [
7439
+ showVolumeSlider,
7440
+ showSpeedMenu
7441
+ ]);
6908
7442
  var formatTime = function formatTime(seconds) {
6909
7443
  if (!isFinite(seconds)) return "0:00:00";
6910
7444
  var hours = Math.floor(seconds / 3600);
@@ -6930,6 +7464,7 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
6930
7464
  setShowCenterPlay(true);
6931
7465
  }
6932
7466
  }
7467
+ resetControlsTimer();
6933
7468
  };
6934
7469
  var handleCenterPlayClick = function handleCenterPlayClick() {
6935
7470
  if (videoRef.current && videoRef.current.paused) {
@@ -6955,6 +7490,7 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
6955
7490
  videoRef.current.currentTime = newTime;
6956
7491
  }
6957
7492
  }
7493
+ resetControlsTimer();
6958
7494
  };
6959
7495
  var handleVolumeChange = function handleVolumeChange(newVolume) {
6960
7496
  if (playerRef.current && isFinite(newVolume)) {
@@ -6978,6 +7514,7 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
6978
7514
  src,
6979
7515
  allowNativeHls,
6980
7516
  licenseKey,
7517
+ vmapUrl,
6981
7518
  lowLatencyMode,
6982
7519
  driftToleranceMs,
6983
7520
  vastMode
@@ -7020,6 +7557,7 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
7020
7557
  if (licenseKey !== void 0) cfg.licenseKey = licenseKey;
7021
7558
  if (vastMode !== void 0) cfg.vastMode = vastMode;
7022
7559
  if (vastTagUrl !== void 0) cfg.vastTagUrl = vastTagUrl;
7560
+ if (vmapUrl !== void 0) cfg.vmapUrl = vmapUrl;
7023
7561
  if (adPlayerType !== void 0) cfg.adPlayerType = adPlayerType;
7024
7562
  if (minSegmentsBeforePlay !== void 0) cfg.minSegmentsBeforePlay = minSegmentsBeforePlay;
7025
7563
  var player = new StormcloudVideoPlayer(cfg);
@@ -7110,7 +7648,6 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
7110
7648
  (0, import_react.useEffect)(function() {
7111
7649
  if (!playerRef.current || !videoRef.current) return;
7112
7650
  var updateStates = function updateStates() {
7113
- var _videoRef_current;
7114
7651
  if (playerRef.current && videoRef.current) {
7115
7652
  setIsMuted(playerRef.current.isMuted());
7116
7653
  setIsPlaying(!videoRef.current.paused);
@@ -7123,12 +7660,11 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
7123
7660
  var rateValue = videoRef.current.playbackRate;
7124
7661
  setPlaybackRate(isFinite(rateValue) && rateValue > 0 ? rateValue : 1);
7125
7662
  }
7126
- setIsFullscreen(document.fullscreenElement === ((_videoRef_current = videoRef.current) === null || _videoRef_current === void 0 ? void 0 : _videoRef_current.parentElement));
7663
+ setIsFullscreen(document.fullscreenElement === wrapperRef.current);
7127
7664
  };
7128
7665
  var interval = setInterval(updateStates, 200);
7129
7666
  var handleFullscreenChange = function handleFullscreenChange() {
7130
- var _videoRef_current;
7131
- setIsFullscreen(document.fullscreenElement === ((_videoRef_current = videoRef.current) === null || _videoRef_current === void 0 ? void 0 : _videoRef_current.parentElement));
7667
+ setIsFullscreen(document.fullscreenElement === wrapperRef.current);
7132
7668
  };
7133
7669
  document.addEventListener("fullscreenchange", handleFullscreenChange);
7134
7670
  return function() {
@@ -7256,13 +7792,25 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
7256
7792
  }, [
7257
7793
  debugAdTiming
7258
7794
  ]);
7795
+ (0, import_react.useEffect)(function() {
7796
+ return function() {
7797
+ if (controlsTimerRef.current) {
7798
+ clearTimeout(controlsTimerRef.current);
7799
+ }
7800
+ };
7801
+ }, []);
7802
+ var progressPercent = duration > 0 ? currentTime / duration * 100 : 0;
7803
+ var VolumeIcon = isMuted || volume === 0 ? import_fa.FaVolumeMute : volume < 0.5 ? import_fa.FaVolumeDown : import_fa.FaVolumeUp;
7259
7804
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, {
7260
7805
  children: [
7261
7806
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", {
7262
- 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 "
7807
+ 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 "
7263
7808
  }),
7264
7809
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
7265
- className: "stormcloud-video-wrapper ".concat(wrapperClassName || ""),
7810
+ ref: wrapperRef,
7811
+ className: "sc-wrapper ".concat(wrapperClassName || ""),
7812
+ onMouseMove: handleWrapperMouseMove,
7813
+ onMouseLeave: handleWrapperMouseLeave,
7266
7814
  style: _object_spread({
7267
7815
  display: "flex",
7268
7816
  alignItems: "center",
@@ -7277,7 +7825,7 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
7277
7825
  maxWidth: isFullscreen ? "100vw" : "100%",
7278
7826
  maxHeight: isFullscreen ? "100vh" : "none",
7279
7827
  zIndex: isFullscreen ? 999999 : void 0,
7280
- backgroundColor: isFullscreen ? "#000" : void 0,
7828
+ backgroundColor: "#000",
7281
7829
  borderRadius: isFullscreen ? 0 : void 0,
7282
7830
  boxShadow: isFullscreen ? "none" : void 0
7283
7831
  }, wrapperStyle),
@@ -7303,16 +7851,16 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
7303
7851
  children: children
7304
7852
  })),
7305
7853
  (isLoading || isBuffering) && !hideLoadingIndicator && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_fa.FaSpinner, {
7306
- className: "stormcloud-loading-indicator",
7307
- size: 42,
7308
- color: "white",
7854
+ className: "sc-loading-indicator",
7855
+ size: 40,
7856
+ color: "rgba(255, 255, 255, 0.85)",
7309
7857
  style: {
7310
7858
  position: "absolute",
7311
- top: "calc(50% - 21px)",
7312
- left: "calc(50% - 21px)",
7859
+ top: "calc(50% - 20px)",
7860
+ left: "calc(50% - 20px)",
7313
7861
  zIndex: 20,
7314
- animation: "spin 1s linear infinite",
7315
- filter: "drop-shadow(0 3px 6px rgba(0, 0, 0, 0.8))"
7862
+ animation: "sc-spin 0.9s linear infinite",
7863
+ filter: "drop-shadow(0 2px 8px rgba(0, 0, 0, 0.6))"
7316
7864
  }
7317
7865
  }),
7318
7866
  showLicenseWarning && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
@@ -7322,13 +7870,13 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
7322
7870
  left: "50%",
7323
7871
  transform: "translate(-50%, -50%)",
7324
7872
  zIndex: 25,
7325
- background: "linear-gradient(135deg, rgba(220, 38, 38, 0.95) 0%, rgba(185, 28, 28, 0.9) 100%)",
7873
+ background: "rgba(220, 38, 38, 0.92)",
7874
+ backdropFilter: "blur(24px)",
7326
7875
  color: "white",
7327
- padding: "24px 32px",
7328
- borderRadius: "16px",
7329
- backdropFilter: "blur(20px)",
7330
- border: "2px solid rgba(255, 255, 255, 0.2)",
7331
- boxShadow: "0 20px 60px rgba(0, 0, 0, 0.6), inset 0 2px 0 rgba(255, 255, 255, 0.2)",
7876
+ padding: "28px 36px",
7877
+ borderRadius: "14px",
7878
+ border: "1px solid rgba(255, 255, 255, 0.15)",
7879
+ boxShadow: "0 24px 64px rgba(0, 0, 0, 0.5)",
7332
7880
  textAlign: "center",
7333
7881
  maxWidth: "400px",
7334
7882
  margin: "0 16px"
@@ -7336,20 +7884,18 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
7336
7884
  children: [
7337
7885
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
7338
7886
  style: {
7339
- fontSize: "20px",
7340
- fontWeight: "bold",
7341
- marginBottom: "12px",
7342
- color: "#ffffff",
7343
- textShadow: "0 2px 4px rgba(0, 0, 0, 0.5)"
7887
+ fontSize: "18px",
7888
+ fontWeight: "700",
7889
+ marginBottom: "10px",
7890
+ letterSpacing: "-0.02em"
7344
7891
  },
7345
7892
  children: "License Key Required"
7346
7893
  }),
7347
7894
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
7348
7895
  style: {
7349
- fontSize: "14px",
7350
- lineHeight: "1.5",
7351
- color: "rgba(255, 255, 255, 0.9)",
7352
- textShadow: "0 1px 2px rgba(0, 0, 0, 0.3)"
7896
+ fontSize: "13px",
7897
+ lineHeight: "1.6",
7898
+ color: "rgba(255, 255, 255, 0.85)"
7353
7899
  },
7354
7900
  children: [
7355
7901
  "Please provide a valid license key to use the Stormcloud Video Player.",
@@ -7368,573 +7914,419 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
7368
7914
  transform: "translate(-50%, -50%)",
7369
7915
  zIndex: 15,
7370
7916
  cursor: "pointer",
7371
- background: "linear-gradient(135deg, rgba(0, 0, 0, 0.9) 0%, rgba(20, 20, 20, 0.8) 100%)",
7917
+ background: "rgba(0, 0, 0, 0.55)",
7918
+ backdropFilter: "blur(8px)",
7372
7919
  borderRadius: "50%",
7373
- width: "100px",
7374
- height: "100px",
7920
+ width: "".concat(92 * responsiveScale, "px"),
7921
+ height: "".concat(92 * responsiveScale, "px"),
7375
7922
  display: "flex",
7376
7923
  alignItems: "center",
7377
7924
  justifyContent: "center",
7378
- backdropFilter: "blur(20px)",
7379
- border: "3px solid rgba(255, 255, 255, 0.8)",
7380
- boxShadow: "0 12px 40px rgba(0, 0, 0, 0.8), inset 0 2px 0 rgba(255, 255, 255, 0.3)",
7381
- transition: "all 0.3s cubic-bezier(0.4, 0, 0.2, 1)"
7925
+ transition: "background 0.2s ease, transform 0.2s ease",
7926
+ animation: "sc-fade-in 0.2s ease"
7382
7927
  },
7383
7928
  onMouseEnter: function onMouseEnter(e) {
7384
- var target = e.currentTarget;
7385
- target.style.transform = "translate(-50%, -50%)";
7386
- target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.95) 0%, rgba(40, 40, 40, 0.9) 100%)";
7387
- target.style.boxShadow = "0 16px 48px rgba(0, 0, 0, 0.9), inset 0 2px 0 rgba(255, 255, 255, 0.4)";
7388
- target.style.borderColor = "rgba(255, 255, 255, 0.9)";
7929
+ e.currentTarget.style.background = "rgba(0, 0, 0, 0.72)";
7930
+ e.currentTarget.style.transform = "translate(-50%, -50%) scale(1.06)";
7389
7931
  },
7390
7932
  onMouseLeave: function onMouseLeave(e) {
7391
- var target = e.currentTarget;
7392
- target.style.transform = "translate(-50%, -50%)";
7393
- target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.9) 0%, rgba(20, 20, 20, 0.8) 100%)";
7394
- target.style.boxShadow = "0 12px 40px rgba(0, 0, 0, 0.8), inset 0 2px 0 rgba(255, 255, 255, 0.3)";
7395
- target.style.borderColor = "rgba(255, 255, 255, 0.8)";
7933
+ e.currentTarget.style.background = "rgba(0, 0, 0, 0.55)";
7934
+ e.currentTarget.style.transform = "translate(-50%, -50%) scale(1)";
7396
7935
  },
7397
7936
  title: "Play",
7398
7937
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_fa.FaPlay, {
7399
- size: 36,
7938
+ size: Math.max(24, 32 * responsiveScale),
7400
7939
  color: "white",
7401
7940
  style: {
7402
- marginLeft: "6px",
7403
- filter: "drop-shadow(0 2px 4px rgba(0, 0, 0, 0.8))"
7941
+ marginLeft: "4px"
7404
7942
  }
7405
7943
  })
7406
7944
  }),
7407
- shouldShowEnhancedControls && !showLicenseWarning ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, {
7408
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
7409
- style: {
7410
- position: "absolute",
7411
- bottom: 0,
7412
- left: 0,
7413
- right: 0,
7414
- background: "linear-gradient(180deg, transparent 0%, rgba(0, 0, 0, 0.8) 100%)",
7415
- padding: "20px 16px 16px",
7416
- zIndex: 10
7417
- },
7418
- children: [
7419
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
7420
- style: {
7421
- width: "100%",
7422
- height: "8px",
7423
- background: "linear-gradient(90deg, rgba(255, 255, 255, 0.2) 0%, rgba(255, 255, 255, 0.1) 100%)",
7424
- borderRadius: "8px",
7425
- marginBottom: "16px",
7426
- cursor: "pointer",
7427
- position: "relative",
7428
- backdropFilter: "blur(5px)",
7429
- border: "1px solid rgba(255, 255, 255, 0.1)",
7430
- boxShadow: "inset 0 2px 4px rgba(0, 0, 0, 0.2)"
7431
- },
7432
- onClick: handleTimelineSeek,
7433
- children: [
7434
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
7435
- style: {
7436
- height: "100%",
7437
- 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%)",
7438
- borderRadius: "8px",
7439
- width: "".concat(duration > 0 ? currentTime / duration * 100 : 0, "%"),
7440
- transition: "width 0.2s cubic-bezier(0.4, 0, 0.2, 1)",
7441
- boxShadow: "0 2px 8px rgba(139, 92, 246, 0.4)"
7442
- }
7443
- }),
7444
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
7445
- style: {
7446
- position: "absolute",
7447
- top: "-6px",
7448
- right: "".concat(duration > 0 ? 100 - currentTime / duration * 100 : 100, "%"),
7449
- width: "20px",
7450
- height: "20px",
7451
- background: "linear-gradient(135deg, rgba(255, 255, 255, 0.95) 0%, rgba(240, 240, 240, 0.9) 100%)",
7452
- borderRadius: "50%",
7453
- border: "3px solid rgba(139, 92, 246, 0.8)",
7454
- boxShadow: "0 4px 16px rgba(139, 92, 246, 0.4), inset 0 1px 0 rgba(255, 255, 255, 0.8)",
7455
- transform: "translateX(50%)",
7456
- transition: "all 0.2s cubic-bezier(0.4, 0, 0.2, 1)"
7457
- }
7458
- })
7459
- ]
7460
- }),
7461
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
7462
- style: {
7463
- display: "flex",
7464
- alignItems: "center",
7465
- justifyContent: "space-between",
7466
- color: "white",
7467
- flexWrap: viewportWidth < 768 ? "wrap" : "nowrap",
7468
- gap: "".concat(8 * responsiveScale, "px")
7469
- },
7470
- children: [
7471
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
7472
- style: {
7473
- display: "flex",
7474
- alignItems: "center",
7475
- gap: "".concat(12 * responsiveScale, "px"),
7476
- flexWrap: viewportWidth < 480 ? "wrap" : "nowrap"
7477
- },
7478
- children: [
7479
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", {
7480
- onClick: handlePlayPause,
7945
+ shouldShowEnhancedControls && !showLicenseWarning ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
7946
+ className: "sc-controls-bar",
7947
+ style: {
7948
+ position: "absolute",
7949
+ bottom: 0,
7950
+ left: 0,
7951
+ right: 0,
7952
+ background: "linear-gradient(0deg, rgba(0, 0, 0, 0.8) 0%, rgba(0, 0, 0, 0.35) 60%, transparent 100%)",
7953
+ padding: "".concat(20 * responsiveScale, "px ").concat(12 * responsiveScale, "px ").concat(8 * responsiveScale, "px"),
7954
+ zIndex: 10,
7955
+ opacity: controlsVisible || adStatus.showAds ? 1 : 0,
7956
+ transform: controlsVisible || adStatus.showAds ? "translateY(0)" : "translateY(6px)",
7957
+ pointerEvents: controlsVisible || adStatus.showAds ? "auto" : "none"
7958
+ },
7959
+ children: [
7960
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
7961
+ className: "sc-progress-track",
7962
+ style: {
7963
+ width: "100%",
7964
+ height: "3px",
7965
+ background: "rgba(255, 255, 255, 0.2)",
7966
+ borderRadius: "1.5px",
7967
+ marginBottom: "".concat(8 * responsiveScale, "px"),
7968
+ cursor: "pointer",
7969
+ position: "relative",
7970
+ transition: "height 0.1s ease"
7971
+ },
7972
+ onClick: handleTimelineSeek,
7973
+ onMouseEnter: function onMouseEnter(e) {
7974
+ e.currentTarget.style.height = "5px";
7975
+ },
7976
+ onMouseLeave: function onMouseLeave(e) {
7977
+ e.currentTarget.style.height = "3px";
7978
+ },
7979
+ children: [
7980
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
7981
+ style: {
7982
+ position: "absolute",
7983
+ top: 0,
7984
+ left: 0,
7985
+ bottom: 0,
7986
+ background: adStatus.showAds ? "#f5c518" : "#ff0000",
7987
+ borderRadius: "1.5px",
7988
+ width: "".concat(progressPercent, "%"),
7989
+ transition: "width 0.15s linear"
7990
+ }
7991
+ }),
7992
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
7993
+ className: "sc-progress-thumb",
7994
+ style: {
7995
+ position: "absolute",
7996
+ top: "50%",
7997
+ left: "".concat(progressPercent, "%"),
7998
+ transform: "translate(-50%, -50%) scale(0)",
7999
+ width: "13px",
8000
+ height: "13px",
8001
+ background: adStatus.showAds ? "#f5c518" : "#ff0000",
8002
+ borderRadius: "50%",
8003
+ boxShadow: "0 0 4px rgba(0, 0, 0, 0.3)",
8004
+ transition: "transform 0.1s ease, left 0.15s linear"
8005
+ }
8006
+ })
8007
+ ]
8008
+ }),
8009
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
8010
+ style: {
8011
+ display: "flex",
8012
+ alignItems: "center",
8013
+ justifyContent: "space-between",
8014
+ color: "white",
8015
+ gap: "".concat(8 * responsiveScale, "px")
8016
+ },
8017
+ children: [
8018
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
8019
+ style: {
8020
+ display: "flex",
8021
+ alignItems: "center",
8022
+ gap: "".concat(8 * responsiveScale, "px")
8023
+ },
8024
+ children: [
8025
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", {
8026
+ className: "sc-ctrl-btn",
8027
+ onClick: handlePlayPause,
8028
+ style: {
8029
+ padding: "".concat(8 * responsiveScale, "px"),
8030
+ borderRadius: "50%",
8031
+ minWidth: "".concat(36 * responsiveScale, "px"),
8032
+ minHeight: "".concat(36 * responsiveScale, "px")
8033
+ },
8034
+ title: isPlaying ? "Pause" : "Play",
8035
+ children: isPlaying ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_fa.FaPause, {
8036
+ size: Math.max(14, 18 * responsiveScale)
8037
+ }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_fa.FaPlay, {
8038
+ size: Math.max(14, 18 * responsiveScale),
7481
8039
  style: {
7482
- background: "linear-gradient(135deg, rgba(0, 0, 0, 0.75) 0%, rgba(0, 0, 0, 0.65) 100%)",
7483
- backdropFilter: "blur(12px)",
7484
- border: "".concat(2 * responsiveScale, "px solid rgba(255, 255, 255, 0.3)"),
7485
- color: "#ffffff",
7486
- cursor: "pointer",
7487
- padding: "".concat(10 * responsiveScale, "px"),
7488
- borderRadius: "".concat(16 * responsiveScale, "px"),
7489
- display: "flex",
7490
- alignItems: "center",
7491
- justifyContent: "center",
7492
- transition: "all 0.3s cubic-bezier(0.4, 0, 0.2, 1)",
7493
- 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)",
7494
- minWidth: "".concat(48 * responsiveScale, "px"),
7495
- minHeight: "".concat(48 * responsiveScale, "px")
7496
- },
7497
- onMouseEnter: function onMouseEnter(e) {
7498
- var target = e.target;
7499
- target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.85) 0%, rgba(0, 0, 0, 0.75) 100%)";
7500
- 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)";
7501
- },
7502
- onMouseLeave: function onMouseLeave(e) {
7503
- var target = e.target;
7504
- target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.75) 0%, rgba(0, 0, 0, 0.65) 100%)";
7505
- 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)";
7506
- },
7507
- title: isPlaying ? "Pause" : "Play",
7508
- children: isPlaying ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_fa.FaPause, {
7509
- size: Math.max(16, 20 * responsiveScale),
8040
+ marginLeft: "2px"
8041
+ }
8042
+ })
8043
+ }),
8044
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
8045
+ style: {
8046
+ display: "flex",
8047
+ alignItems: "center"
8048
+ },
8049
+ onMouseEnter: function onMouseEnter() {
8050
+ return setShowVolumeSlider(true);
8051
+ },
8052
+ onMouseLeave: function onMouseLeave() {
8053
+ return setShowVolumeSlider(false);
8054
+ },
8055
+ children: [
8056
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", {
8057
+ className: "sc-ctrl-btn",
8058
+ onClick: function onClick() {
8059
+ if (playerRef.current) playerRef.current.toggleMute();
8060
+ onVolumeToggle === null || onVolumeToggle === void 0 ? void 0 : onVolumeToggle();
8061
+ resetControlsTimer();
8062
+ },
7510
8063
  style: {
7511
- filter: "drop-shadow(0 0 0 transparent)"
7512
- }
7513
- }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_fa.FaPlay, {
7514
- size: Math.max(16, 20 * responsiveScale),
8064
+ padding: "".concat(8 * responsiveScale, "px"),
8065
+ borderRadius: "50%",
8066
+ minWidth: "".concat(36 * responsiveScale, "px"),
8067
+ minHeight: "".concat(36 * responsiveScale, "px")
8068
+ },
8069
+ title: isMuted ? "Unmute" : "Mute",
8070
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(VolumeIcon, {
8071
+ size: Math.max(14, 18 * responsiveScale)
8072
+ })
8073
+ }),
8074
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
7515
8075
  style: {
7516
- filter: "drop-shadow(0 0 0 transparent)"
7517
- }
7518
- })
7519
- }),
7520
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
7521
- style: {
7522
- position: "relative",
7523
- display: "flex",
7524
- alignItems: "center",
7525
- padding: "8px",
7526
- margin: "-8px"
7527
- },
7528
- onMouseEnter: function onMouseEnter() {
7529
- return setShowVolumeSlider(true);
7530
- },
7531
- onMouseLeave: function onMouseLeave() {
7532
- return setShowVolumeSlider(false);
7533
- },
7534
- children: [
7535
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", {
7536
- onClick: function onClick() {
7537
- if (playerRef.current) {
7538
- playerRef.current.toggleMute();
7539
- }
7540
- if (onVolumeToggle) {
7541
- onVolumeToggle();
7542
- }
7543
- },
8076
+ width: showVolumeSlider ? "".concat(62 * responsiveScale, "px") : "0px",
8077
+ overflow: "hidden",
8078
+ transition: "width 0.2s cubic-bezier(0.4, 0, 0.2, 1)",
8079
+ display: "flex",
8080
+ alignItems: "center",
8081
+ paddingLeft: showVolumeSlider ? "2px" : "0",
8082
+ paddingRight: showVolumeSlider ? "4px" : "0"
8083
+ },
8084
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
7544
8085
  style: {
7545
- background: "linear-gradient(135deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.6) 100%)",
7546
- backdropFilter: "blur(10px)",
7547
- border: "".concat(2 * responsiveScale, "px solid rgba(255, 255, 255, 0.3)"),
7548
- color: "#ffffff",
8086
+ position: "relative",
8087
+ width: "".concat(56 * responsiveScale, "px"),
8088
+ height: "3px",
7549
8089
  cursor: "pointer",
7550
- padding: "".concat(8 * responsiveScale, "px"),
7551
- borderRadius: "".concat(16 * responsiveScale, "px"),
7552
- display: "flex",
7553
- alignItems: "center",
7554
- justifyContent: "center",
7555
- transition: "all 0.3s cubic-bezier(0.4, 0, 0.2, 1)",
7556
- 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)",
7557
- minWidth: "".concat(44 * responsiveScale, "px"),
7558
- minHeight: "".concat(44 * responsiveScale, "px")
8090
+ borderRadius: "1.5px"
7559
8091
  },
7560
- onMouseEnter: function onMouseEnter(e) {
7561
- var target = e.target;
7562
- target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.8) 0%, rgba(0, 0, 0, 0.7) 100%)";
7563
- 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)";
8092
+ onMouseDown: function onMouseDown(e) {
8093
+ e.preventDefault();
8094
+ var el = e.currentTarget;
8095
+ var move = function move(ev) {
8096
+ var r2 = el.getBoundingClientRect();
8097
+ handleVolumeChange(Math.max(0, Math.min(1, (ev.clientX - r2.left) / r2.width)));
8098
+ };
8099
+ var up = function up1() {
8100
+ document.removeEventListener("mousemove", move);
8101
+ document.removeEventListener("mouseup", up);
8102
+ };
8103
+ document.addEventListener("mousemove", move);
8104
+ document.addEventListener("mouseup", up);
8105
+ var r = el.getBoundingClientRect();
8106
+ handleVolumeChange(Math.max(0, Math.min(1, (e.clientX - r.left) / r.width)));
7564
8107
  },
7565
- onMouseLeave: function onMouseLeave(e) {
7566
- var target = e.target;
7567
- target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.6) 100%)";
7568
- 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)";
8108
+ onClick: function onClick(e) {
8109
+ e.stopPropagation();
8110
+ var r = e.currentTarget.getBoundingClientRect();
8111
+ handleVolumeChange(Math.max(0, Math.min(1, (e.clientX - r.left) / r.width)));
7569
8112
  },
7570
- title: isMuted ? "Unmute" : "Mute",
7571
- children: isMuted || volume === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_fa.FaVolumeMute, {
7572
- size: Math.max(14, 16 * responsiveScale),
7573
- style: {
7574
- filter: "drop-shadow(0 0 0 transparent)"
7575
- }
7576
- }) : volume < 0.5 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_fa.FaVolumeDown, {
7577
- size: Math.max(14, 16 * responsiveScale),
7578
- style: {
7579
- filter: "drop-shadow(0 0 0 transparent)"
7580
- }
7581
- }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_fa.FaVolumeUp, {
7582
- size: Math.max(14, 16 * responsiveScale),
7583
- style: {
7584
- filter: "drop-shadow(0 0 0 transparent)"
7585
- }
7586
- })
7587
- }),
7588
- showVolumeSlider && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, {
7589
8113
  children: [
7590
8114
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
7591
8115
  style: {
7592
8116
  position: "absolute",
7593
- bottom: "100%",
7594
- left: "50%",
7595
- transform: "translateX(-50%)",
7596
- width: "60px",
7597
- height: "20px",
7598
- marginBottom: "-16px",
7599
- zIndex: 9
7600
- },
7601
- onMouseEnter: function onMouseEnter() {
7602
- return setShowVolumeSlider(true);
7603
- },
7604
- onMouseLeave: function onMouseLeave() {
7605
- return setShowVolumeSlider(false);
8117
+ inset: 0,
8118
+ background: "rgba(255, 255, 255, 0.2)",
8119
+ borderRadius: "1.5px"
7606
8120
  }
7607
8121
  }),
7608
8122
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
7609
8123
  style: {
7610
8124
  position: "absolute",
7611
- bottom: "100%",
7612
- left: "50%",
7613
- transform: "translateX(-50%)",
7614
- marginBottom: "4px",
7615
- background: "linear-gradient(135deg, rgba(0, 0, 0, 0.88) 0%, rgba(20, 20, 20, 0.92) 100%)",
7616
- backdropFilter: "blur(15px)",
7617
- padding: "10px 14px",
7618
- borderRadius: "14px",
7619
- border: "1px solid rgba(255, 255, 255, 0.15)",
7620
- display: "flex",
7621
- flexDirection: "column",
7622
- alignItems: "center",
7623
- justifyContent: "center",
7624
- height: "128px",
7625
- 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)",
7626
- zIndex: 10,
7627
- transition: "transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out, border-color 0.2s ease-in-out"
7628
- },
7629
- onMouseEnter: function onMouseEnter(e) {
7630
- setShowVolumeSlider(true);
7631
- 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)";
7632
- e.currentTarget.style.borderColor = "rgba(59, 130, 246, 0.4)";
7633
- },
7634
- onMouseLeave: function onMouseLeave(e) {
7635
- setShowVolumeSlider(false);
7636
- 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)";
7637
- e.currentTarget.style.borderColor = "rgba(255, 255, 255, 0.15)";
7638
- },
7639
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
7640
- style: {
7641
- position: "relative",
7642
- width: "8px",
7643
- height: "104px",
7644
- cursor: "pointer",
7645
- transition: "transform 0.2s ease-in-out"
7646
- },
7647
- onMouseEnter: function onMouseEnter(e) {},
7648
- onMouseLeave: function onMouseLeave(e) {},
7649
- onMouseDown: function onMouseDown(e) {
7650
- e.preventDefault();
7651
- var sliderElement = e.currentTarget;
7652
- var handleMouseMove = function handleMouseMove(moveEvent) {
7653
- if (!sliderElement) return;
7654
- var rect2 = sliderElement.getBoundingClientRect();
7655
- var y2 = moveEvent.clientY - rect2.top;
7656
- var percentage2 = 1 - Math.max(0, Math.min(1, y2 / rect2.height));
7657
- handleVolumeChange(percentage2);
7658
- };
7659
- var handleMouseUp = function handleMouseUp1() {
7660
- document.removeEventListener("mousemove", handleMouseMove);
7661
- document.removeEventListener("mouseup", handleMouseUp);
7662
- };
7663
- document.addEventListener("mousemove", handleMouseMove);
7664
- document.addEventListener("mouseup", handleMouseUp);
7665
- var rect = sliderElement.getBoundingClientRect();
7666
- var y = e.clientY - rect.top;
7667
- var percentage = 1 - Math.max(0, Math.min(1, y / rect.height));
7668
- handleVolumeChange(percentage);
7669
- },
7670
- onClick: function onClick(e) {
7671
- e.stopPropagation();
7672
- var rect = e.currentTarget.getBoundingClientRect();
7673
- var y = e.clientY - rect.top;
7674
- var percentage = 1 - Math.max(0, Math.min(1, y / rect.height));
7675
- handleVolumeChange(percentage);
7676
- },
7677
- children: [
7678
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
7679
- style: {
7680
- position: "absolute",
7681
- bottom: "0",
7682
- left: "0",
7683
- width: "100%",
7684
- height: "100%",
7685
- background: "linear-gradient(180deg, rgba(255, 255, 255, 0.4) 0%, rgba(255, 255, 255, 0.15) 100%)",
7686
- borderRadius: "4px",
7687
- boxShadow: "inset 0 1px 3px rgba(0, 0, 0, 0.2)"
7688
- }
7689
- }),
7690
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
7691
- style: {
7692
- position: "absolute",
7693
- bottom: "0",
7694
- left: "0",
7695
- width: "100%",
7696
- height: "".concat((isMuted ? 0 : volume) * 100, "%"),
7697
- background: "linear-gradient(180deg, rgba(96, 165, 250, 1) 0%, rgba(59, 130, 246, 0.95) 50%, rgba(37, 99, 235, 0.9) 100%)",
7698
- borderRadius: "4px",
7699
- transition: "height 0.15s ease-out, box-shadow 0.2s ease-in-out",
7700
- boxShadow: "0 0 8px rgba(59, 130, 246, 0.5), inset 0 1px 0 rgba(255, 255, 255, 0.3)"
7701
- }
7702
- }),
7703
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
7704
- style: {
7705
- position: "absolute",
7706
- bottom: "calc(".concat((isMuted ? 0 : volume) * 100, "% - 7px)"),
7707
- left: "50%",
7708
- transform: "translateX(-50%)",
7709
- width: "14px",
7710
- height: "14px",
7711
- background: "linear-gradient(135deg, #ffffff 0%, #f0f9ff 100%)",
7712
- borderRadius: "50%",
7713
- 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)",
7714
- 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",
7715
- cursor: "grab"
7716
- },
7717
- onMouseEnter: function onMouseEnter(e) {
7718
- 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)";
7719
- e.currentTarget.style.cursor = "grab";
7720
- },
7721
- onMouseLeave: function onMouseLeave(e) {
7722
- 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)";
7723
- },
7724
- onMouseDown: function onMouseDown(e) {
7725
- e.currentTarget.style.cursor = "grabbing";
7726
- },
7727
- onMouseUp: function onMouseUp(e) {
7728
- e.currentTarget.style.cursor = "grab";
7729
- }
7730
- })
7731
- ]
7732
- })
8125
+ top: 0,
8126
+ left: 0,
8127
+ bottom: 0,
8128
+ width: "".concat((isMuted ? 0 : volume) * 100, "%"),
8129
+ background: "#fff",
8130
+ borderRadius: "1.5px",
8131
+ transition: "width 0.1s ease-out"
8132
+ }
8133
+ }),
8134
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
8135
+ style: {
8136
+ position: "absolute",
8137
+ top: "50%",
8138
+ left: "".concat((isMuted ? 0 : volume) * 100, "%"),
8139
+ transform: "translate(-50%, -50%)",
8140
+ width: "12px",
8141
+ height: "12px",
8142
+ background: "#fff",
8143
+ borderRadius: "50%",
8144
+ boxShadow: "0 0 3px rgba(0, 0, 0, 0.3)",
8145
+ transition: "left 0.1s ease-out"
8146
+ }
7733
8147
  })
7734
8148
  ]
7735
8149
  })
7736
- ]
7737
- }),
7738
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
7739
- style: {
7740
- fontSize: "".concat(14 * responsiveScale, "px"),
7741
- fontFamily: "monospace",
7742
- color: "rgba(255, 255, 255, 0.9)",
7743
- display: viewportWidth < 480 ? "none" : "block"
7744
- },
7745
- children: [
7746
- formatTime(currentTime),
7747
- " / ",
7748
- formatTime(duration)
7749
- ]
7750
- })
7751
- ]
7752
- }),
7753
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
7754
- style: {
7755
- display: "flex",
7756
- alignItems: "center",
7757
- gap: "".concat(12 * responsiveScale, "px")
7758
- },
7759
- children: [
7760
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
7761
- style: {
7762
- position: "relative",
7763
- display: viewportWidth < 600 ? "none" : "block"
7764
- },
7765
- children: [
7766
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("button", {
7767
- onClick: function onClick() {
7768
- return setShowSpeedMenu(!showSpeedMenu);
7769
- },
7770
- style: {
7771
- background: "linear-gradient(135deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.6) 100%)",
7772
- backdropFilter: "blur(10px)",
7773
- border: "".concat(2 * responsiveScale, "px solid rgba(255, 255, 255, 0.3)"),
7774
- color: "#ffffff",
7775
- cursor: "pointer",
7776
- padding: "".concat(8 * responsiveScale, "px ").concat(14 * responsiveScale, "px"),
7777
- borderRadius: "".concat(14 * responsiveScale, "px"),
7778
- fontSize: "".concat(14 * responsiveScale, "px"),
7779
- fontFamily: "monospace",
7780
- fontWeight: "700",
7781
- transition: "all 0.3s cubic-bezier(0.4, 0, 0.2, 1)",
7782
- 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)",
7783
- minWidth: "".concat(56 * responsiveScale, "px"),
7784
- minHeight: "".concat(40 * responsiveScale, "px")
7785
- },
7786
- onMouseEnter: function onMouseEnter(e) {
7787
- var target = e.target;
7788
- target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.8) 0%, rgba(0, 0, 0, 0.7) 100%)";
7789
- 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)";
7790
- },
7791
- onMouseLeave: function onMouseLeave(e) {
7792
- var target = e.target;
7793
- target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.6) 100%)";
7794
- 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)";
7795
- },
7796
- title: "Playback Speed",
7797
- children: [
7798
- playbackRate,
7799
- "x"
7800
- ]
7801
- }),
7802
- showSpeedMenu && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
7803
- style: {
7804
- position: "absolute",
7805
- bottom: "100%",
7806
- right: 0,
7807
- marginBottom: "12px",
7808
- background: "linear-gradient(135deg, rgba(0, 0, 0, 0.9) 0%, rgba(20, 20, 20, 0.95) 100%)",
7809
- backdropFilter: "blur(20px)",
7810
- borderRadius: "12px",
7811
- border: "1px solid rgba(255, 255, 255, 0.1)",
7812
- overflow: "hidden",
7813
- minWidth: "90px",
7814
- boxShadow: "0 16px 48px rgba(0, 0, 0, 0.5), inset 0 1px 0 rgba(255, 255, 255, 0.1)"
7815
- },
7816
- children: [
7817
- 0.25,
7818
- 0.5,
7819
- 0.75,
7820
- 1,
7821
- 1.25,
7822
- 1.5,
7823
- 1.75,
7824
- 2
7825
- ].map(function(speed) {
7826
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("button", {
7827
- onClick: function onClick() {
7828
- return handlePlaybackRateChange(speed);
7829
- },
7830
- style: {
7831
- display: "block",
7832
- width: "100%",
7833
- padding: "10px 16px",
7834
- background: playbackRate === speed ? "linear-gradient(135deg, rgba(99, 102, 241, 0.8) 0%, rgba(139, 92, 246, 0.6) 100%)" : "transparent",
7835
- border: "none",
7836
- color: "white",
7837
- cursor: "pointer",
7838
- fontSize: "13px",
7839
- fontFamily: "monospace",
7840
- fontWeight: "600",
7841
- textAlign: "center",
7842
- transition: "all 0.2s cubic-bezier(0.4, 0, 0.2, 1)",
7843
- borderBottom: speed !== 2 ? "1px solid rgba(255, 255, 255, 0.05)" : "none"
7844
- },
7845
- onMouseEnter: function onMouseEnter(e) {
7846
- if (playbackRate !== speed) {
7847
- e.target.style.background = "linear-gradient(135deg, rgba(255, 255, 255, 0.15) 0%, rgba(255, 255, 255, 0.05) 100%)";
7848
- }
7849
- },
7850
- onMouseLeave: function onMouseLeave(e) {
7851
- if (playbackRate !== speed) {
7852
- e.target.style.background = "transparent";
7853
- }
7854
- },
7855
- children: [
7856
- speed,
7857
- "x"
7858
- ]
7859
- }, speed);
7860
- })
7861
- })
7862
- ]
7863
- }),
7864
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", {
7865
- onClick: function onClick() {
7866
- if (onFullscreenToggle) {
7867
- onFullscreenToggle();
7868
- } else if (playerRef.current) {
7869
- playerRef.current.toggleFullscreen().catch(function(err) {
7870
- console.error("Fullscreen error:", err);
7871
- });
7872
- }
7873
- },
7874
- style: {
7875
- background: "linear-gradient(135deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.6) 100%)",
7876
- backdropFilter: "blur(10px)",
7877
- border: "".concat(2 * responsiveScale, "px solid rgba(255, 255, 255, 0.3)"),
7878
- color: "#ffffff",
7879
- cursor: "pointer",
7880
- padding: "".concat(8 * responsiveScale, "px"),
7881
- borderRadius: "".concat(16 * responsiveScale, "px"),
7882
- display: "flex",
7883
- alignItems: "center",
7884
- justifyContent: "center",
7885
- transition: "all 0.3s cubic-bezier(0.4, 0, 0.2, 1)",
7886
- 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)",
7887
- minWidth: "".concat(44 * responsiveScale, "px"),
7888
- minHeight: "".concat(44 * responsiveScale, "px")
7889
- },
7890
- onMouseEnter: function onMouseEnter(e) {
7891
- var target = e.target;
7892
- target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.8) 0%, rgba(0, 0, 0, 0.7) 100%)";
7893
- 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)";
7894
- },
7895
- onMouseLeave: function onMouseLeave(e) {
7896
- var target = e.target;
7897
- target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.6) 100%)";
7898
- 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)";
7899
- },
7900
- title: isFullscreen ? "Exit Fullscreen" : "Enter Fullscreen",
7901
- children: isFullscreen ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_fa.FaCompress, {
7902
- size: Math.max(14, 16 * responsiveScale),
8150
+ })
8151
+ ]
8152
+ }),
8153
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
8154
+ style: {
8155
+ fontSize: "".concat(13 * responsiveScale, "px"),
8156
+ fontFamily: "Roboto, 'Segoe UI', Arial, sans-serif",
8157
+ color: "rgba(255, 255, 255, 0.9)",
8158
+ display: viewportWidth < 480 ? "none" : "block",
8159
+ fontVariantNumeric: "tabular-nums",
8160
+ userSelect: "none",
8161
+ marginLeft: "".concat(4 * responsiveScale, "px")
8162
+ },
8163
+ children: [
8164
+ formatTime(currentTime),
8165
+ " ",
8166
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
7903
8167
  style: {
7904
- filter: "drop-shadow(0 0 0 transparent)"
7905
- }
7906
- }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_fa.FaExpand, {
7907
- size: Math.max(14, 16 * responsiveScale),
8168
+ color: "rgba(255,255,255,0.5)"
8169
+ },
8170
+ children: "/"
8171
+ }),
8172
+ " ",
8173
+ formatTime(duration)
8174
+ ]
8175
+ })
8176
+ ]
8177
+ }),
8178
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
8179
+ style: {
8180
+ display: "flex",
8181
+ alignItems: "center",
8182
+ gap: "".concat(8 * responsiveScale, "px")
8183
+ },
8184
+ children: [
8185
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
8186
+ style: {
8187
+ position: "relative",
8188
+ display: viewportWidth < 600 ? "none" : "block"
8189
+ },
8190
+ children: [
8191
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("button", {
8192
+ className: "sc-ctrl-btn",
8193
+ onClick: function onClick() {
8194
+ setShowSpeedMenu(!showSpeedMenu);
8195
+ resetControlsTimer();
8196
+ },
7908
8197
  style: {
7909
- filter: "drop-shadow(0 0 0 transparent)"
7910
- }
8198
+ padding: "".concat(6 * responsiveScale, "px ").concat(10 * responsiveScale, "px"),
8199
+ borderRadius: "".concat(6 * responsiveScale, "px"),
8200
+ fontSize: "".concat(13 * responsiveScale, "px"),
8201
+ fontFamily: "'SF Mono', 'Cascadia Code', monospace",
8202
+ fontWeight: "600",
8203
+ minHeight: "".concat(32 * responsiveScale, "px")
8204
+ },
8205
+ title: "Playback Speed",
8206
+ children: [
8207
+ playbackRate,
8208
+ "x"
8209
+ ]
8210
+ }),
8211
+ showSpeedMenu && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
8212
+ style: {
8213
+ position: "absolute",
8214
+ bottom: "100%",
8215
+ right: 0,
8216
+ marginBottom: "8px",
8217
+ background: "rgba(0, 0, 0, 0.8)",
8218
+ backdropFilter: "blur(24px)",
8219
+ WebkitBackdropFilter: "blur(24px)",
8220
+ borderRadius: "10px",
8221
+ border: "1px solid rgba(255, 255, 255, 0.1)",
8222
+ overflow: "hidden",
8223
+ minWidth: "80px",
8224
+ boxShadow: "0 12px 40px rgba(0, 0, 0, 0.5)",
8225
+ animation: "sc-fade-in 0.15s ease"
8226
+ },
8227
+ children: [
8228
+ 0.25,
8229
+ 0.5,
8230
+ 0.75,
8231
+ 1,
8232
+ 1.25,
8233
+ 1.5,
8234
+ 1.75,
8235
+ 2
8236
+ ].map(function(speed) {
8237
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("button", {
8238
+ onClick: function onClick() {
8239
+ return handlePlaybackRateChange(speed);
8240
+ },
8241
+ style: {
8242
+ display: "block",
8243
+ width: "100%",
8244
+ padding: "".concat(8 * responsiveScale, "px ").concat(14 * responsiveScale, "px"),
8245
+ background: playbackRate === speed ? "rgba(255, 255, 255, 0.12)" : "transparent",
8246
+ border: "none",
8247
+ color: playbackRate === speed ? "#fff" : "rgba(255, 255, 255, 0.7)",
8248
+ cursor: "pointer",
8249
+ fontSize: "".concat(12 * responsiveScale, "px"),
8250
+ fontFamily: "'SF Mono', monospace",
8251
+ fontWeight: playbackRate === speed ? "700" : "500",
8252
+ textAlign: "center",
8253
+ transition: "background 0.15s ease, color 0.15s ease"
8254
+ },
8255
+ onMouseEnter: function onMouseEnter(e) {
8256
+ if (playbackRate !== speed) {
8257
+ e.target.style.background = "rgba(255, 255, 255, 0.08)";
8258
+ e.target.style.color = "#fff";
8259
+ }
8260
+ },
8261
+ onMouseLeave: function onMouseLeave(e) {
8262
+ if (playbackRate !== speed) {
8263
+ e.target.style.background = "transparent";
8264
+ e.target.style.color = "rgba(255, 255, 255, 0.7)";
8265
+ }
8266
+ },
8267
+ children: [
8268
+ speed,
8269
+ "x"
8270
+ ]
8271
+ }, speed);
8272
+ })
7911
8273
  })
8274
+ ]
8275
+ }),
8276
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", {
8277
+ className: "sc-ctrl-btn",
8278
+ onClick: function onClick() {
8279
+ if (onFullscreenToggle) {
8280
+ onFullscreenToggle();
8281
+ } else if (wrapperRef.current) {
8282
+ if (!document.fullscreenElement) {
8283
+ wrapperRef.current.requestFullscreen().catch(function() {});
8284
+ } else {
8285
+ document.exitFullscreen().catch(function() {});
8286
+ }
8287
+ }
8288
+ resetControlsTimer();
8289
+ },
8290
+ style: {
8291
+ padding: "".concat(8 * responsiveScale, "px"),
8292
+ borderRadius: "50%",
8293
+ minWidth: "".concat(36 * responsiveScale, "px"),
8294
+ minHeight: "".concat(36 * responsiveScale, "px")
8295
+ },
8296
+ title: isFullscreen ? "Exit Fullscreen" : "Enter Fullscreen",
8297
+ children: isFullscreen ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_fa.FaCompress, {
8298
+ size: Math.max(14, 18 * responsiveScale)
8299
+ }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_fa.FaExpand, {
8300
+ size: Math.max(14, 18 * responsiveScale)
7912
8301
  })
7913
- ]
7914
- })
7915
- ]
7916
- })
7917
- ]
7918
- })
8302
+ })
8303
+ ]
8304
+ })
8305
+ ]
8306
+ })
8307
+ ]
7919
8308
  }) : showCustomControls && !showLicenseWarning && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
8309
+ className: "sc-controls-bar",
7920
8310
  style: {
7921
8311
  position: "absolute",
7922
8312
  bottom: "".concat(10 * responsiveScale, "px"),
7923
8313
  right: "".concat(10 * responsiveScale, "px"),
7924
- transform: "none",
7925
8314
  display: "flex",
7926
8315
  flexDirection: isPortrait ? "column" : "row",
7927
- gap: "".concat(10 * responsiveScale, "px"),
7928
- zIndex: 10
8316
+ gap: "".concat(8 * responsiveScale, "px"),
8317
+ zIndex: 10,
8318
+ opacity: controlsVisible ? 1 : 0,
8319
+ transform: controlsVisible ? "translateY(0)" : "translateY(4px)",
8320
+ pointerEvents: controlsVisible ? "auto" : "none"
7929
8321
  },
7930
8322
  children: [
7931
8323
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
7932
8324
  style: {
7933
- position: "relative",
7934
8325
  display: "flex",
7935
8326
  alignItems: "center",
7936
- padding: "8px",
7937
- margin: "-8px"
8327
+ background: "rgba(0, 0, 0, 0.6)",
8328
+ borderRadius: "".concat(18 * responsiveScale, "px"),
8329
+ padding: "2px"
7938
8330
  },
7939
8331
  onMouseEnter: function onMouseEnter() {
7940
8332
  return setShowVolumeSlider(true);
@@ -7944,260 +8336,128 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
7944
8336
  },
7945
8337
  children: [
7946
8338
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", {
8339
+ className: "sc-ctrl-btn",
7947
8340
  onClick: function onClick() {
7948
- if (playerRef.current) {
7949
- playerRef.current.toggleMute();
7950
- }
7951
- if (onVolumeToggle) {
7952
- onVolumeToggle();
7953
- }
7954
- },
7955
- onMouseEnter: function onMouseEnter(e) {
7956
- var target = e.currentTarget;
7957
- 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)";
7958
- target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.85) 0%, rgba(0, 0, 0, 0.75) 100%)";
7959
- },
7960
- onMouseLeave: function onMouseLeave(e) {
7961
- var target = e.currentTarget;
7962
- 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)";
7963
- target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.75) 0%, rgba(0, 0, 0, 0.65) 100%)";
8341
+ if (playerRef.current) playerRef.current.toggleMute();
8342
+ onVolumeToggle === null || onVolumeToggle === void 0 ? void 0 : onVolumeToggle();
8343
+ resetControlsTimer();
7964
8344
  },
7965
8345
  style: {
7966
- background: "linear-gradient(135deg, rgba(0, 0, 0, 0.75) 0%, rgba(0, 0, 0, 0.65) 100%)",
7967
- color: "#ffffff",
7968
- border: "none",
7969
- borderRadius: "".concat(18 * responsiveScale, "px"),
7970
8346
  padding: "".concat(8 * responsiveScale, "px"),
7971
- cursor: "pointer",
7972
- display: "flex",
7973
- alignItems: "center",
7974
- justifyContent: "center",
7975
- backdropFilter: "blur(20px)",
7976
- 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)",
7977
- transition: "all 0.4s cubic-bezier(0.4, 0, 0.2, 1)",
7978
- minWidth: "".concat(46 * responsiveScale, "px"),
7979
- minHeight: "".concat(46 * responsiveScale, "px")
8347
+ borderRadius: "50%",
8348
+ minWidth: "".concat(36 * responsiveScale, "px"),
8349
+ minHeight: "".concat(36 * responsiveScale, "px")
7980
8350
  },
7981
8351
  title: isMuted ? "Unmute" : "Mute",
7982
- children: isMuted || volume === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_fa.FaVolumeMute, {
7983
- size: Math.max(14, 16 * responsiveScale),
7984
- style: {
7985
- filter: "drop-shadow(0 2px 4px rgba(0, 0, 0, 0.8))",
7986
- color: "#ffffff"
7987
- }
7988
- }) : volume < 0.5 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_fa.FaVolumeDown, {
7989
- size: Math.max(14, 16 * responsiveScale),
7990
- style: {
7991
- filter: "drop-shadow(0 2px 4px rgba(0, 0, 0, 0.8))",
7992
- color: "#ffffff"
7993
- }
7994
- }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_fa.FaVolumeUp, {
7995
- size: Math.max(14, 16 * responsiveScale),
7996
- style: {
7997
- filter: "drop-shadow(0 2px 4px rgba(0, 0, 0, 0.8))",
7998
- color: "#ffffff"
7999
- }
8352
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(VolumeIcon, {
8353
+ size: Math.max(14, 18 * responsiveScale)
8000
8354
  })
8001
8355
  }),
8002
- showVolumeSlider && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, {
8003
- children: [
8004
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
8005
- style: {
8006
- position: "absolute",
8007
- bottom: "100%",
8008
- left: "50%",
8009
- transform: "translateX(-50%)",
8010
- width: "60px",
8011
- height: "20px",
8012
- marginBottom: "-16px",
8013
- zIndex: 9
8014
- },
8015
- onMouseEnter: function onMouseEnter() {
8016
- return setShowVolumeSlider(true);
8017
- },
8018
- onMouseLeave: function onMouseLeave() {
8019
- return setShowVolumeSlider(false);
8020
- }
8021
- }),
8022
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
8023
- style: {
8024
- position: "absolute",
8025
- bottom: "100%",
8026
- left: "50%",
8027
- transform: "translateX(-50%)",
8028
- marginBottom: "4px",
8029
- background: "linear-gradient(135deg, rgba(0, 0, 0, 0.96) 0%, rgba(20, 20, 20, 0.92) 100%)",
8030
- backdropFilter: "blur(20px)",
8031
- padding: "10px 14px",
8032
- borderRadius: "14px",
8033
- border: "2px solid rgba(255, 255, 255, 0.7)",
8034
- display: "flex",
8035
- flexDirection: "column",
8036
- alignItems: "center",
8037
- justifyContent: "center",
8038
- height: "128px",
8039
- 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)",
8040
- zIndex: 10,
8041
- transition: "transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out, border-color 0.2s ease-in-out"
8042
- },
8043
- onMouseEnter: function onMouseEnter(e) {
8044
- setShowVolumeSlider(true);
8045
- 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)";
8046
- e.currentTarget.style.borderColor = "rgba(96, 165, 250, 0.8)";
8047
- },
8048
- onMouseLeave: function onMouseLeave(e) {
8049
- setShowVolumeSlider(false);
8050
- 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)";
8051
- e.currentTarget.style.borderColor = "rgba(255, 255, 255, 0.7)";
8052
- },
8053
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
8356
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
8357
+ style: {
8358
+ width: showVolumeSlider ? "".concat(62 * responsiveScale, "px") : "0px",
8359
+ overflow: "hidden",
8360
+ transition: "width 0.2s cubic-bezier(0.4, 0, 0.2, 1)",
8361
+ display: "flex",
8362
+ alignItems: "center",
8363
+ paddingLeft: showVolumeSlider ? "2px" : "0",
8364
+ paddingRight: showVolumeSlider ? "6px" : "0"
8365
+ },
8366
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
8367
+ style: {
8368
+ position: "relative",
8369
+ width: "".concat(56 * responsiveScale, "px"),
8370
+ height: "3px",
8371
+ cursor: "pointer",
8372
+ borderRadius: "1.5px"
8373
+ },
8374
+ onMouseDown: function onMouseDown(e) {
8375
+ e.preventDefault();
8376
+ var el = e.currentTarget;
8377
+ var move = function move(ev) {
8378
+ var r2 = el.getBoundingClientRect();
8379
+ handleVolumeChange(Math.max(0, Math.min(1, (ev.clientX - r2.left) / r2.width)));
8380
+ };
8381
+ var up = function up1() {
8382
+ document.removeEventListener("mousemove", move);
8383
+ document.removeEventListener("mouseup", up);
8384
+ };
8385
+ document.addEventListener("mousemove", move);
8386
+ document.addEventListener("mouseup", up);
8387
+ var r = el.getBoundingClientRect();
8388
+ handleVolumeChange(Math.max(0, Math.min(1, (e.clientX - r.left) / r.width)));
8389
+ },
8390
+ onClick: function onClick(e) {
8391
+ e.stopPropagation();
8392
+ var r = e.currentTarget.getBoundingClientRect();
8393
+ handleVolumeChange(Math.max(0, Math.min(1, (e.clientX - r.left) / r.width)));
8394
+ },
8395
+ children: [
8396
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
8054
8397
  style: {
8055
- position: "relative",
8056
- width: "8px",
8057
- height: "104px",
8058
- cursor: "pointer",
8059
- transition: "transform 0.2s ease-in-out"
8060
- },
8061
- onMouseDown: function onMouseDown(e) {
8062
- e.preventDefault();
8063
- var sliderElement = e.currentTarget;
8064
- var handleMouseMove = function handleMouseMove(moveEvent) {
8065
- if (!sliderElement) return;
8066
- var rect2 = sliderElement.getBoundingClientRect();
8067
- var y2 = moveEvent.clientY - rect2.top;
8068
- var percentage2 = 1 - Math.max(0, Math.min(1, y2 / rect2.height));
8069
- handleVolumeChange(percentage2);
8070
- };
8071
- var handleMouseUp = function handleMouseUp1() {
8072
- document.removeEventListener("mousemove", handleMouseMove);
8073
- document.removeEventListener("mouseup", handleMouseUp);
8074
- };
8075
- document.addEventListener("mousemove", handleMouseMove);
8076
- document.addEventListener("mouseup", handleMouseUp);
8077
- var rect = sliderElement.getBoundingClientRect();
8078
- var y = e.clientY - rect.top;
8079
- var percentage = 1 - Math.max(0, Math.min(1, y / rect.height));
8080
- handleVolumeChange(percentage);
8081
- },
8082
- onClick: function onClick(e) {
8083
- e.stopPropagation();
8084
- var rect = e.currentTarget.getBoundingClientRect();
8085
- var y = e.clientY - rect.top;
8086
- var percentage = 1 - Math.max(0, Math.min(1, y / rect.height));
8087
- handleVolumeChange(percentage);
8088
- },
8089
- children: [
8090
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
8091
- style: {
8092
- position: "absolute",
8093
- bottom: "0",
8094
- left: "0",
8095
- width: "100%",
8096
- height: "100%",
8097
- background: "linear-gradient(180deg, rgba(255, 255, 255, 0.85) 0%, rgba(255, 255, 255, 0.5) 100%)",
8098
- borderRadius: "4px",
8099
- border: "1px solid rgba(255, 255, 255, 0.4)",
8100
- boxShadow: "inset 0 1px 3px rgba(0, 0, 0, 0.3)"
8101
- }
8102
- }),
8103
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
8104
- style: {
8105
- position: "absolute",
8106
- bottom: "0",
8107
- left: "0",
8108
- width: "100%",
8109
- height: "".concat((isMuted ? 0 : volume) * 100, "%"),
8110
- background: "linear-gradient(180deg, rgba(125, 211, 252, 1) 0%, rgba(96, 165, 250, 0.98) 50%, rgba(59, 130, 246, 0.95) 100%)",
8111
- borderRadius: "4px",
8112
- transition: "height 0.15s ease-out, box-shadow 0.2s ease-in-out",
8113
- boxShadow: "0 0 12px rgba(96, 165, 250, 0.6), inset 0 1px 0 rgba(255, 255, 255, 0.4)"
8114
- }
8115
- }),
8116
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
8117
- style: {
8118
- position: "absolute",
8119
- bottom: "calc(".concat((isMuted ? 0 : volume) * 100, "% - 8px)"),
8120
- left: "50%",
8121
- transform: "translateX(-50%)",
8122
- width: "16px",
8123
- height: "16px",
8124
- background: "linear-gradient(135deg, #ffffff 0%, #f0f9ff 100%)",
8125
- borderRadius: "50%",
8126
- border: "2px solid rgba(96, 165, 250, 0.9)",
8127
- 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)",
8128
- 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",
8129
- cursor: "grab"
8130
- },
8131
- onMouseEnter: function onMouseEnter(e) {
8132
- 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)";
8133
- e.currentTarget.style.cursor = "grab";
8134
- },
8135
- onMouseLeave: function onMouseLeave(e) {
8136
- 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)";
8137
- },
8138
- onMouseDown: function onMouseDown(e) {
8139
- e.currentTarget.style.cursor = "grabbing";
8140
- },
8141
- onMouseUp: function onMouseUp(e) {
8142
- e.currentTarget.style.cursor = "grab";
8143
- }
8144
- })
8145
- ]
8398
+ position: "absolute",
8399
+ inset: 0,
8400
+ background: "rgba(255, 255, 255, 0.2)",
8401
+ borderRadius: "1.5px"
8402
+ }
8403
+ }),
8404
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
8405
+ style: {
8406
+ position: "absolute",
8407
+ top: 0,
8408
+ left: 0,
8409
+ bottom: 0,
8410
+ width: "".concat((isMuted ? 0 : volume) * 100, "%"),
8411
+ background: "#fff",
8412
+ borderRadius: "1.5px",
8413
+ transition: "width 0.1s ease-out"
8414
+ }
8415
+ }),
8416
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
8417
+ style: {
8418
+ position: "absolute",
8419
+ top: "50%",
8420
+ left: "".concat((isMuted ? 0 : volume) * 100, "%"),
8421
+ transform: "translate(-50%, -50%)",
8422
+ width: "12px",
8423
+ height: "12px",
8424
+ background: "#fff",
8425
+ borderRadius: "50%",
8426
+ boxShadow: "0 0 3px rgba(0, 0, 0, 0.3)",
8427
+ transition: "left 0.1s ease-out"
8428
+ }
8146
8429
  })
8147
- })
8148
- ]
8430
+ ]
8431
+ })
8149
8432
  })
8150
8433
  ]
8151
8434
  }),
8152
8435
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", {
8436
+ className: "sc-ctrl-btn",
8153
8437
  onClick: function onClick() {
8154
8438
  if (onFullscreenToggle) {
8155
8439
  onFullscreenToggle();
8156
- } else if (playerRef.current) {
8157
- playerRef.current.toggleFullscreen().catch(function(err) {
8158
- console.error("Fullscreen error:", err);
8159
- });
8440
+ } else if (wrapperRef.current) {
8441
+ if (!document.fullscreenElement) {
8442
+ wrapperRef.current.requestFullscreen().catch(function() {});
8443
+ } else {
8444
+ document.exitFullscreen().catch(function() {});
8445
+ }
8160
8446
  }
8161
- },
8162
- onMouseEnter: function onMouseEnter(e) {
8163
- var target = e.currentTarget;
8164
- 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)";
8165
- target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.85) 0%, rgba(0, 0, 0, 0.75) 100%)";
8166
- },
8167
- onMouseLeave: function onMouseLeave(e) {
8168
- var target = e.currentTarget;
8169
- 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)";
8170
- target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.75) 0%, rgba(0, 0, 0, 0.65) 100%)";
8447
+ resetControlsTimer();
8171
8448
  },
8172
8449
  style: {
8173
- background: "linear-gradient(135deg, rgba(0, 0, 0, 0.75) 0%, rgba(0, 0, 0, 0.65) 100%)",
8174
- color: "#ffffff",
8175
- border: "none",
8176
- borderRadius: "".concat(18 * responsiveScale, "px"),
8177
8450
  padding: "".concat(8 * responsiveScale, "px"),
8178
- cursor: "pointer",
8179
- display: "flex",
8180
- alignItems: "center",
8181
- justifyContent: "center",
8182
- backdropFilter: "blur(20px)",
8183
- 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)",
8184
- transition: "all 0.4s cubic-bezier(0.4, 0, 0.2, 1)",
8185
- minWidth: "".concat(46 * responsiveScale, "px"),
8186
- minHeight: "".concat(46 * responsiveScale, "px")
8451
+ borderRadius: "50%",
8452
+ minWidth: "".concat(36 * responsiveScale, "px"),
8453
+ minHeight: "".concat(36 * responsiveScale, "px"),
8454
+ background: "rgba(0, 0, 0, 0.6)"
8187
8455
  },
8188
8456
  title: isFullscreen ? "Exit Fullscreen" : "Enter Fullscreen",
8189
8457
  children: isFullscreen ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_fa.FaCompress, {
8190
- size: Math.max(14, 16 * responsiveScale),
8191
- style: {
8192
- filter: "drop-shadow(0 2px 4px rgba(0, 0, 0, 0.8))",
8193
- color: "#ffffff"
8194
- }
8458
+ size: Math.max(14, 18 * responsiveScale)
8195
8459
  }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_fa.FaExpand, {
8196
- size: Math.max(14, 16 * responsiveScale),
8197
- style: {
8198
- filter: "drop-shadow(0 2px 4px rgba(0, 0, 0, 0.8))",
8199
- color: "#ffffff"
8200
- }
8460
+ size: Math.max(14, 18 * responsiveScale)
8201
8461
  })
8202
8462
  })
8203
8463
  ]