stormcloud-video-player 0.1.9 → 0.1.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/index.cjs CHANGED
@@ -45,6 +45,7 @@ var import_hls = __toESM(require("hls.js"), 1);
45
45
  // src/sdk/ima.ts
46
46
  function createImaController(video) {
47
47
  let adPlaying = false;
48
+ let originalMutedState = false;
48
49
  const listeners = /* @__PURE__ */ new Map();
49
50
  function emit(event, payload) {
50
51
  const set = listeners.get(event);
@@ -211,6 +212,7 @@ function createImaController(video) {
211
212
  } catch {
212
213
  }
213
214
  adPlaying = false;
215
+ video.muted = originalMutedState;
214
216
  if (adContainerEl)
215
217
  adContainerEl.style.pointerEvents = "none";
216
218
  if (adsLoadedReject) {
@@ -243,6 +245,8 @@ function createImaController(video) {
243
245
  AdEvent.CONTENT_PAUSE_REQUESTED,
244
246
  () => {
245
247
  console.log("[IMA] Content pause requested");
248
+ originalMutedState = video.muted;
249
+ video.muted = true;
246
250
  video.pause();
247
251
  adPlaying = true;
248
252
  if (adContainerEl)
@@ -255,6 +259,7 @@ function createImaController(video) {
255
259
  () => {
256
260
  console.log("[IMA] Content resume requested");
257
261
  adPlaying = false;
262
+ video.muted = originalMutedState;
258
263
  if (adContainerEl)
259
264
  adContainerEl.style.pointerEvents = "none";
260
265
  video.play().catch(() => {
@@ -265,6 +270,7 @@ function createImaController(video) {
265
270
  adsManager.addEventListener(AdEvent.ALL_ADS_COMPLETED, () => {
266
271
  console.log("[IMA] All ads completed");
267
272
  adPlaying = false;
273
+ video.muted = originalMutedState;
268
274
  if (adContainerEl) adContainerEl.style.pointerEvents = "none";
269
275
  video.play().catch(() => {
270
276
  });
@@ -279,6 +285,7 @@ function createImaController(video) {
279
285
  } catch (e) {
280
286
  console.error("[IMA] Error setting up ads manager:", e);
281
287
  adPlaying = false;
288
+ video.muted = originalMutedState;
282
289
  if (adContainerEl) adContainerEl.style.pointerEvents = "none";
283
290
  video.play().catch(() => {
284
291
  });
@@ -351,6 +358,7 @@ function createImaController(video) {
351
358
  },
352
359
  async stop() {
353
360
  adPlaying = false;
361
+ video.muted = originalMutedState;
354
362
  try {
355
363
  adsManager?.stop?.();
356
364
  } catch {
@@ -364,6 +372,7 @@ function createImaController(video) {
364
372
  } catch {
365
373
  }
366
374
  adPlaying = false;
375
+ video.muted = originalMutedState;
367
376
  try {
368
377
  adsLoader?.destroy?.();
369
378
  } catch {
@@ -395,6 +404,32 @@ function createImaController(video) {
395
404
  },
396
405
  off(event, listener) {
397
406
  listeners.get(event)?.delete(listener);
407
+ },
408
+ updateOriginalMutedState(muted) {
409
+ originalMutedState = muted;
410
+ },
411
+ getOriginalMutedState() {
412
+ return originalMutedState;
413
+ },
414
+ setAdVolume(volume) {
415
+ if (adsManager && adPlaying) {
416
+ try {
417
+ adsManager.setVolume(Math.max(0, Math.min(1, volume)));
418
+ } catch (error) {
419
+ console.warn("[IMA] Failed to set ad volume:", error);
420
+ }
421
+ }
422
+ },
423
+ getAdVolume() {
424
+ if (adsManager && adPlaying) {
425
+ try {
426
+ return adsManager.getVolume();
427
+ } catch (error) {
428
+ console.warn("[IMA] Failed to get ad volume:", error);
429
+ return 1;
430
+ }
431
+ }
432
+ return 1;
398
433
  }
399
434
  };
400
435
  }
@@ -1532,9 +1567,22 @@ var StormcloudVideoPlayer = class {
1532
1567
  return void 0;
1533
1568
  }
1534
1569
  toggleMute() {
1535
- this.video.muted = !this.video.muted;
1536
- if (this.config.debugAdTiming) {
1537
- console.log("[StormcloudVideoPlayer] Muted:", this.video.muted);
1570
+ if (this.ima.isAdPlaying()) {
1571
+ const currentPerceptualState = this.isMuted();
1572
+ const newMutedState = !currentPerceptualState;
1573
+ this.ima.updateOriginalMutedState(newMutedState);
1574
+ this.ima.setAdVolume(newMutedState ? 0 : 1);
1575
+ if (this.config.debugAdTiming) {
1576
+ console.log(
1577
+ "[StormcloudVideoPlayer] Mute toggle during ad - immediately applied:",
1578
+ newMutedState
1579
+ );
1580
+ }
1581
+ } else {
1582
+ this.video.muted = !this.video.muted;
1583
+ if (this.config.debugAdTiming) {
1584
+ console.log("[StormcloudVideoPlayer] Muted:", this.video.muted);
1585
+ }
1538
1586
  }
1539
1587
  }
1540
1588
  toggleFullscreen() {
@@ -1575,6 +1623,10 @@ var StormcloudVideoPlayer = class {
1575
1623
  });
1576
1624
  }
1577
1625
  isMuted() {
1626
+ if (this.ima.isAdPlaying()) {
1627
+ const adVolume = this.ima.getAdVolume();
1628
+ return adVolume === 0;
1629
+ }
1578
1630
  return this.video.muted;
1579
1631
  }
1580
1632
  isFullscreen() {
@@ -1655,6 +1707,54 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(
1655
1707
  const [shouldShowNativeControls, setShouldShowNativeControls] = import_react.default.useState(true);
1656
1708
  const [isMuted, setIsMuted] = import_react.default.useState(false);
1657
1709
  const [isFullscreen, setIsFullscreen] = import_react.default.useState(false);
1710
+ const [isPlaying, setIsPlaying] = import_react.default.useState(false);
1711
+ const [currentTime, setCurrentTime] = import_react.default.useState(0);
1712
+ const [duration, setDuration] = import_react.default.useState(0);
1713
+ const [volume, setVolume] = import_react.default.useState(1);
1714
+ const [playbackRate, setPlaybackRate] = import_react.default.useState(1);
1715
+ const [showVolumeSlider, setShowVolumeSlider] = import_react.default.useState(false);
1716
+ const [showSpeedMenu, setShowSpeedMenu] = import_react.default.useState(false);
1717
+ const formatTime = (seconds) => {
1718
+ if (!isFinite(seconds)) return "0:00:00";
1719
+ const hours = Math.floor(seconds / 3600);
1720
+ const minutes = Math.floor(seconds % 3600 / 60);
1721
+ const remainingSeconds = Math.floor(seconds % 60);
1722
+ return `${hours}:${minutes.toString().padStart(2, "0")}:${remainingSeconds.toString().padStart(2, "0")}`;
1723
+ };
1724
+ const handlePlayPause = () => {
1725
+ if (videoRef.current) {
1726
+ if (videoRef.current.paused) {
1727
+ videoRef.current.play();
1728
+ } else {
1729
+ videoRef.current.pause();
1730
+ }
1731
+ }
1732
+ };
1733
+ const handleTimelineSeek = (e) => {
1734
+ if (videoRef.current && duration > 0 && isFinite(duration)) {
1735
+ const rect = e.currentTarget.getBoundingClientRect();
1736
+ const clickX = e.clientX - rect.left;
1737
+ const progress = Math.max(0, Math.min(1, clickX / rect.width));
1738
+ const newTime = progress * duration;
1739
+ if (isFinite(newTime) && newTime >= 0 && newTime <= duration) {
1740
+ videoRef.current.currentTime = newTime;
1741
+ }
1742
+ }
1743
+ };
1744
+ const handleVolumeChange = (newVolume) => {
1745
+ if (videoRef.current && isFinite(newVolume)) {
1746
+ const clampedVolume = Math.max(0, Math.min(1, newVolume));
1747
+ videoRef.current.volume = clampedVolume;
1748
+ videoRef.current.muted = clampedVolume === 0;
1749
+ }
1750
+ };
1751
+ const handlePlaybackRateChange = (rate) => {
1752
+ if (videoRef.current && isFinite(rate) && rate > 0) {
1753
+ videoRef.current.playbackRate = rate;
1754
+ }
1755
+ setShowSpeedMenu(false);
1756
+ };
1757
+ const shouldShowEnhancedControls = allowNativeHls && showCustomControls;
1658
1758
  const criticalPropsKey = (0, import_react.useMemo)(() => {
1659
1759
  return CRITICAL_PROPS.map((prop) => `${prop}:${props[prop]}`).join("|");
1660
1760
  }, [src, allowNativeHls, licenseKey, lowLatencyMode, driftToleranceMs]);
@@ -1751,8 +1851,21 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(
1751
1851
  (0, import_react.useEffect)(() => {
1752
1852
  if (!playerRef.current || !videoRef.current) return;
1753
1853
  const updateStates = () => {
1754
- if (videoRef.current) {
1755
- setIsMuted(videoRef.current.muted);
1854
+ if (playerRef.current && videoRef.current) {
1855
+ setIsMuted(playerRef.current.isMuted());
1856
+ setIsPlaying(!videoRef.current.paused);
1857
+ const currentTimeValue = videoRef.current.currentTime;
1858
+ setCurrentTime(isFinite(currentTimeValue) ? currentTimeValue : 0);
1859
+ const durationValue = videoRef.current.duration;
1860
+ setDuration(isFinite(durationValue) ? durationValue : 0);
1861
+ const volumeValue = videoRef.current.volume;
1862
+ setVolume(
1863
+ isFinite(volumeValue) ? Math.max(0, Math.min(1, volumeValue)) : 1
1864
+ );
1865
+ const rateValue = videoRef.current.playbackRate;
1866
+ setPlaybackRate(
1867
+ isFinite(rateValue) && rateValue > 0 ? rateValue : 1
1868
+ );
1756
1869
  }
1757
1870
  setIsFullscreen(
1758
1871
  document.fullscreenElement === videoRef.current?.parentElement
@@ -1773,387 +1886,919 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(
1773
1886
  );
1774
1887
  };
1775
1888
  }, []);
1776
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1777
- "div",
1778
- {
1779
- className: wrapperClassName,
1780
- style: {
1781
- display: "flex",
1782
- alignItems: "center",
1783
- justifyContent: "center",
1784
- position: isFullscreen ? "fixed" : "relative",
1785
- top: isFullscreen ? 0 : void 0,
1786
- left: isFullscreen ? 0 : void 0,
1787
- overflow: "hidden",
1788
- width: isFullscreen ? "100vw" : "100%",
1789
- height: isFullscreen ? "100vh" : "100%",
1790
- maxWidth: isFullscreen ? "100vw" : "100%",
1791
- maxHeight: isFullscreen ? "100vh" : "100%",
1792
- zIndex: isFullscreen ? 9999 : void 0,
1793
- backgroundColor: isFullscreen ? "#000" : void 0,
1794
- ...wrapperStyle
1795
- },
1796
- children: [
1797
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1798
- "video",
1799
- {
1800
- ref: videoRef,
1801
- className,
1802
- style: {
1803
- display: "block",
1804
- width: "100%",
1805
- height: "100%",
1806
- objectFit: isFullscreen ? "cover" : "contain",
1807
- backgroundColor: "#000",
1808
- ...style
1809
- },
1810
- controls: shouldShowNativeControls && controls && !showCustomControls,
1811
- playsInline,
1812
- preload,
1813
- poster,
1814
- ...restVideoAttrs,
1815
- children
1816
- }
1817
- ),
1818
- adStatus.showAds && adStatus.totalAds > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1819
- "div",
1820
- {
1821
- style: {
1822
- position: "absolute",
1823
- top: "10px",
1824
- right: "10px",
1825
- backgroundColor: "rgba(0, 0, 0, 0.7)",
1826
- color: "white",
1827
- padding: "4px 8px",
1828
- borderRadius: "4px",
1829
- fontSize: "12px",
1830
- fontFamily: "Arial, sans-serif",
1831
- zIndex: 10
1832
- },
1833
- children: [
1834
- "Ad ",
1835
- adStatus.currentIndex,
1836
- "/",
1837
- adStatus.totalAds
1838
- ]
1839
- }
1840
- ),
1841
- showCustomControls && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1842
- "div",
1843
- {
1844
- style: {
1845
- position: "absolute",
1846
- bottom: "10px",
1847
- right: "10px",
1848
- display: "flex",
1849
- gap: "8px",
1850
- zIndex: 10
1851
- },
1852
- children: [
1853
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1854
- "button",
1855
- {
1856
- onClick: () => {
1857
- if (onVolumeToggle) {
1858
- onVolumeToggle();
1859
- } else if (playerRef.current) {
1860
- playerRef.current.toggleMute();
1861
- }
1862
- },
1863
- onMouseEnter: (e) => {
1864
- const target = e.currentTarget;
1865
- target.style.transform = "translateY(-2px) scale(1.05)";
1866
- target.style.boxShadow = "0 6px 20px rgba(0, 0, 0, 0.4), inset 0 1px 0 rgba(255, 255, 255, 0.2)";
1867
- target.style.background = "linear-gradient(135deg, rgba(20, 20, 20, 0.9) 0%, rgba(60, 60, 60, 0.95) 100%)";
1868
- },
1869
- onMouseLeave: (e) => {
1870
- const target = e.currentTarget;
1871
- target.style.transform = "translateY(0) scale(1)";
1872
- target.style.boxShadow = "0 4px 15px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.1)";
1873
- target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.8) 0%, rgba(40, 40, 40, 0.9) 100%)";
1874
- },
1875
- style: {
1876
- background: "linear-gradient(135deg, rgba(0, 0, 0, 0.8) 0%, rgba(40, 40, 40, 0.9) 100%)",
1877
- color: "white",
1878
- border: "1px solid rgba(255, 255, 255, 0.2)",
1879
- borderRadius: "8px",
1880
- padding: "10px",
1881
- cursor: "pointer",
1882
- display: "flex",
1883
- alignItems: "center",
1884
- justifyContent: "center",
1885
- backdropFilter: "blur(10px)",
1886
- boxShadow: "0 4px 15px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.1)",
1887
- transition: "all 0.3s cubic-bezier(0.4, 0, 0.2, 1)"
1888
- },
1889
- title: isMuted ? "Unmute" : "Mute",
1890
- children: isMuted ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1891
- "svg",
1892
- {
1893
- width: "18",
1894
- height: "18",
1895
- viewBox: "0 0 24 24",
1896
- fill: "none",
1897
- xmlns: "http://www.w3.org/2000/svg",
1898
- children: [
1899
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("defs", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1900
- "linearGradient",
1901
- {
1902
- id: "volumeGradient",
1903
- x1: "0%",
1904
- y1: "0%",
1905
- x2: "100%",
1906
- y2: "100%",
1907
- children: [
1908
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("stop", { offset: "0%", stopColor: "#ffffff", stopOpacity: "1" }),
1909
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1910
- "stop",
1911
- {
1912
- offset: "100%",
1913
- stopColor: "#e0e0e0",
1914
- stopOpacity: "0.9"
1915
- }
1916
- )
1917
- ]
1918
- }
1919
- ) }),
1920
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1921
- "path",
1922
- {
1923
- d: "M3 8.5v7c0 .28.22.5.5.5H7l4.29 4.29c.63.63 1.71.18 1.71-.71V4.41c0-.89-1.08-1.34-1.71-.71L7 8H3.5c-.28 0-.5.22-.5.5z",
1924
- fill: "url(#volumeGradient)",
1925
- stroke: "rgba(255,255,255,0.3)",
1926
- strokeWidth: "0.5"
1889
+ (0, import_react.useEffect)(() => {
1890
+ if (!videoRef.current) return;
1891
+ const handleLoadedMetadata = () => {
1892
+ if (videoRef.current) {
1893
+ const video2 = videoRef.current;
1894
+ void video2.offsetHeight;
1895
+ }
1896
+ };
1897
+ const video = videoRef.current;
1898
+ video.addEventListener("loadedmetadata", handleLoadedMetadata);
1899
+ video.addEventListener("loadeddata", handleLoadedMetadata);
1900
+ video.addEventListener("canplay", handleLoadedMetadata);
1901
+ return () => {
1902
+ video.removeEventListener("loadedmetadata", handleLoadedMetadata);
1903
+ video.removeEventListener("loadeddata", handleLoadedMetadata);
1904
+ video.removeEventListener("canplay", handleLoadedMetadata);
1905
+ };
1906
+ }, []);
1907
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
1908
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { children: `
1909
+ .stormcloud-video-wrapper:fullscreen {
1910
+ border-radius: 0 !important;
1911
+ box-shadow: none !important;
1912
+ width: 100vw !important;
1913
+ height: 100vh !important;
1914
+ max-width: 100vw !important;
1915
+ max-height: 100vh !important;
1916
+ position: fixed !important;
1917
+ top: 0 !important;
1918
+ left: 0 !important;
1919
+ z-index: 999999 !important;
1920
+ background: #000 !important;
1921
+ display: flex !important;
1922
+ align-items: center !important;
1923
+ justify-content: center !important;
1924
+ }
1925
+
1926
+ .stormcloud-video-wrapper:has(*:fullscreen) {
1927
+ border-radius: 0 !important;
1928
+ box-shadow: none !important;
1929
+ width: 100vw !important;
1930
+ height: 100vh !important;
1931
+ max-width: 100vw !important;
1932
+ max-height: 100vh !important;
1933
+ position: fixed !important;
1934
+ top: 0 !important;
1935
+ left: 0 !important;
1936
+ z-index: 999999 !important;
1937
+ background: #000 !important;
1938
+ display: flex !important;
1939
+ align-items: center !important;
1940
+ justify-content: center !important;
1941
+ }
1942
+
1943
+ *:fullscreen {
1944
+ width: 100vw !important;
1945
+ height: 100vh !important;
1946
+ max-width: 100vw !important;
1947
+ max-height: 100vh !important;
1948
+ position: fixed !important;
1949
+ top: 0 !important;
1950
+ left: 0 !important;
1951
+ z-index: 999999 !important;
1952
+ background: #000 !important;
1953
+ }
1954
+ ` }),
1955
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1956
+ "div",
1957
+ {
1958
+ className: `stormcloud-video-wrapper ${wrapperClassName || ""}`,
1959
+ style: {
1960
+ display: "flex",
1961
+ alignItems: "center",
1962
+ justifyContent: "center",
1963
+ position: isFullscreen ? "fixed" : "relative",
1964
+ top: isFullscreen ? 0 : void 0,
1965
+ left: isFullscreen ? 0 : void 0,
1966
+ overflow: "hidden",
1967
+ width: isFullscreen ? "100vw" : "100%",
1968
+ height: isFullscreen ? "100vh" : "auto",
1969
+ minHeight: isFullscreen ? "100vh" : "auto",
1970
+ maxWidth: isFullscreen ? "100vw" : "100%",
1971
+ maxHeight: isFullscreen ? "100vh" : "none",
1972
+ zIndex: isFullscreen ? 999999 : void 0,
1973
+ backgroundColor: isFullscreen ? "#000" : void 0,
1974
+ borderRadius: isFullscreen ? 0 : void 0,
1975
+ boxShadow: isFullscreen ? "none" : void 0,
1976
+ ...wrapperStyle
1977
+ },
1978
+ children: [
1979
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1980
+ "video",
1981
+ {
1982
+ ref: videoRef,
1983
+ className,
1984
+ style: {
1985
+ display: "block",
1986
+ width: "100%",
1987
+ height: isFullscreen ? "100%" : "auto",
1988
+ maxWidth: "100%",
1989
+ maxHeight: isFullscreen ? "100%" : "none",
1990
+ objectFit: isFullscreen ? "cover" : "contain",
1991
+ backgroundColor: "#000",
1992
+ aspectRatio: isFullscreen ? "unset" : void 0,
1993
+ ...style
1994
+ },
1995
+ controls: shouldShowNativeControls && controls && !showCustomControls,
1996
+ playsInline,
1997
+ preload,
1998
+ poster,
1999
+ ...restVideoAttrs,
2000
+ children
2001
+ }
2002
+ ),
2003
+ adStatus.showAds && adStatus.totalAds > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
2004
+ "div",
2005
+ {
2006
+ style: {
2007
+ position: "absolute",
2008
+ top: "10px",
2009
+ right: "10px",
2010
+ backgroundColor: "rgba(0, 0, 0, 0.7)",
2011
+ color: "white",
2012
+ padding: "4px 8px",
2013
+ borderRadius: "4px",
2014
+ fontSize: "12px",
2015
+ fontFamily: "Arial, sans-serif",
2016
+ zIndex: 10
2017
+ },
2018
+ children: [
2019
+ "Ad ",
2020
+ adStatus.currentIndex,
2021
+ "/",
2022
+ adStatus.totalAds
2023
+ ]
2024
+ }
2025
+ ),
2026
+ shouldShowEnhancedControls ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
2027
+ "div",
2028
+ {
2029
+ style: {
2030
+ position: "absolute",
2031
+ bottom: 0,
2032
+ left: 0,
2033
+ right: 0,
2034
+ background: "linear-gradient(180deg, transparent 0%, rgba(0, 0, 0, 0.8) 100%)",
2035
+ padding: "20px 16px 16px",
2036
+ zIndex: 10
2037
+ },
2038
+ children: [
2039
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
2040
+ "div",
2041
+ {
2042
+ style: {
2043
+ width: "100%",
2044
+ height: "6px",
2045
+ backgroundColor: "rgba(255, 255, 255, 0.3)",
2046
+ borderRadius: "3px",
2047
+ marginBottom: "12px",
2048
+ cursor: "pointer",
2049
+ position: "relative"
2050
+ },
2051
+ onClick: handleTimelineSeek,
2052
+ children: [
2053
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2054
+ "div",
2055
+ {
2056
+ style: {
2057
+ height: "100%",
2058
+ backgroundColor: "#ff4444",
2059
+ borderRadius: "3px",
2060
+ width: `${duration > 0 ? currentTime / duration * 100 : 0}%`,
2061
+ transition: "width 0.1s ease"
1927
2062
  }
1928
- ),
1929
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1930
- "path",
1931
- {
1932
- d: "M16.5 8.5l-1.41-1.41L12 10.18 8.91 7.09 7.5 8.5l3.09 3.09L7.5 14.68l1.41 1.41L12 13l3.09 3.09 1.41-1.41L13.41 12l3.09-3.5z",
1933
- fill: "#ff4444",
1934
- stroke: "rgba(255,255,255,0.5)",
1935
- strokeWidth: "0.5"
2063
+ }
2064
+ ),
2065
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2066
+ "div",
2067
+ {
2068
+ style: {
2069
+ position: "absolute",
2070
+ top: "-4px",
2071
+ right: `${duration > 0 ? 100 - currentTime / duration * 100 : 100}%`,
2072
+ width: "14px",
2073
+ height: "14px",
2074
+ backgroundColor: "#ff4444",
2075
+ borderRadius: "50%",
2076
+ border: "2px solid white",
2077
+ boxShadow: "0 2px 6px rgba(0, 0, 0, 0.3)",
2078
+ transform: "translateX(50%)"
1936
2079
  }
1937
- )
1938
- ]
1939
- }
1940
- ) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1941
- "svg",
1942
- {
1943
- width: "18",
1944
- height: "18",
1945
- viewBox: "0 0 24 24",
1946
- fill: "none",
1947
- xmlns: "http://www.w3.org/2000/svg",
1948
- children: [
1949
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("defs", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1950
- "linearGradient",
1951
- {
1952
- id: "volumeGradient",
1953
- x1: "0%",
1954
- y1: "0%",
1955
- x2: "100%",
1956
- y2: "100%",
1957
- children: [
1958
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("stop", { offset: "0%", stopColor: "#ffffff", stopOpacity: "1" }),
1959
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1960
- "stop",
2080
+ }
2081
+ )
2082
+ ]
2083
+ }
2084
+ ),
2085
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
2086
+ "div",
2087
+ {
2088
+ style: {
2089
+ display: "flex",
2090
+ alignItems: "center",
2091
+ justifyContent: "space-between",
2092
+ color: "white"
2093
+ },
2094
+ children: [
2095
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
2096
+ "div",
2097
+ {
2098
+ style: {
2099
+ display: "flex",
2100
+ alignItems: "center",
2101
+ gap: "12px"
2102
+ },
2103
+ children: [
2104
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2105
+ "button",
2106
+ {
2107
+ onClick: handlePlayPause,
2108
+ style: {
2109
+ background: "transparent",
2110
+ border: "none",
2111
+ color: "white",
2112
+ cursor: "pointer",
2113
+ padding: "8px",
2114
+ borderRadius: "4px",
2115
+ display: "flex",
2116
+ alignItems: "center",
2117
+ justifyContent: "center",
2118
+ transition: "background-color 0.2s"
2119
+ },
2120
+ onMouseEnter: (e) => {
2121
+ e.target.style.backgroundColor = "rgba(255, 255, 255, 0.1)";
2122
+ },
2123
+ onMouseLeave: (e) => {
2124
+ e.target.style.backgroundColor = "transparent";
2125
+ },
2126
+ title: isPlaying ? "Pause" : "Play",
2127
+ children: isPlaying ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2128
+ "svg",
2129
+ {
2130
+ width: "24",
2131
+ height: "24",
2132
+ viewBox: "0 0 24 24",
2133
+ fill: "currentColor",
2134
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M6 4h4v16H6V4zm8 0h4v16h-4V4z" })
2135
+ }
2136
+ ) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2137
+ "svg",
2138
+ {
2139
+ width: "24",
2140
+ height: "24",
2141
+ viewBox: "0 0 24 24",
2142
+ fill: "currentColor",
2143
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M8 5v14l11-7z" })
2144
+ }
2145
+ )
2146
+ }
2147
+ ),
2148
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
2149
+ "div",
2150
+ {
2151
+ style: {
2152
+ position: "relative",
2153
+ display: "flex",
2154
+ alignItems: "center"
2155
+ },
2156
+ onMouseEnter: () => setShowVolumeSlider(true),
2157
+ onMouseLeave: () => setShowVolumeSlider(false),
2158
+ children: [
2159
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2160
+ "button",
2161
+ {
2162
+ onClick: () => {
2163
+ if (onVolumeToggle) {
2164
+ onVolumeToggle();
2165
+ } else if (playerRef.current) {
2166
+ playerRef.current.toggleMute();
2167
+ }
2168
+ },
2169
+ style: {
2170
+ background: "transparent",
2171
+ border: "none",
2172
+ color: "white",
2173
+ cursor: "pointer",
2174
+ padding: "8px",
2175
+ borderRadius: "4px",
2176
+ display: "flex",
2177
+ alignItems: "center",
2178
+ justifyContent: "center",
2179
+ transition: "background-color 0.2s"
2180
+ },
2181
+ onMouseEnter: (e) => {
2182
+ e.target.style.backgroundColor = "rgba(255, 255, 255, 0.1)";
2183
+ },
2184
+ onMouseLeave: (e) => {
2185
+ e.target.style.backgroundColor = "transparent";
2186
+ },
2187
+ title: isMuted ? "Unmute" : "Mute",
2188
+ children: isMuted || volume === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
2189
+ "svg",
2190
+ {
2191
+ width: "20",
2192
+ height: "20",
2193
+ viewBox: "0 0 24 24",
2194
+ fill: "currentColor",
2195
+ children: [
2196
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M3 8.5v7c0 .28.22.5.5.5H7l4.29 4.29c.63.63 1.71.18 1.71-.71V4.41c0-.89-1.08-1.34-1.71-.71L7 8H3.5c-.28 0-.5.22-.5.5z" }),
2197
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2198
+ "path",
2199
+ {
2200
+ d: "M16.5 8.5l-1.41-1.41L12 10.18 8.91 7.09 7.5 8.5l3.09 3.09L7.5 14.68l1.41 1.41L12 13l3.09 3.09 1.41-1.41L13.41 12l3.09-3.5z",
2201
+ fill: "#ff4444"
2202
+ }
2203
+ )
2204
+ ]
2205
+ }
2206
+ ) : volume < 0.5 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
2207
+ "svg",
2208
+ {
2209
+ width: "20",
2210
+ height: "20",
2211
+ viewBox: "0 0 24 24",
2212
+ fill: "currentColor",
2213
+ children: [
2214
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M3 8.5v7c0 .28.22.5.5.5H7l4.29 4.29c.63.63 1.71.18 1.71-.71V4.41c0-.89-1.08-1.34-1.71-.71L7 8H3.5c-.28 0-.5.22-.5.5z" }),
2215
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2216
+ "path",
2217
+ {
2218
+ d: "M15.5 12c0-1.33-.58-2.53-1.5-3.35v6.69c.92-.81 1.5-2.01 1.5-3.34z",
2219
+ opacity: "0.8"
2220
+ }
2221
+ )
2222
+ ]
2223
+ }
2224
+ ) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
2225
+ "svg",
2226
+ {
2227
+ width: "20",
2228
+ height: "20",
2229
+ viewBox: "0 0 24 24",
2230
+ fill: "currentColor",
2231
+ children: [
2232
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M3 8.5v7c0 .28.22.5.5.5H7l4.29 4.29c.63.63 1.71.18 1.71-.71V4.41c0-.89-1.08-1.34-1.71-.71L7 8H3.5c-.28 0-.5.22-.5.5z" }),
2233
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2234
+ "path",
2235
+ {
2236
+ d: "M15.5 12c0-1.33-.58-2.53-1.5-3.35v6.69c.92-.81 1.5-2.01 1.5-3.34z",
2237
+ opacity: "0.8"
2238
+ }
2239
+ ),
2240
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2241
+ "path",
2242
+ {
2243
+ d: "M14 4.45v1.75c2.01.91 3.5 3.02 3.5 5.3 0 2.28-1.49 4.39-3.5 5.3v1.75c2.89-.86 5-3.54 5-7.05s-2.11-6.19-5-7.05z",
2244
+ opacity: "0.6"
2245
+ }
2246
+ )
2247
+ ]
2248
+ }
2249
+ )
2250
+ }
2251
+ ),
2252
+ showVolumeSlider && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2253
+ "div",
2254
+ {
2255
+ style: {
2256
+ position: "absolute",
2257
+ bottom: "100%",
2258
+ left: "50%",
2259
+ transform: "translateX(-50%)",
2260
+ marginBottom: "8px",
2261
+ background: "rgba(0, 0, 0, 0.9)",
2262
+ padding: "8px",
2263
+ borderRadius: "4px",
2264
+ display: "flex",
2265
+ flexDirection: "column",
2266
+ alignItems: "center",
2267
+ height: "100px"
2268
+ },
2269
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2270
+ "input",
2271
+ {
2272
+ type: "range",
2273
+ min: "0",
2274
+ max: "1",
2275
+ step: "0.01",
2276
+ value: isMuted ? 0 : volume,
2277
+ onChange: (e) => handleVolumeChange(parseFloat(e.target.value)),
2278
+ style: {
2279
+ writingMode: "bt-lr",
2280
+ WebkitAppearance: "slider-vertical",
2281
+ width: "4px",
2282
+ height: "80px",
2283
+ background: "rgba(255, 255, 255, 0.3)",
2284
+ outline: "none"
2285
+ }
2286
+ }
2287
+ )
2288
+ }
2289
+ )
2290
+ ]
2291
+ }
2292
+ ),
2293
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
2294
+ "div",
2295
+ {
2296
+ style: {
2297
+ fontSize: "14px",
2298
+ fontFamily: "monospace",
2299
+ color: "rgba(255, 255, 255, 0.9)"
2300
+ },
2301
+ children: [
2302
+ formatTime(currentTime),
2303
+ " / ",
2304
+ formatTime(duration)
2305
+ ]
2306
+ }
2307
+ )
2308
+ ]
2309
+ }
2310
+ ),
2311
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
2312
+ "div",
2313
+ {
2314
+ style: {
2315
+ display: "flex",
2316
+ alignItems: "center",
2317
+ gap: "12px"
2318
+ },
2319
+ children: [
2320
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { position: "relative" }, children: [
2321
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
2322
+ "button",
1961
2323
  {
1962
- offset: "100%",
1963
- stopColor: "#e0e0e0",
1964
- stopOpacity: "0.9"
2324
+ onClick: () => setShowSpeedMenu(!showSpeedMenu),
2325
+ style: {
2326
+ background: "transparent",
2327
+ border: "none",
2328
+ color: "white",
2329
+ cursor: "pointer",
2330
+ padding: "8px 12px",
2331
+ borderRadius: "4px",
2332
+ fontSize: "14px",
2333
+ fontFamily: "monospace",
2334
+ transition: "background-color 0.2s"
2335
+ },
2336
+ onMouseEnter: (e) => {
2337
+ e.target.style.backgroundColor = "rgba(255, 255, 255, 0.1)";
2338
+ },
2339
+ onMouseLeave: (e) => {
2340
+ e.target.style.backgroundColor = "transparent";
2341
+ },
2342
+ title: "Playback Speed",
2343
+ children: [
2344
+ playbackRate,
2345
+ "x"
2346
+ ]
2347
+ }
2348
+ ),
2349
+ showSpeedMenu && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2350
+ "div",
2351
+ {
2352
+ style: {
2353
+ position: "absolute",
2354
+ bottom: "100%",
2355
+ right: 0,
2356
+ marginBottom: "8px",
2357
+ background: "rgba(0, 0, 0, 0.9)",
2358
+ borderRadius: "4px",
2359
+ overflow: "hidden",
2360
+ minWidth: "80px"
2361
+ },
2362
+ children: [0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2].map(
2363
+ (speed) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
2364
+ "button",
2365
+ {
2366
+ onClick: () => handlePlaybackRateChange(speed),
2367
+ style: {
2368
+ display: "block",
2369
+ width: "100%",
2370
+ padding: "8px 12px",
2371
+ background: playbackRate === speed ? "rgba(255, 68, 68, 0.8)" : "transparent",
2372
+ border: "none",
2373
+ color: "white",
2374
+ cursor: "pointer",
2375
+ fontSize: "14px",
2376
+ fontFamily: "monospace",
2377
+ textAlign: "left",
2378
+ transition: "background-color 0.2s"
2379
+ },
2380
+ onMouseEnter: (e) => {
2381
+ if (playbackRate !== speed) {
2382
+ e.target.style.backgroundColor = "rgba(255, 255, 255, 0.1)";
2383
+ }
2384
+ },
2385
+ onMouseLeave: (e) => {
2386
+ if (playbackRate !== speed) {
2387
+ e.target.style.backgroundColor = "transparent";
2388
+ }
2389
+ },
2390
+ children: [
2391
+ speed,
2392
+ "x"
2393
+ ]
2394
+ },
2395
+ speed
2396
+ )
2397
+ )
1965
2398
  }
1966
2399
  )
1967
- ]
1968
- }
1969
- ) }),
1970
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1971
- "path",
1972
- {
1973
- d: "M3 8.5v7c0 .28.22.5.5.5H7l4.29 4.29c.63.63 1.71.18 1.71-.71V4.41c0-.89-1.08-1.34-1.71-.71L7 8H3.5c-.28 0-.5.22-.5.5z",
1974
- fill: "url(#volumeGradient)",
1975
- stroke: "rgba(255,255,255,0.3)",
1976
- strokeWidth: "0.5"
1977
- }
1978
- ),
1979
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1980
- "path",
1981
- {
1982
- d: "M15.5 12c0-1.33-.58-2.53-1.5-3.35v6.69c.92-.81 1.5-2.01 1.5-3.34z",
1983
- fill: "url(#volumeGradient)",
1984
- opacity: "0.8"
1985
- }
1986
- ),
1987
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1988
- "path",
1989
- {
1990
- d: "M14 4.45v1.75c2.01.91 3.5 3.02 3.5 5.3 0 2.28-1.49 4.39-3.5 5.3v1.75c2.89-.86 5-3.54 5-7.05s-2.11-6.19-5-7.05z",
1991
- fill: "url(#volumeGradient)",
1992
- opacity: "0.6"
1993
- }
1994
- )
1995
- ]
1996
- }
1997
- )
1998
- }
1999
- ),
2000
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2001
- "button",
2002
- {
2003
- onClick: () => {
2004
- if (onFullscreenToggle) {
2005
- onFullscreenToggle();
2006
- } else if (playerRef.current) {
2007
- playerRef.current.toggleFullscreen().catch((err) => {
2008
- console.error("Fullscreen error:", err);
2009
- });
2010
- }
2011
- },
2012
- onMouseEnter: (e) => {
2013
- const target = e.currentTarget;
2014
- target.style.transform = "translateY(-2px) scale(1.05)";
2015
- target.style.boxShadow = "0 6px 20px rgba(0, 0, 0, 0.4), inset 0 1px 0 rgba(255, 255, 255, 0.2)";
2016
- target.style.background = "linear-gradient(135deg, rgba(20, 20, 20, 0.9) 0%, rgba(60, 60, 60, 0.95) 100%)";
2017
- },
2018
- onMouseLeave: (e) => {
2019
- const target = e.currentTarget;
2020
- target.style.transform = "translateY(0) scale(1)";
2021
- target.style.boxShadow = "0 4px 15px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.1)";
2022
- target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.8) 0%, rgba(40, 40, 40, 0.9) 100%)";
2023
- },
2024
- style: {
2025
- background: "linear-gradient(135deg, rgba(0, 0, 0, 0.8) 0%, rgba(40, 40, 40, 0.9) 100%)",
2026
- color: "white",
2027
- border: "1px solid rgba(255, 255, 255, 0.2)",
2028
- borderRadius: "8px",
2029
- padding: "10px",
2030
- cursor: "pointer",
2031
- display: "flex",
2032
- alignItems: "center",
2033
- justifyContent: "center",
2034
- backdropFilter: "blur(10px)",
2035
- boxShadow: "0 4px 15px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.1)",
2036
- transition: "all 0.3s cubic-bezier(0.4, 0, 0.2, 1)"
2037
- },
2038
- title: isFullscreen ? "Exit Fullscreen" : "Enter Fullscreen",
2039
- children: isFullscreen ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
2040
- "svg",
2041
- {
2042
- width: "20",
2043
- height: "20",
2044
- viewBox: "0 0 24 24",
2045
- fill: "none",
2046
- xmlns: "http://www.w3.org/2000/svg",
2047
- children: [
2048
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2049
- "path",
2050
- {
2051
- d: "M8 8h3v3l-1-1-2 2-1.5-1.5L8.5 8.5 8 8z",
2052
- fill: "white",
2053
- stroke: "rgba(255,255,255,0.8)",
2054
- strokeWidth: "0.5"
2055
- }
2056
- ),
2057
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2058
- "path",
2059
- {
2060
- d: "M16 8h-3v3l1-1 2 2 1.5-1.5L15.5 8.5 16 8z",
2061
- fill: "white",
2062
- stroke: "rgba(255,255,255,0.8)",
2063
- strokeWidth: "0.5"
2064
- }
2065
- ),
2066
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2067
- "path",
2068
- {
2069
- d: "M8 16h3v-3l-1 1-2-2-1.5 1.5L8.5 15.5 8 16z",
2070
- fill: "white",
2071
- stroke: "rgba(255,255,255,0.8)",
2072
- strokeWidth: "0.5"
2073
- }
2074
- ),
2075
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2076
- "path",
2077
- {
2078
- d: "M16 16h-3v-3l1 1 2-2 1.5 1.5L15.5 15.5 16 16z",
2079
- fill: "white",
2080
- stroke: "rgba(255,255,255,0.8)",
2081
- strokeWidth: "0.5"
2082
- }
2083
- )
2084
- ]
2085
- }
2086
- ) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
2087
- "svg",
2088
- {
2089
- width: "20",
2090
- height: "20",
2091
- viewBox: "0 0 24 24",
2092
- fill: "none",
2093
- xmlns: "http://www.w3.org/2000/svg",
2094
- children: [
2095
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2096
- "path",
2097
- {
2098
- d: "M3 3h6v2H5v4H3V3z",
2099
- fill: "white",
2100
- stroke: "rgba(255,255,255,0.8)",
2101
- strokeWidth: "0.5"
2102
- }
2103
- ),
2104
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2105
- "path",
2106
- {
2107
- d: "M21 3h-6v2h4v4h2V3z",
2108
- fill: "white",
2109
- stroke: "rgba(255,255,255,0.8)",
2110
- strokeWidth: "0.5"
2111
- }
2112
- ),
2113
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2114
- "path",
2115
- {
2116
- d: "M3 21v-6h2v4h4v2H3z",
2117
- fill: "white",
2118
- stroke: "rgba(255,255,255,0.8)",
2119
- strokeWidth: "0.5"
2120
- }
2121
- ),
2122
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2123
- "path",
2124
- {
2125
- d: "M21 21h-6v-2h4v-4h2v6z",
2126
- fill: "white",
2127
- stroke: "rgba(255,255,255,0.8)",
2128
- strokeWidth: "0.5"
2129
- }
2130
- )
2131
- ]
2132
- }
2133
- )
2134
- }
2135
- )
2136
- ]
2137
- }
2138
- ),
2139
- onControlClick && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2140
- "div",
2141
- {
2142
- onClick: onControlClick,
2143
- style: {
2144
- position: "absolute",
2145
- top: 0,
2146
- left: 0,
2147
- right: 0,
2148
- bottom: 0,
2149
- zIndex: 1,
2150
- cursor: "pointer"
2400
+ ] }),
2401
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2402
+ "button",
2403
+ {
2404
+ onClick: () => {
2405
+ if (onFullscreenToggle) {
2406
+ onFullscreenToggle();
2407
+ } else if (playerRef.current) {
2408
+ playerRef.current.toggleFullscreen().catch((err) => {
2409
+ console.error("Fullscreen error:", err);
2410
+ });
2411
+ }
2412
+ },
2413
+ style: {
2414
+ background: "transparent",
2415
+ border: "none",
2416
+ color: "white",
2417
+ cursor: "pointer",
2418
+ padding: "8px",
2419
+ borderRadius: "4px",
2420
+ display: "flex",
2421
+ alignItems: "center",
2422
+ justifyContent: "center",
2423
+ transition: "background-color 0.2s"
2424
+ },
2425
+ onMouseEnter: (e) => {
2426
+ e.target.style.backgroundColor = "rgba(255, 255, 255, 0.1)";
2427
+ },
2428
+ onMouseLeave: (e) => {
2429
+ e.target.style.backgroundColor = "transparent";
2430
+ },
2431
+ title: isFullscreen ? "Exit Fullscreen" : "Enter Fullscreen",
2432
+ children: isFullscreen ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
2433
+ "svg",
2434
+ {
2435
+ width: "20",
2436
+ height: "20",
2437
+ viewBox: "0 0 24 24",
2438
+ fill: "currentColor",
2439
+ children: [
2440
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M8 8h3v3l-1-1-2 2-1.5-1.5L8.5 8.5 8 8z" }),
2441
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M16 8h-3v3l1-1 2 2 1.5-1.5L15.5 8.5 16 8z" }),
2442
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M8 16h3v-3l-1 1-2-2-1.5 1.5L8.5 15.5 8 16z" }),
2443
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M16 16h-3v-3l1 1 2-2 1.5 1.5L15.5 15.5 16 16z" })
2444
+ ]
2445
+ }
2446
+ ) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
2447
+ "svg",
2448
+ {
2449
+ width: "20",
2450
+ height: "20",
2451
+ viewBox: "0 0 24 24",
2452
+ fill: "currentColor",
2453
+ children: [
2454
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M3 3h6v2H5v4H3V3z" }),
2455
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M21 3h-6v2h4v4h2V3z" }),
2456
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M3 21v-6h2v4h4v2H3z" }),
2457
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M21 21h-6v-2h4v-4h2v6z" })
2458
+ ]
2459
+ }
2460
+ )
2461
+ }
2462
+ )
2463
+ ]
2464
+ }
2465
+ )
2466
+ ]
2467
+ }
2468
+ )
2469
+ ]
2151
2470
  }
