stormcloud-video-player 0.7.13 → 0.7.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/index.d.cts CHANGED
@@ -157,6 +157,7 @@ declare class StormcloudVideoPlayer {
157
157
  private pendingAdBreak;
158
158
  private prefetchTimerId;
159
159
  private savedMutedStateBeforeAd;
160
+ private adLayerInitialized;
160
161
  private consecutiveFailures;
161
162
  private readonly maxConsecutiveFailures;
162
163
  private lastAdRequestTime;
@@ -192,6 +193,8 @@ declare class StormcloudVideoPlayer {
192
193
  getRemainingAdSeconds(): number;
193
194
  isAdPlaying(): boolean;
194
195
  isShowingAds(): boolean;
196
+ private initializeAdLayer;
197
+ setDisableAds(disabled: boolean): void;
195
198
  private syncMainContentAudioWhenVisible;
196
199
  getStreamType(): "hls" | "other";
197
200
  shouldShowNativeControls(): boolean;
@@ -204,6 +207,7 @@ declare class StormcloudVideoPlayer {
204
207
  private stopAdInsertionPolling;
205
208
  private fetchAdInsertionPoint;
206
209
  private checkAdInsertionInManifest;
210
+ private extractTsFilename;
207
211
  private fragmentMatchesSegment;
208
212
  private clearAdInsertionOffsetTimer;
209
213
  private startContinuousFetchLoop;
@@ -4026,6 +4030,14 @@ interface SwirlScrollerConfig {
4026
4030
  auto_refresh?: boolean;
4027
4031
  use_custom_text?: boolean;
4028
4032
  custom_text?: string;
4033
+ label?: string;
4034
+ label_line2?: string;
4035
+ label_color?: string;
4036
+ label_text_color?: string;
4037
+ accent_color?: string;
4038
+ show_accent_line?: boolean;
4039
+ separator_char?: string;
4040
+ preset?: string;
4029
4041
  }
4030
4042
  type SwirlOverlayType = "image" | "text" | "scroller" | "shape" | "score_bug" | "lower_third" | "qr_code" | "coming_up_next" | "contextual_trigger" | "odds_betting" | "breaking_news" | "countdown";
4031
4043
  interface SwirlOverlay {
package/lib/index.d.ts CHANGED
@@ -157,6 +157,7 @@ declare class StormcloudVideoPlayer {
157
157
  private pendingAdBreak;
158
158
  private prefetchTimerId;
159
159
  private savedMutedStateBeforeAd;
160
+ private adLayerInitialized;
160
161
  private consecutiveFailures;
161
162
  private readonly maxConsecutiveFailures;
162
163
  private lastAdRequestTime;
@@ -192,6 +193,8 @@ declare class StormcloudVideoPlayer {
192
193
  getRemainingAdSeconds(): number;
193
194
  isAdPlaying(): boolean;
194
195
  isShowingAds(): boolean;
196
+ private initializeAdLayer;
197
+ setDisableAds(disabled: boolean): void;
195
198
  private syncMainContentAudioWhenVisible;
196
199
  getStreamType(): "hls" | "other";
197
200
  shouldShowNativeControls(): boolean;
@@ -204,6 +207,7 @@ declare class StormcloudVideoPlayer {
204
207
  private stopAdInsertionPolling;
205
208
  private fetchAdInsertionPoint;
206
209
  private checkAdInsertionInManifest;
210
+ private extractTsFilename;
207
211
  private fragmentMatchesSegment;
208
212
  private clearAdInsertionOffsetTimer;
209
213
  private startContinuousFetchLoop;
@@ -4026,6 +4030,14 @@ interface SwirlScrollerConfig {
4026
4030
  auto_refresh?: boolean;
4027
4031
  use_custom_text?: boolean;
4028
4032
  custom_text?: string;
4033
+ label?: string;
4034
+ label_line2?: string;
4035
+ label_color?: string;
4036
+ label_text_color?: string;
4037
+ accent_color?: string;
4038
+ show_accent_line?: boolean;
4039
+ separator_char?: string;
4040
+ preset?: string;
4029
4041
  }
4030
4042
  type SwirlOverlayType = "image" | "text" | "scroller" | "shape" | "score_bug" | "lower_third" | "qr_code" | "coming_up_next" | "contextual_trigger" | "odds_betting" | "breaking_news" | "countdown";
4031
4043
  interface SwirlOverlay {
package/lib/index.js CHANGED
@@ -2765,6 +2765,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
2765
2765
  this.maxTotalAdRequestsPerBreak = 20;
2766
2766
  this.pendingAdBreak = null;
2767
2767
  this.savedMutedStateBeforeAd = null;
2768
+ this.adLayerInitialized = false;
2768
2769
  this.consecutiveFailures = 0;
2769
2770
  this.maxConsecutiveFailures = 5;
2770
2771
  this.lastAdRequestTime = 0;
@@ -3413,12 +3414,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3413
3414
  this.video.autoplay = !!this.config.autoplay;
3414
3415
  this.video.muted = !!this.config.muted;
3415
3416
  if (!this.config.disableAds) {
3416
- this.adLayer.initialize();
3417
- if (!this.config.disableFiller) {
3418
- this.ensureFillerVideo();
3419
- }
3420
- this.adLayer.updateOriginalMutedState(this.video.muted, this.video.volume);
3421
- this.attachAdLayerEventListeners();
3417
+ this.initializeAdLayer();
3422
3418
  }
3423
3419
  this.timeUpdateHandler = function() {
3424
3420
  _this.onTimeUpdate(_this.video.currentTime);
@@ -3519,6 +3515,31 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3519
3515
  return this.showAds;
3520
3516
  }
3521
3517
  },
3518
+ {
3519
+ key: "initializeAdLayer",
3520
+ value: function initializeAdLayer() {
3521
+ if (this.adLayerInitialized) return;
3522
+ this.adLayer.initialize();
3523
+ if (!this.config.disableFiller) {
3524
+ this.ensureFillerVideo();
3525
+ }
3526
+ this.adLayer.updateOriginalMutedState(this.video.muted, this.video.volume);
3527
+ this.attachAdLayerEventListeners();
3528
+ this.adLayerInitialized = true;
3529
+ }
3530
+ },
3531
+ {
3532
+ key: "setDisableAds",
3533
+ value: function setDisableAds(disabled) {
3534
+ this.config.disableAds = disabled;
3535
+ if (!disabled && this.attached) {
3536
+ this.initializeAdLayer();
3537
+ }
3538
+ if (this.config.debugAdTiming) {
3539
+ console.log("[StormcloudVideoPlayer] setDisableAds:", disabled);
3540
+ }
3541
+ }
3542
+ },
3522
3543
  {
3523
3544
  key: "syncMainContentAudioWhenVisible",
3524
3545
  value: function syncMainContentAudioWhenVisible() {
@@ -4043,14 +4064,21 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4043
4064
  }
4044
4065
  }
4045
4066
  },
4067
+ {
4068
+ key: "extractTsFilename",
4069
+ value: function extractTsFilename(url) {
4070
+ var _parts_;
4071
+ var clean = url.includes("?") ? url.slice(0, url.indexOf("?")) : url;
4072
+ var parts = clean.split("/");
4073
+ return (_parts_ = parts[parts.length - 1]) !== null && _parts_ !== void 0 ? _parts_ : clean;
4074
+ }
4075
+ },
4046
4076
  {
4047
4077
  key: "fragmentMatchesSegment",
4048
4078
  value: function fragmentMatchesSegment(frag, segmentName) {
4049
- var _rawUrl_split_;
4050
4079
  var rawUrl = (frag === null || frag === void 0 ? void 0 : frag.url) || (frag === null || frag === void 0 ? void 0 : frag.relurl) || "";
4051
- var url = (_rawUrl_split_ = rawUrl.split("?")[0]) !== null && _rawUrl_split_ !== void 0 ? _rawUrl_split_ : "";
4052
- var name = segmentName.startsWith("/") ? segmentName : "/" + segmentName;
4053
- return url.endsWith(name) || url.includes(name);
4080
+ if (!rawUrl) return false;
4081
+ return this.extractTsFilename(rawUrl) === this.extractTsFilename(segmentName);
4054
4082
  }
4055
4083
  },
4056
4084
  {
@@ -5581,7 +5609,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5581
5609
  // src/ui/StormcloudVideoPlayer.tsx
5582
5610
  import { FaPlay, FaPause, FaVolumeUp, FaVolumeMute, FaVolumeDown, FaExpand, FaCompress, FaCog, FaTimes, FaCopy } from "react-icons/fa";
5583
5611
  // src/ui/OverlayRenderer.tsx
5584
- import React, { useEffect, useRef, useState, useCallback, useMemo } from "react";
5612
+ import React, { useEffect, useRef, useState, useCallback, useMemo, useId } from "react";
5585
5613
  // src/utils/overlays.ts
5586
5614
  var OVERLAY_API_BASE = "https://adstorm.co/api-adstorm-dev";
5587
5615
  function timeStringToSeconds(timeStr) {
@@ -5746,60 +5774,303 @@ function TextOverlay(param) {
5746
5774
  children: text
5747
5775
  });
5748
5776
  }
5777
+ function fetchRSSItems(rssUrl, maxItems) {
5778
+ return _async_to_generator(function() {
5779
+ var resp, data, parser, doc;
5780
+ return _ts_generator(this, function(_state) {
5781
+ switch(_state.label){
5782
+ case 0:
5783
+ return [
5784
+ 4,
5785
+ fetch("https://api.allorigins.win/get?url=".concat(encodeURIComponent(rssUrl)))
5786
+ ];
5787
+ case 1:
5788
+ resp = _state.sent();
5789
+ return [
5790
+ 4,
5791
+ resp.json()
5792
+ ];
5793
+ case 2:
5794
+ data = _state.sent();
5795
+ if (!data.contents) throw new Error("No content from RSS feed");
5796
+ parser = new DOMParser();
5797
+ doc = parser.parseFromString(data.contents, "text/xml");
5798
+ if (doc.querySelector("parsererror")) throw new Error("Invalid RSS XML");
5799
+ return [
5800
+ 2,
5801
+ Array.from(doc.querySelectorAll("item")).map(function(item) {
5802
+ var _item_querySelector, _item_querySelector1, _item_querySelector2, _item_querySelector3, _item_querySelector4;
5803
+ return {
5804
+ title: (((_item_querySelector = item.querySelector("title")) === null || _item_querySelector === void 0 ? void 0 : _item_querySelector.textContent) || "").replace(/<[^>]*>/g, "").trim(),
5805
+ description: (((_item_querySelector1 = item.querySelector("description")) === null || _item_querySelector1 === void 0 ? void 0 : _item_querySelector1.textContent) || "").replace(/<[^>]*>/g, "").trim(),
5806
+ pubDate: ((_item_querySelector2 = item.querySelector("pubDate")) === null || _item_querySelector2 === void 0 ? void 0 : _item_querySelector2.textContent) || "",
5807
+ author: ((_item_querySelector3 = item.querySelector("author, dc\\:creator")) === null || _item_querySelector3 === void 0 ? void 0 : _item_querySelector3.textContent) || "",
5808
+ category: ((_item_querySelector4 = item.querySelector("category")) === null || _item_querySelector4 === void 0 ? void 0 : _item_querySelector4.textContent) || ""
5809
+ };
5810
+ }).filter(function(i) {
5811
+ return i.title;
5812
+ }).slice(0, maxItems)
5813
+ ];
5814
+ }
5815
+ });
5816
+ })();
5817
+ }
5749
5818
  function ScrollerOverlay(param) {
5750
5819
  var overlay = param.overlay;
5751
- var _ref, _ref1, _ref2, _ref3, _ref4;
5820
+ var _ref, _ref1, _ref2, _ref3, _ref4, _ref5, _ref6, _ref7, _ref8, _ref9, _ref10, _ref11, _ref12;
5752
5821
  var cfg = overlay.scroller_config;
5753
- var text = (cfg === null || cfg === void 0 ? void 0 : cfg.use_custom_text) && cfg.custom_text ? cfg.custom_text : overlay.content || (cfg === null || cfg === void 0 ? void 0 : cfg.custom_text) || "";
5754
- var scrollSpeed = (_ref = cfg === null || cfg === void 0 ? void 0 : cfg.scroll_speed) !== null && _ref !== void 0 ? _ref : 50;
5755
- var direction = (_ref1 = cfg === null || cfg === void 0 ? void 0 : cfg.direction) !== null && _ref1 !== void 0 ? _ref1 : "left";
5756
- var fontSize = (cfg === null || cfg === void 0 ? void 0 : cfg.font_size) ? "".concat(cfg.font_size, "px") : "clamp(10px, 1.2vw, 18px)";
5822
+ var uid = useId().replace(/:/g, "");
5823
+ var _useState = _sliced_to_array(useState([]), 2), rssItems = _useState[0], setRssItems = _useState[1];
5824
+ var _useState1 = _sliced_to_array(useState(false), 2), rssLoading = _useState1[0], setRssLoading = _useState1[1];
5825
+ var rssUrl = (cfg === null || cfg === void 0 ? void 0 : cfg.rss_url) || "";
5826
+ var maxItems = (_ref = cfg === null || cfg === void 0 ? void 0 : cfg.max_items) !== null && _ref !== void 0 ? _ref : 10;
5827
+ var autoRefresh = (cfg === null || cfg === void 0 ? void 0 : cfg.auto_refresh) !== false;
5828
+ var updateInterval = (_ref1 = cfg === null || cfg === void 0 ? void 0 : cfg.update_interval) !== null && _ref1 !== void 0 ? _ref1 : 5;
5829
+ useEffect(function() {
5830
+ if (!rssUrl || (cfg === null || cfg === void 0 ? void 0 : cfg.use_custom_text) && (cfg === null || cfg === void 0 ? void 0 : cfg.custom_text)) return;
5831
+ var cancelled = false;
5832
+ setRssLoading(true);
5833
+ fetchRSSItems(rssUrl, maxItems).then(function(items) {
5834
+ if (!cancelled) setRssItems(items);
5835
+ }).catch(function() {}).finally(function() {
5836
+ if (!cancelled) setRssLoading(false);
5837
+ });
5838
+ return function() {
5839
+ cancelled = true;
5840
+ };
5841
+ }, [
5842
+ rssUrl,
5843
+ maxItems,
5844
+ cfg === null || cfg === void 0 ? void 0 : cfg.use_custom_text,
5845
+ cfg === null || cfg === void 0 ? void 0 : cfg.custom_text
5846
+ ]);
5847
+ useEffect(function() {
5848
+ if (!rssUrl || !autoRefresh || (cfg === null || cfg === void 0 ? void 0 : cfg.use_custom_text) && (cfg === null || cfg === void 0 ? void 0 : cfg.custom_text)) return;
5849
+ var interval = setInterval(function() {
5850
+ fetchRSSItems(rssUrl, maxItems).then(setRssItems).catch(function() {});
5851
+ }, updateInterval * 60 * 1e3);
5852
+ return function() {
5853
+ return clearInterval(interval);
5854
+ };
5855
+ }, [
5856
+ rssUrl,
5857
+ autoRefresh,
5858
+ updateInterval,
5859
+ maxItems,
5860
+ cfg === null || cfg === void 0 ? void 0 : cfg.use_custom_text,
5861
+ cfg === null || cfg === void 0 ? void 0 : cfg.custom_text
5862
+ ]);
5863
+ var sep = (_ref2 = cfg === null || cfg === void 0 ? void 0 : cfg.separator_char) !== null && _ref2 !== void 0 ? _ref2 : "\u25C6";
5864
+ var segments;
5865
+ if ((cfg === null || cfg === void 0 ? void 0 : cfg.use_custom_text) && (cfg === null || cfg === void 0 ? void 0 : cfg.custom_text)) {
5866
+ segments = [
5867
+ cfg.custom_text
5868
+ ];
5869
+ } else if (rssItems.length > 0) {
5870
+ segments = rssItems.map(function(item) {
5871
+ var parts = [];
5872
+ if ((cfg === null || cfg === void 0 ? void 0 : cfg.show_title) !== false && item.title) parts.push(item.title);
5873
+ if ((cfg === null || cfg === void 0 ? void 0 : cfg.show_description) && item.description) parts.push(item.description);
5874
+ if ((cfg === null || cfg === void 0 ? void 0 : cfg.show_timestamp) && item.pubDate) {
5875
+ try {
5876
+ parts.push(new Date(item.pubDate).toLocaleDateString());
5877
+ } catch (unused) {}
5878
+ }
5879
+ if ((cfg === null || cfg === void 0 ? void 0 : cfg.show_author) && item.author) parts.push("— ".concat(item.author));
5880
+ if ((cfg === null || cfg === void 0 ? void 0 : cfg.show_category) && item.category) parts.push("[".concat(item.category, "]"));
5881
+ return parts.join(" ");
5882
+ });
5883
+ } else if (rssLoading) {
5884
+ segments = [
5885
+ "Loading feed\u2026"
5886
+ ];
5887
+ } else if (overlay.content) {
5888
+ segments = [
5889
+ overlay.content
5890
+ ];
5891
+ } else {
5892
+ segments = rssUrl ? [
5893
+ "Fetching RSS feed\u2026"
5894
+ ] : [
5895
+ "RSS Ticker"
5896
+ ];
5897
+ }
5898
+ var scrollSpeed = (_ref3 = cfg === null || cfg === void 0 ? void 0 : cfg.scroll_speed) !== null && _ref3 !== void 0 ? _ref3 : 40;
5899
+ var direction = (_ref4 = cfg === null || cfg === void 0 ? void 0 : cfg.direction) !== null && _ref4 !== void 0 ? _ref4 : "left";
5900
+ var fontSize = (_ref5 = cfg === null || cfg === void 0 ? void 0 : cfg.font_size) !== null && _ref5 !== void 0 ? _ref5 : 15;
5757
5901
  var fontFamily = (cfg === null || cfg === void 0 ? void 0 : cfg.font_family) || "Roboto, 'Segoe UI', Arial, sans-serif";
5758
- var fontWeight = (cfg === null || cfg === void 0 ? void 0 : cfg.font_weight) || "600";
5902
+ var fontWeight = (cfg === null || cfg === void 0 ? void 0 : cfg.font_weight) || "700";
5759
5903
  var textColor = (cfg === null || cfg === void 0 ? void 0 : cfg.text_color) || "#ffffff";
5760
- var bgColor = (cfg === null || cfg === void 0 ? void 0 : cfg.background_color) || "transparent";
5761
- var bgOpacity = (cfg === null || cfg === void 0 ? void 0 : cfg.background_opacity) !== void 0 ? cfg.background_opacity / 100 : 0;
5762
- var borderColor = (cfg === null || cfg === void 0 ? void 0 : cfg.border_color) || "transparent";
5763
- var borderWidth = (_ref2 = cfg === null || cfg === void 0 ? void 0 : cfg.border_width) !== null && _ref2 !== void 0 ? _ref2 : 0;
5764
- var borderRadius = (_ref3 = cfg === null || cfg === void 0 ? void 0 : cfg.border_radius) !== null && _ref3 !== void 0 ? _ref3 : 0;
5765
- var padding = (_ref4 = cfg === null || cfg === void 0 ? void 0 : cfg.padding) !== null && _ref4 !== void 0 ? _ref4 : 4;
5766
- var isVertical = direction === "up" || direction === "down";
5904
+ var bgColor = (cfg === null || cfg === void 0 ? void 0 : cfg.background_color) || "#0d0d1a";
5905
+ var bgOpacity = (cfg === null || cfg === void 0 ? void 0 : cfg.background_opacity) !== void 0 ? cfg.background_opacity / 100 : 0.95;
5906
+ var borderRadius = (_ref6 = cfg === null || cfg === void 0 ? void 0 : cfg.border_radius) !== null && _ref6 !== void 0 ? _ref6 : 0;
5907
+ var itemSpacing = (_ref7 = cfg === null || cfg === void 0 ? void 0 : cfg.item_spacing) !== null && _ref7 !== void 0 ? _ref7 : 60;
5908
+ var label = (_ref8 = cfg === null || cfg === void 0 ? void 0 : cfg.label) !== null && _ref8 !== void 0 ? _ref8 : "NEWS";
5909
+ var labelLine2 = (_ref9 = cfg === null || cfg === void 0 ? void 0 : cfg.label_line2) !== null && _ref9 !== void 0 ? _ref9 : "";
5910
+ var labelColor = (_ref10 = cfg === null || cfg === void 0 ? void 0 : cfg.label_color) !== null && _ref10 !== void 0 ? _ref10 : "#f97316";
5911
+ var labelTextColor = (_ref11 = cfg === null || cfg === void 0 ? void 0 : cfg.label_text_color) !== null && _ref11 !== void 0 ? _ref11 : "#ffffff";
5912
+ var accentColor = (_ref12 = cfg === null || cfg === void 0 ? void 0 : cfg.accent_color) !== null && _ref12 !== void 0 ? _ref12 : labelColor;
5913
+ var showAccentLine = (cfg === null || cfg === void 0 ? void 0 : cfg.show_accent_line) !== false;
5914
+ var isHorizontal = direction === "left" || direction === "right";
5767
5915
  var isReverse = direction === "right" || direction === "down";
5768
- var durationSec = Math.max(3, 120 - scrollSpeed);
5769
- var animId = "sc-scroller-".concat(overlay.id);
5770
- var keyframes = isVertical ? "@keyframes ".concat(animId, " {\n 0% { transform: translateY(").concat(isReverse ? "-100%" : "100%", "); }\n 100% { transform: translateY(").concat(isReverse ? "100%" : "-100%", "); }\n }") : "@keyframes ".concat(animId, " {\n 0% { transform: translateX(").concat(isReverse ? "-100%" : "100%", "); }\n 100% { transform: translateX(").concat(isReverse ? "100%" : "-100%", "); }\n }");
5916
+ var fullText = segments.join(" ".concat(sep, " "));
5917
+ var durationSec = Math.max(6, fullText.length * 9 / scrollSpeed);
5918
+ var animId = "sc-ticker-".concat(overlay.id, "-").concat(uid);
5919
+ var keyframes = isHorizontal ? "@keyframes ".concat(animId, " {\n ").concat(isReverse ? "0% { transform: translateX(-50%); } 100% { transform: translateX(0%); }" : "0% { transform: translateX(0); } 100% { transform: translateX(-50%); }", "\n }") : "@keyframes ".concat(animId, " {\n ").concat(isReverse ? "0% { transform: translateY(-50%); } 100% { transform: translateY(0%); }" : "0% { transform: translateY(0); } 100% { transform: translateY(-50%); }", "\n }");
5771
5920
  return /* @__PURE__ */ jsxs(Fragment, {
5772
5921
  children: [
5773
5922
  /* @__PURE__ */ jsx("style", {
5774
5923
  children: keyframes
5775
5924
  }),
5776
- /* @__PURE__ */ jsx("div", {
5925
+ /* @__PURE__ */ jsxs("div", {
5777
5926
  style: {
5778
5927
  width: "100%",
5779
5928
  height: "100%",
5780
- overflow: "hidden",
5781
5929
  display: "flex",
5782
- alignItems: "center",
5783
- backgroundColor: bgOpacity > 0 ? "rgba(".concat(hexToRgb(bgColor), ", ").concat(bgOpacity, ")") : void 0,
5784
- border: borderWidth > 0 ? "".concat(borderWidth, "px solid ").concat(borderColor) : void 0,
5930
+ flexDirection: "column",
5931
+ overflow: "hidden",
5785
5932
  borderRadius: borderRadius > 0 ? "".concat(borderRadius, "px") : void 0,
5786
- padding: "".concat(padding, "px"),
5787
- boxSizing: "border-box",
5788
- pointerEvents: "none"
5933
+ backgroundColor: "rgba(".concat(hexToRgb(bgColor), ", ").concat(bgOpacity, ")"),
5934
+ fontFamily: fontFamily,
5935
+ fontSize: "".concat(fontSize, "px"),
5936
+ fontWeight: fontWeight,
5937
+ color: textColor,
5938
+ pointerEvents: "none",
5939
+ userSelect: "none"
5789
5940
  },
5790
- children: /* @__PURE__ */ jsx("div", {
5791
- style: {
5792
- whiteSpace: "nowrap",
5793
- fontSize: fontSize,
5794
- fontFamily: fontFamily,
5795
- fontWeight: fontWeight,
5796
- color: textColor,
5797
- animation: "".concat(animId, " ").concat(durationSec, "s linear infinite"),
5798
- textShadow: "0 1px 4px rgba(0,0,0,0.5)",
5799
- userSelect: "none"
5800
- },
5801
- children: text
5802
- })
5941
+ children: [
5942
+ showAccentLine && /* @__PURE__ */ jsx("div", {
5943
+ style: {
5944
+ height: 3,
5945
+ background: accentColor,
5946
+ flexShrink: 0,
5947
+ width: "100%"
5948
+ }
5949
+ }),
5950
+ /* @__PURE__ */ jsxs("div", {
5951
+ style: {
5952
+ display: "flex",
5953
+ flex: 1,
5954
+ overflow: "hidden",
5955
+ minHeight: 0
5956
+ },
5957
+ children: [
5958
+ label && /* @__PURE__ */ jsxs("div", {
5959
+ style: {
5960
+ background: labelColor,
5961
+ color: labelTextColor,
5962
+ padding: "0 14px",
5963
+ display: "flex",
5964
+ flexDirection: "column",
5965
+ alignItems: "center",
5966
+ justifyContent: "center",
5967
+ flexShrink: 0,
5968
+ minWidth: 72,
5969
+ textAlign: "center",
5970
+ gap: 1
5971
+ },
5972
+ children: [
5973
+ /* @__PURE__ */ jsx("span", {
5974
+ style: {
5975
+ fontWeight: 800,
5976
+ fontSize: "0.82em",
5977
+ letterSpacing: "0.05em",
5978
+ lineHeight: 1.1,
5979
+ textTransform: "uppercase",
5980
+ whiteSpace: "nowrap"
5981
+ },
5982
+ children: label
5983
+ }),
5984
+ labelLine2 && /* @__PURE__ */ jsx("span", {
5985
+ style: {
5986
+ fontWeight: 500,
5987
+ fontSize: "0.62em",
5988
+ letterSpacing: "0.03em",
5989
+ lineHeight: 1.1,
5990
+ opacity: 0.85,
5991
+ whiteSpace: "nowrap"
5992
+ },
5993
+ children: labelLine2
5994
+ })
5995
+ ]
5996
+ }),
5997
+ label && /* @__PURE__ */ jsx("div", {
5998
+ style: {
5999
+ width: 3,
6000
+ background: accentColor,
6001
+ flexShrink: 0
6002
+ }
6003
+ }),
6004
+ /* @__PURE__ */ jsx("div", {
6005
+ style: {
6006
+ flex: 1,
6007
+ overflow: "hidden",
6008
+ position: "relative",
6009
+ display: "flex",
6010
+ alignItems: "center"
6011
+ },
6012
+ children: isHorizontal ? /* @__PURE__ */ jsx("div", {
6013
+ style: {
6014
+ display: "inline-flex",
6015
+ whiteSpace: "nowrap",
6016
+ animation: "".concat(animId, " ").concat(durationSec, "s linear infinite"),
6017
+ willChange: "transform"
6018
+ },
6019
+ children: [
6020
+ 0,
6021
+ 1
6022
+ ].map(function(copy) {
6023
+ return /* @__PURE__ */ jsx("span", {
6024
+ style: {
6025
+ paddingRight: "".concat(itemSpacing, "px")
6026
+ },
6027
+ children: segments.map(function(seg, i) {
6028
+ return /* @__PURE__ */ jsxs(React.Fragment, {
6029
+ children: [
6030
+ i > 0 && /* @__PURE__ */ jsx("span", {
6031
+ style: {
6032
+ opacity: 0.5,
6033
+ margin: "0 8px"
6034
+ },
6035
+ children: sep
6036
+ }),
6037
+ /* @__PURE__ */ jsx("span", {
6038
+ style: {
6039
+ textShadow: "0 1px 3px rgba(0,0,0,0.6)"
6040
+ },
6041
+ children: seg
6042
+ })
6043
+ ]
6044
+ }, i);
6045
+ })
6046
+ }, copy);
6047
+ })
6048
+ }) : /* @__PURE__ */ jsx("div", {
6049
+ style: {
6050
+ display: "flex",
6051
+ flexDirection: "column",
6052
+ whiteSpace: "nowrap",
6053
+ animation: "".concat(animId, " ").concat(durationSec, "s linear infinite"),
6054
+ willChange: "transform"
6055
+ },
6056
+ children: [
6057
+ 0,
6058
+ 1
6059
+ ].map(function(copy) {
6060
+ return segments.map(function(seg, i) {
6061
+ return /* @__PURE__ */ jsx("div", {
6062
+ style: {
6063
+ paddingBottom: "".concat(itemSpacing / 4, "px")
6064
+ },
6065
+ children: seg
6066
+ }, "".concat(copy, "-").concat(i));
6067
+ });
6068
+ })
6069
+ })
6070
+ })
6071
+ ]
6072
+ })
6073
+ ]
5803
6074
  })
5804
6075
  ]
5805
6076
  });
@@ -7014,12 +7285,13 @@ var StormcloudVideoPlayerComponent = React2.memo(function(props) {
7014
7285
  var _React2_useState21 = _sliced_to_array(React2.useState(false), 2), showDebugPanel = _React2_useState21[0], setShowDebugPanel = _React2_useState21[1];
7015
7286
  var _React2_useState22 = _sliced_to_array(React2.useState([]), 2), debugMarkers = _React2_useState22[0], setDebugMarkers = _React2_useState22[1];
7016
7287
  var _React2_useState23 = _sliced_to_array(React2.useState(false), 2), showAiPanel = _React2_useState23[0], setShowAiPanel = _React2_useState23[1];
7017
- var _React2_useState24 = _sliced_to_array(React2.useState({
7288
+ var _React2_useState24 = _sliced_to_array(React2.useState(disableAds !== null && disableAds !== void 0 ? disableAds : false), 2), adsDisabled = _React2_useState24[0], setAdsDisabled = _React2_useState24[1];
7289
+ var _React2_useState25 = _sliced_to_array(React2.useState({
7018
7290
  context: null,
7019
7291
  isLoading: false,
7020
7292
  error: null,
7021
7293
  lastPolledAt: null
7022
- }), 2), aiLiveContext = _React2_useState24[0], setAiLiveContext = _React2_useState24[1];
7294
+ }), 2), aiLiveContext = _React2_useState25[0], setAiLiveContext = _React2_useState25[1];
7023
7295
  var getResponsiveScale = function getResponsiveScale() {
7024
7296
  if (viewportWidth < 480) return 0.7;
7025
7297
  if (viewportWidth < 768) return 0.8;
@@ -8506,6 +8778,31 @@ var StormcloudVideoPlayerComponent = React2.memo(function(props) {
8506
8778
  gap: "".concat(8 * responsiveScale, "px")
8507
8779
  },
8508
8780
  children: [
8781
+ /* @__PURE__ */ jsx2("button", {
8782
+ className: "sc-ctrl-btn",
8783
+ onClick: function onClick() {
8784
+ var _playerRef_current;
8785
+ var next = !adsDisabled;
8786
+ setAdsDisabled(next);
8787
+ (_playerRef_current = playerRef.current) === null || _playerRef_current === void 0 ? void 0 : _playerRef_current.setDisableAds(next);
8788
+ resetControlsTimer();
8789
+ },
8790
+ style: {
8791
+ padding: "".concat(8 * responsiveScale, "px"),
8792
+ borderRadius: "50%",
8793
+ minWidth: "".concat(36 * responsiveScale, "px"),
8794
+ minHeight: "".concat(36 * responsiveScale, "px"),
8795
+ background: adsDisabled ? "rgba(239, 68, 68, 0.28)" : "transparent",
8796
+ fontFamily: "'SF Mono', 'Cascadia Code', monospace",
8797
+ fontSize: "".concat(12 * responsiveScale, "px"),
8798
+ fontWeight: 700,
8799
+ letterSpacing: "0.03em",
8800
+ color: adsDisabled ? "rgba(252, 165, 165, 0.9)" : "rgba(255, 255, 255, 0.75)",
8801
+ textDecoration: adsDisabled ? "line-through" : "none"
8802
+ },
8803
+ title: adsDisabled ? "Enable ads" : "Disable ads",
8804
+ children: "AD"
8805
+ }),
8509
8806
  swirlProjectId && /* @__PURE__ */ jsx2("button", {
8510
8807
  className: "sc-ctrl-btn",
8511
8808
  onClick: function onClick() {
@@ -8799,6 +9096,31 @@ var StormcloudVideoPlayerComponent = React2.memo(function(props) {
8799
9096
  })
8800
9097
  ]
8801
9098
  }),
9099
+ /* @__PURE__ */ jsx2("button", {
9100
+ className: "sc-ctrl-btn",
9101
+ onClick: function onClick() {
9102
+ var _playerRef_current;
9103
+ var next = !adsDisabled;
9104
+ setAdsDisabled(next);
9105
+ (_playerRef_current = playerRef.current) === null || _playerRef_current === void 0 ? void 0 : _playerRef_current.setDisableAds(next);
9106
+ resetControlsTimer();
9107
+ },
9108
+ style: {
9109
+ padding: "".concat(8 * responsiveScale, "px"),
9110
+ borderRadius: "50%",
9111
+ minWidth: "".concat(36 * responsiveScale, "px"),
9112
+ minHeight: "".concat(36 * responsiveScale, "px"),
9113
+ background: adsDisabled ? "rgba(239, 68, 68, 0.28)" : "rgba(0, 0, 0, 0.6)",
9114
+ fontFamily: "'SF Mono', 'Cascadia Code', monospace",
9115
+ fontSize: "".concat(12 * responsiveScale, "px"),
9116
+ fontWeight: 700,
9117
+ letterSpacing: "0.03em",
9118
+ color: adsDisabled ? "rgba(252, 165, 165, 0.9)" : "rgba(255, 255, 255, 0.75)",
9119
+ textDecoration: adsDisabled ? "line-through" : "none"
9120
+ },
9121
+ title: adsDisabled ? "Enable ads" : "Disable ads",
9122
+ children: "AD"
9123
+ }),
8802
9124
  swirlProjectId && /* @__PURE__ */ jsx2("button", {
8803
9125
  className: "sc-ctrl-btn",
8804
9126
  onClick: function onClick() {