2152
- }
2153
- )
2154
- ]
2155
- }
2156
- );
2471
+ ) }) : showCustomControls && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
2472
+ "div",
2473
+ {
2474
+ style: {
2475
+ position: "absolute",
2476
+ bottom: "10px",
2477
+ right: "10px",
2478
+ display: "flex",
2479
+ gap: "8px",
2480
+ zIndex: 10
2481
+ },
2482
+ children: [
2483
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2484
+ "button",
2485
+ {
2486
+ onClick: () => {
2487
+ if (onVolumeToggle) {
2488
+ onVolumeToggle();
2489
+ } else if (playerRef.current) {
2490
+ playerRef.current.toggleMute();
2491
+ }
2492
+ },
2493
+ onMouseEnter: (e) => {
2494
+ const target = e.currentTarget;
2495
+ target.style.transform = "translateY(-2px) scale(1.05)";
2496
+ target.style.boxShadow = "0 6px 20px rgba(0, 0, 0, 0.4), inset 0 1px 0 rgba(255, 255, 255, 0.2)";
2497
+ target.style.background = "linear-gradient(135deg, rgba(20, 20, 20, 0.9) 0%, rgba(60, 60, 60, 0.95) 100%)";
2498
+ },
2499
+ onMouseLeave: (e) => {
2500
+ const target = e.currentTarget;
2501
+ target.style.transform = "translateY(0) scale(1)";
2502
+ target.style.boxShadow = "0 4px 15px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.1)";
2503
+ target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.8) 0%, rgba(40, 40, 40, 0.9) 100%)";
2504
+ },
2505
+ style: {
2506
+ background: "linear-gradient(135deg, rgba(0, 0, 0, 0.8) 0%, rgba(40, 40, 40, 0.9) 100%)",
2507
+ color: "white",
2508
+ border: "1px solid rgba(255, 255, 255, 0.2)",
2509
+ borderRadius: "8px",
2510
+ padding: "10px",
2511
+ cursor: "pointer",
2512
+ display: "flex",
2513
+ alignItems: "center",
2514
+ justifyContent: "center",
2515
+ backdropFilter: "blur(10px)",
2516
+ boxShadow: "0 4px 15px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.1)",
2517
+ transition: "all 0.3s cubic-bezier(0.4, 0, 0.2, 1)"
2518
+ },
2519
+ title: isMuted ? "Unmute" : "Mute",
2520
+ children: isMuted ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
2521
+ "svg",
2522
+ {
2523
+ width: "18",
2524
+ height: "18",
2525
+ viewBox: "0 0 24 24",
2526
+ fill: "none",
2527
+ xmlns: "http://www.w3.org/2000/svg",
2528
+ children: [
2529
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("defs", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
2530
+ "linearGradient",
2531
+ {
2532
+ id: "volumeGradient",
2533
+ x1: "0%",
2534
+ y1: "0%",
2535
+ x2: "100%",
2536
+ y2: "100%",
2537
+ children: [
2538
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2539
+ "stop",
2540
+ {
2541
+ offset: "0%",
2542
+ stopColor: "#ffffff",
2543
+ stopOpacity: "1"
2544
+ }
2545
+ ),
2546
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2547
+ "stop",
2548
+ {
2549
+ offset: "100%",
2550
+ stopColor: "#e0e0e0",
2551
+ stopOpacity: "0.9"
2552
+ }
2553
+ )
2554
+ ]
2555
+ }
2556
+ ) }),
2557
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2558
+ "path",
2559
+ {
2560
+ d: "M3 8.5v7c0 .28.22.5.5.5H7l4.29 4.29c.63.63 1.71.18 1.71-.71V4.41c0-.89-1.08-1.34-1.71-.71L7 8H3.5c-.28 0-.5.22-.5.5z",
2561
+ fill: "url(#volumeGradient)",
2562
+ stroke: "rgba(255,255,255,0.3)",
2563
+ strokeWidth: "0.5"
2564
+ }
2565
+ ),
2566
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2567
+ "path",
2568
+ {
2569
+ d: "M16.5 8.5l-1.41-1.41L12 10.18 8.91 7.09 7.5 8.5l3.09 3.09L7.5 14.68l1.41 1.41L12 13l3.09 3.09 1.41-1.41L13.41 12l3.09-3.5z",
2570
+ fill: "#ff4444",
2571
+ stroke: "rgba(255,255,255,0.5)",
2572
+ strokeWidth: "0.5"
2573
+ }
2574
+ )
2575
+ ]
2576
+ }
2577
+ ) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
2578
+ "svg",
2579
+ {
2580
+ width: "18",
2581
+ height: "18",
2582
+ viewBox: "0 0 24 24",
2583
+ fill: "none",
2584
+ xmlns: "http://www.w3.org/2000/svg",
2585
+ children: [
2586
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("defs", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
2587
+ "linearGradient",
2588
+ {
2589
+ id: "volumeGradient",
2590
+ x1: "0%",
2591
+ y1: "0%",
2592
+ x2: "100%",
2593
+ y2: "100%",
2594
+ children: [
2595
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2596
+ "stop",
2597
+ {
2598
+ offset: "0%",
2599
+ stopColor: "#ffffff",
2600
+ stopOpacity: "1"
2601
+ }
2602
+ ),
2603
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2604
+ "stop",
2605
+ {
2606
+ offset: "100%",
2607
+ stopColor: "#e0e0e0",
2608
+ stopOpacity: "0.9"
2609
+ }
2610
+ )
2611
+ ]
2612
+ }
2613
+ ) }),
2614
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2615
+ "path",
2616
+ {
2617
+ d: "M3 8.5v7c0 .28.22.5.5.5H7l4.29 4.29c.63.63 1.71.18 1.71-.71V4.41c0-.89-1.08-1.34-1.71-.71L7 8H3.5c-.28 0-.5.22-.5.5z",
2618
+ fill: "url(#volumeGradient)",
2619
+ stroke: "rgba(255,255,255,0.3)",
2620
+ strokeWidth: "0.5"
2621
+ }
2622
+ ),
2623
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2624
+ "path",
2625
+ {
2626
+ d: "M15.5 12c0-1.33-.58-2.53-1.5-3.35v6.69c.92-.81 1.5-2.01 1.5-3.34z",
2627
+ fill: "url(#volumeGradient)",
2628
+ opacity: "0.8"
2629
+ }
2630
+ ),
2631
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2632
+ "path",
2633
+ {
2634
+ d: "M14 4.45v1.75c2.01.91 3.5 3.02 3.5 5.3 0 2.28-1.49 4.39-3.5 5.3v1.75c2.89-.86 5-3.54 5-7.05s-2.11-6.19-5-7.05z",
2635
+ fill: "url(#volumeGradient)",
2636
+ opacity: "0.6"
2637
+ }
2638
+ )
2639
+ ]
2640
+ }
2641
+ )
2642
+ }
2643
+ ),
2644
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2645
+ "button",
2646
+ {
2647
+ onClick: () => {
2648
+ if (onFullscreenToggle) {
2649
+ onFullscreenToggle();
2650
+ } else if (playerRef.current) {
2651
+ playerRef.current.toggleFullscreen().catch((err) => {
2652
+ console.error("Fullscreen error:", err);
2653
+ });
2654
+ }
2655
+ },
2656
+ onMouseEnter: (e) => {
2657
+ const target = e.currentTarget;
2658
+ target.style.transform = "translateY(-2px) scale(1.05)";
2659
+ target.style.boxShadow = "0 6px 20px rgba(0, 0, 0, 0.4), inset 0 1px 0 rgba(255, 255, 255, 0.2)";
2660
+ target.style.background = "linear-gradient(135deg, rgba(20, 20, 20, 0.9) 0%, rgba(60, 60, 60, 0.95) 100%)";
2661
+ },
2662
+ onMouseLeave: (e) => {
2663
+ const target = e.currentTarget;
2664
+ target.style.transform = "translateY(0) scale(1)";
2665
+ target.style.boxShadow = "0 4px 15px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.1)";
2666
+ target.style.background = "linear-gradient(135deg, rgba(0, 0, 0, 0.8) 0%, rgba(40, 40, 40, 0.9) 100%)";
2667
+ },
2668
+ style: {
2669
+ background: "linear-gradient(135deg, rgba(0, 0, 0, 0.8) 0%, rgba(40, 40, 40, 0.9) 100%)",
2670
+ color: "white",
2671
+ border: "1px solid rgba(255, 255, 255, 0.2)",
2672
+ borderRadius: "8px",
2673
+ padding: "10px",
2674
+ cursor: "pointer",
2675
+ display: "flex",
2676
+ alignItems: "center",
2677
+ justifyContent: "center",
2678
+ backdropFilter: "blur(10px)",
2679
+ boxShadow: "0 4px 15px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.1)",
2680
+ transition: "all 0.3s cubic-bezier(0.4, 0, 0.2, 1)"
2681
+ },
2682
+ title: isFullscreen ? "Exit Fullscreen" : "Enter Fullscreen",
2683
+ children: isFullscreen ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
2684
+ "svg",
2685
+ {
2686
+ width: "20",
2687
+ height: "20",
2688
+ viewBox: "0 0 24 24",
2689
+ fill: "none",
2690
+ xmlns: "http://www.w3.org/2000/svg",
2691
+ children: [
2692
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2693
+ "path",
2694
+ {
2695
+ d: "M8 8h3v3l-1-1-2 2-1.5-1.5L8.5 8.5 8 8z",
2696
+ fill: "white",
2697
+ stroke: "rgba(255,255,255,0.8)",
2698
+ strokeWidth: "0.5"
2699
+ }
2700
+ ),
2701
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2702
+ "path",
2703
+ {
2704
+ d: "M16 8h-3v3l1-1 2 2 1.5-1.5L15.5 8.5 16 8z",
2705
+ fill: "white",
2706
+ stroke: "rgba(255,255,255,0.8)",
2707
+ strokeWidth: "0.5"
2708
+ }
2709
+ ),
2710
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2711
+ "path",
2712
+ {
2713
+ d: "M8 16h3v-3l-1 1-2-2-1.5 1.5L8.5 15.5 8 16z",
2714
+ fill: "white",
2715
+ stroke: "rgba(255,255,255,0.8)",
2716
+ strokeWidth: "0.5"
2717
+ }
2718
+ ),
2719
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2720
+ "path",
2721
+ {
2722
+ d: "M16 16h-3v-3l1 1 2-2 1.5 1.5L15.5 15.5 16 16z",
2723
+ fill: "white",
2724
+ stroke: "rgba(255,255,255,0.8)",
2725
+ strokeWidth: "0.5"
2726
+ }
2727
+ )
2728
+ ]
2729
+ }
2730
+ ) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
2731
+ "svg",
2732
+ {
2733
+ width: "20",
2734
+ height: "20",
2735
+ viewBox: "0 0 24 24",
2736
+ fill: "none",
2737
+ xmlns: "http://www.w3.org/2000/svg",
2738
+ children: [
2739
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2740
+ "path",
2741
+ {
2742
+ d: "M3 3h6v2H5v4H3V3z",
2743
+ fill: "white",
2744
+ stroke: "rgba(255,255,255,0.8)",
2745
+ strokeWidth: "0.5"
2746
+ }
2747
+ ),
2748
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2749
+ "path",
2750
+ {
2751
+ d: "M21 3h-6v2h4v4h2V3z",
2752
+ fill: "white",
2753
+ stroke: "rgba(255,255,255,0.8)",
2754
+ strokeWidth: "0.5"
2755
+ }
2756
+ ),
2757
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2758
+ "path",
2759
+ {
2760
+ d: "M3 21v-6h2v4h4v2H3z",
2761
+ fill: "white",
2762
+ stroke: "rgba(255,255,255,0.8)",
2763
+ strokeWidth: "0.5"
2764
+ }
2765
+ ),
2766
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2767
+ "path",
2768
+ {
2769
+ d: "M21 21h-6v-2h4v-4h2v6z",
2770
+ fill: "white",
2771
+ stroke: "rgba(255,255,255,0.8)",
2772
+ strokeWidth: "0.5"
2773
+ }
2774
+ )
2775
+ ]
2776
+ }
2777
+ )
2778
+ }
2779
+ )
2780
+ ]
2781
+ }
2782
+ ),
2783
+ onControlClick && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2784
+ "div",
2785
+ {
2786
+ onClick: onControlClick,
2787
+ style: {
2788
+ position: "absolute",
2789
+ top: 0,
2790
+ left: 0,
2791
+ right: 0,
2792
+ bottom: 0,
2793
+ zIndex: 1,
2794
+ cursor: "pointer"
2795
+ }
2796
+ }
2797
+ )
2798
+ ]
2799
+ }
2800
+ )
2801
+ ] });
2157
2802
  },
2158
2803
  (prevProps, nextProps) => {
2159
2804
  for (const prop of CRITICAL_PROPS) {