@geekapps/silo-elements-nextjs 0.1.21 → 0.1.23

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/dist/index.js CHANGED
@@ -3,7 +3,7 @@ import { useMultipartUpload, useBatchUpload, useSignedUrl, useFileStatus } from
3
3
  export { SiloProvider, useBatchUpload, useFileStatus, useMultipartUpload, useSignedUrl, useSiloClient } from '@geekapps/silo-nextjs';
4
4
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
5
5
  import gsap from 'gsap';
6
- import { Play, Pause, FastForward, VolumeX, Volume2, AudioLines, Captions, Settings, Minimize, Maximize } from 'lucide-react';
6
+ import { Play, Rewind, Pause, FastForward, VolumeX, Volume2, Captions, Settings, Minimize, Maximize } from 'lucide-react';
7
7
 
8
8
  // src/ImageUploader.tsx
9
9
 
@@ -1208,6 +1208,7 @@ var AUTO_QUALITY = {
1208
1208
  label: "Auto",
1209
1209
  type: "auto"
1210
1210
  };
1211
+ var PLAYBACK_SPEEDS = [0.25, 0.5, 0.75, 1, 1.25, 1.5, 2];
1211
1212
  function Sources(_props) {
1212
1213
  return null;
1213
1214
  }
@@ -1258,7 +1259,15 @@ function Video({
1258
1259
  const [selectedQuality, setSelectedQuality] = useState("auto");
1259
1260
  const [audioTracks, setAudioTracks] = useState([]);
1260
1261
  const [selectedAudio, setSelectedAudio] = useState(0);
1261
- const [openMenu, setOpenMenu] = useState(null);
1262
+ const [settingsOpen, setSettingsOpen] = useState(false);
1263
+ const [settingsTab, setSettingsTab] = useState("quality");
1264
+ const [playbackRate, setPlaybackRate] = useState(1);
1265
+ const [subtitleStyle, setSubtitleStyle] = useState({
1266
+ track: initialSubtitleMode,
1267
+ size: "medium",
1268
+ color: "white",
1269
+ bg: "semi"
1270
+ });
1262
1271
  const [subtitleMode, setSubtitleMode] = useState(initialSubtitleMode);
1263
1272
  const [activeCue, setActiveCue] = useState(null);
1264
1273
  const [storyboardCues, setStoryboardCues] = useState(
@@ -1270,6 +1279,8 @@ function Video({
1270
1279
  const [bufferedTime, setBufferedTime] = useState(0);
1271
1280
  const [isPlaying, setIsPlaying] = useState(false);
1272
1281
  const [hasPlayed, setHasPlayed] = useState(false);
1282
+ const [clickIcon, setClickIcon] = useState(null);
1283
+ const clickIconTimerRef = useRef(null);
1273
1284
  const [isLoading, setIsLoading] = useState(true);
1274
1285
  const [controlsVisible, setControlsVisible] = useState(true);
1275
1286
  const [volume, setVolume] = useState(defaultVolume);
@@ -1293,6 +1304,7 @@ function Video({
1293
1304
  const video = videoRef.current;
1294
1305
  if (!video) return;
1295
1306
  Array.from(video.textTracks).forEach((track) => {
1307
+ if (track.kind === "metadata") return;
1296
1308
  track.mode = mode !== "off" && track.language === mode ? "hidden" : "disabled";
1297
1309
  });
1298
1310
  if (mode === "off") setActiveCue(null);
@@ -1395,6 +1407,11 @@ function Video({
1395
1407
  applySubtitleMode(subtitleMode);
1396
1408
  if (subtitleMode === "off") setActiveCue(null);
1397
1409
  }, [subtitleMode, applySubtitleMode]);
1410
+ useEffect(() => {
1411
+ const video = videoRef.current;
1412
+ if (!video) return;
1413
+ video.playbackRate = playbackRate;
1414
+ }, [playbackRate]);
1398
1415
  const subtitleModeRef = useRef(subtitleMode);
1399
1416
  useEffect(() => {
1400
1417
  subtitleModeRef.current = subtitleMode;
@@ -1408,7 +1425,7 @@ function Video({
1408
1425
  setActiveCue(null);
1409
1426
  return;
1410
1427
  }
1411
- const track = Array.from(video.textTracks).find((t) => t.language === mode);
1428
+ const track = Array.from(video.textTracks).find((t) => t.language === mode && t.kind !== "metadata");
1412
1429
  if (!track || !track.activeCues || track.activeCues.length === 0) {
1413
1430
  setActiveCue(null);
1414
1431
  return;
@@ -1418,6 +1435,7 @@ function Video({
1418
1435
  };
1419
1436
  const bindTracks = () => {
1420
1437
  Array.from(video.textTracks).forEach((t) => {
1438
+ if (t.kind === "metadata") return;
1421
1439
  t.removeEventListener("cuechange", onCueChange);
1422
1440
  t.addEventListener("cuechange", onCueChange);
1423
1441
  });
@@ -1511,7 +1529,7 @@ function Video({
1511
1529
  setQualities([AUTO_QUALITY]);
1512
1530
  setAudioTracks([]);
1513
1531
  setSelectedAudio(0);
1514
- setOpenMenu(null);
1532
+ setSettingsOpen(false);
1515
1533
  video.pause();
1516
1534
  video.removeAttribute("src");
1517
1535
  video.load();
@@ -1653,11 +1671,15 @@ function Video({
1653
1671
  const video = videoRef.current;
1654
1672
  if (!video) return;
1655
1673
  try {
1656
- if (video.paused) {
1674
+ const wasPaused = video.paused;
1675
+ if (wasPaused) {
1657
1676
  await video.play();
1658
1677
  } else {
1659
1678
  video.pause();
1660
1679
  }
1680
+ if (clickIconTimerRef.current) window.clearTimeout(clickIconTimerRef.current);
1681
+ setClickIcon(wasPaused ? "play" : "pause");
1682
+ clickIconTimerRef.current = window.setTimeout(() => setClickIcon(null), 600);
1661
1683
  } catch {
1662
1684
  setError("O navegador bloqueou a reprodu\xE7\xE3o autom\xE1tica.");
1663
1685
  }
@@ -1716,7 +1738,7 @@ function Video({
1716
1738
  }, []);
1717
1739
  const changeAudio = useCallback((trackId) => {
1718
1740
  setSelectedAudio(trackId);
1719
- setOpenMenu(null);
1741
+ setSettingsOpen(false);
1720
1742
  if (hlsRef.current) {
1721
1743
  hlsRef.current.audioTrack = trackId;
1722
1744
  }
@@ -1726,7 +1748,7 @@ function Video({
1726
1748
  const option = qualities.find((quality) => quality.id === qualityId);
1727
1749
  if (!option) return;
1728
1750
  setSelectedQuality(qualityId);
1729
- setOpenMenu(null);
1751
+ setSettingsOpen(false);
1730
1752
  if (option.type === "auto") {
1731
1753
  if (hlsRef.current) {
1732
1754
  hlsRef.current.currentLevel = -1;
@@ -1856,7 +1878,7 @@ function Video({
1856
1878
  className: "relative w-full overflow-hidden rounded-[14px] bg-black shadow-[0_30px_90px_rgba(15,15,15,0.22)] outline-none ring-1 ring-black/5",
1857
1879
  style: maxHeight ? { maxHeight: typeof maxHeight === "number" ? `${maxHeight}px` : maxHeight, aspectRatio: "16/9" } : { aspectRatio: "16/9" },
1858
1880
  children: [
1859
- /* @__PURE__ */ jsx(
1881
+ /* @__PURE__ */ jsxs(
1860
1882
  "video",
1861
1883
  {
1862
1884
  ref: videoRef,
@@ -1864,17 +1886,27 @@ function Video({
1864
1886
  playsInline: true,
1865
1887
  preload: "metadata",
1866
1888
  crossOrigin: "anonymous",
1867
- children: parsed.subtitles.map((subtitle) => /* @__PURE__ */ jsx(
1868
- "track",
1869
- {
1870
- kind: "subtitles",
1871
- src: subtitle.src,
1872
- srcLang: subtitle.srclang,
1873
- label: subtitle.label,
1874
- default: subtitle.default
1875
- },
1876
- `${activeSource.src}-${subtitle.srclang}`
1877
- ))
1889
+ children: [
1890
+ parsed.subtitles.map((subtitle) => /* @__PURE__ */ jsx(
1891
+ "track",
1892
+ {
1893
+ kind: "subtitles",
1894
+ src: subtitle.src,
1895
+ srcLang: subtitle.srclang,
1896
+ label: subtitle.label,
1897
+ default: subtitle.default
1898
+ },
1899
+ `${activeSource.src}-${subtitle.srclang}`
1900
+ )),
1901
+ parsed.storyboard?.src && /* @__PURE__ */ jsx(
1902
+ "track",
1903
+ {
1904
+ kind: "metadata",
1905
+ label: "thumbnails",
1906
+ src: parsed.storyboard.src
1907
+ }
1908
+ )
1909
+ ]
1878
1910
  }
1879
1911
  ),
1880
1912
  poster && !hasPlayed && /* @__PURE__ */ jsx(
@@ -1882,7 +1914,7 @@ function Video({
1882
1914
  {
1883
1915
  src: poster,
1884
1916
  "aria-hidden": true,
1885
- className: "pointer-events-none absolute inset-0 h-full w-full object-cover"
1917
+ className: "pointer-events-none absolute inset-0 h-full w-full object-contain bg-black"
1886
1918
  }
1887
1919
  ),
1888
1920
  /* @__PURE__ */ jsx(
@@ -1920,6 +1952,114 @@ function Video({
1920
1952
  )
1921
1953
  ] }),
1922
1954
  /* @__PURE__ */ jsxs("footer", { onClick: (e) => e.stopPropagation(), className: "relative z-10 px-3 pb-3 text-white @sm:px-5 @sm:pb-5 @lg:px-9 @lg:pb-8", children: [
1955
+ settingsOpen && /* @__PURE__ */ jsxs(Fragment, { children: [
1956
+ /* @__PURE__ */ jsx("div", { className: "fixed inset-0 z-40", onClick: () => setSettingsOpen(false) }),
1957
+ /* @__PURE__ */ jsxs("div", { className: "absolute bottom-full right-3 z-50 mb-2 w-52 overflow-hidden rounded-xl border border-white/10 bg-black/90 shadow-2xl backdrop-blur-xl @sm:right-5 @lg:right-9", children: [
1958
+ /* @__PURE__ */ jsx("div", { className: "flex border-b border-white/10", children: ["quality", ...parsed.subtitles.length > 0 ? ["subtitles"] : [], ...audioTracks.length > 1 ? ["audio"] : [], "playback"].map((tab) => /* @__PURE__ */ jsx(
1959
+ "button",
1960
+ {
1961
+ type: "button",
1962
+ onClick: () => setSettingsTab(tab),
1963
+ className: `flex-1 px-3 py-2.5 text-xs font-semibold capitalize transition ${settingsTab === tab ? "text-white border-b-2 border-white -mb-px" : "text-white/50 hover:text-white/80"}`,
1964
+ children: tab
1965
+ },
1966
+ tab
1967
+ )) }),
1968
+ /* @__PURE__ */ jsxs("div", { className: "max-h-48 overflow-y-auto py-1", children: [
1969
+ settingsTab === "quality" && /* @__PURE__ */ jsx(Fragment, { children: [...qualities].reverse().map((quality) => /* @__PURE__ */ jsxs(
1970
+ SettingsItem,
1971
+ {
1972
+ active: selectedQuality === quality.id,
1973
+ onClick: () => changeQuality(quality.id),
1974
+ children: [
1975
+ quality.label,
1976
+ quality.id === "auto" && /* @__PURE__ */ jsx("span", { className: "ml-1 text-[10px] text-white/40", children: "ABR" })
1977
+ ]
1978
+ },
1979
+ quality.id
1980
+ )) }),
1981
+ settingsTab === "subtitles" && /* @__PURE__ */ jsxs("div", { className: "px-3 py-2 space-y-3", children: [
1982
+ /* @__PURE__ */ jsxs("div", { children: [
1983
+ /* @__PURE__ */ jsx("p", { className: "mb-1 text-[10px] font-semibold uppercase tracking-wider text-white/40", children: "Track" }),
1984
+ /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-1", children: [{ srclang: "off", label: "Off" }, ...parsed.subtitles].map((s) => /* @__PURE__ */ jsx(
1985
+ "button",
1986
+ {
1987
+ type: "button",
1988
+ onClick: () => {
1989
+ const next = s.srclang === "off" ? "off" : s.srclang;
1990
+ setSubtitleMode(next);
1991
+ setSubtitleStyle((st) => ({ ...st, track: next }));
1992
+ },
1993
+ className: `rounded-md px-2 py-1 text-xs font-medium transition ${subtitleStyle.track === s.srclang ? "bg-white text-black" : "bg-white/10 text-white hover:bg-white/20"}`,
1994
+ children: s.label
1995
+ },
1996
+ s.srclang
1997
+ )) })
1998
+ ] }),
1999
+ /* @__PURE__ */ jsxs("div", { children: [
2000
+ /* @__PURE__ */ jsx("p", { className: "mb-1 text-[10px] font-semibold uppercase tracking-wider text-white/40", children: "Size" }),
2001
+ /* @__PURE__ */ jsx("div", { className: "flex gap-1", children: ["small", "medium", "large"].map((s) => /* @__PURE__ */ jsx(
2002
+ "button",
2003
+ {
2004
+ type: "button",
2005
+ onClick: () => setSubtitleStyle((st) => ({ ...st, size: s })),
2006
+ className: `rounded-md px-2 py-1 text-xs font-medium capitalize transition ${subtitleStyle.size === s ? "bg-white text-black" : "bg-white/10 text-white hover:bg-white/20"}`,
2007
+ children: s
2008
+ },
2009
+ s
2010
+ )) })
2011
+ ] }),
2012
+ /* @__PURE__ */ jsxs("div", { children: [
2013
+ /* @__PURE__ */ jsx("p", { className: "mb-1 text-[10px] font-semibold uppercase tracking-wider text-white/40", children: "Color" }),
2014
+ /* @__PURE__ */ jsx("div", { className: "flex gap-2", children: [["white", "#fff"], ["yellow", "#facc15"], ["cyan", "#22d3ee"]].map(([c, hex]) => /* @__PURE__ */ jsx(
2015
+ "button",
2016
+ {
2017
+ type: "button",
2018
+ onClick: () => setSubtitleStyle((st) => ({ ...st, color: c })),
2019
+ className: `size-5 rounded-full ring-2 transition ${subtitleStyle.color === c ? "ring-white" : "ring-transparent"}`,
2020
+ style: { backgroundColor: hex }
2021
+ },
2022
+ c
2023
+ )) })
2024
+ ] }),
2025
+ /* @__PURE__ */ jsxs("div", { children: [
2026
+ /* @__PURE__ */ jsx("p", { className: "mb-1 text-[10px] font-semibold uppercase tracking-wider text-white/40", children: "Background" }),
2027
+ /* @__PURE__ */ jsx("div", { className: "flex gap-1", children: [["none", "None"], ["semi", "Semi"], ["solid", "Solid"]].map(([v, label]) => /* @__PURE__ */ jsx(
2028
+ "button",
2029
+ {
2030
+ type: "button",
2031
+ onClick: () => setSubtitleStyle((st) => ({ ...st, bg: v })),
2032
+ className: `rounded-md px-2 py-1 text-xs font-medium transition ${subtitleStyle.bg === v ? "bg-white text-black" : "bg-white/10 text-white hover:bg-white/20"}`,
2033
+ children: label
2034
+ },
2035
+ v
2036
+ )) })
2037
+ ] })
2038
+ ] }),
2039
+ settingsTab === "audio" && audioTracks.length > 1 && /* @__PURE__ */ jsx(Fragment, { children: audioTracks.map((track) => /* @__PURE__ */ jsx(
2040
+ SettingsItem,
2041
+ {
2042
+ active: selectedAudio === track.id,
2043
+ onClick: () => changeAudio(track.id),
2044
+ children: track.label
2045
+ },
2046
+ track.id
2047
+ )) }),
2048
+ settingsTab === "playback" && /* @__PURE__ */ jsx(Fragment, { children: PLAYBACK_SPEEDS.map((speed) => /* @__PURE__ */ jsx(
2049
+ SettingsItem,
2050
+ {
2051
+ active: playbackRate === speed,
2052
+ onClick: () => {
2053
+ setPlaybackRate(speed);
2054
+ setSettingsOpen(false);
2055
+ },
2056
+ children: speed === 1 ? "Normal" : `${speed}x`
2057
+ },
2058
+ speed
2059
+ )) })
2060
+ ] })
2061
+ ] })
2062
+ ] }),
1923
2063
  /* @__PURE__ */ jsxs(
1924
2064
  "div",
1925
2065
  {
@@ -1974,6 +2114,16 @@ function Video({
1974
2114
  ),
1975
2115
  /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2 @sm:gap-4 @lg:gap-5", children: [
1976
2116
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 @sm:gap-4 @lg:gap-5", children: [
2117
+ /* @__PURE__ */ jsx(
2118
+ "button",
2119
+ {
2120
+ type: "button",
2121
+ onClick: () => seekRelative(-10),
2122
+ className: "grid size-6 place-items-center text-white transition hover:scale-105 hover:text-white/80 @sm:size-8",
2123
+ "aria-label": "Rewind 10 seconds",
2124
+ children: /* @__PURE__ */ jsx(Rewind, { className: "size-5 @sm:size-7" })
2125
+ }
2126
+ ),
1977
2127
  /* @__PURE__ */ jsx(
1978
2128
  "button",
1979
2129
  {
@@ -1989,7 +2139,7 @@ function Video({
1989
2139
  {
1990
2140
  type: "button",
1991
2141
  onClick: () => seekRelative(10),
1992
- className: "hidden size-6 place-items-center text-white transition hover:scale-105 hover:text-white/80 @sm:grid @sm:size-8",
2142
+ className: "grid size-6 place-items-center text-white transition hover:scale-105 hover:text-white/80 @sm:size-8",
1993
2143
  "aria-label": "Forward 10 seconds",
1994
2144
  children: /* @__PURE__ */ jsx(FastForward, { className: "size-5 @sm:size-7" })
1995
2145
  }
@@ -2029,91 +2179,29 @@ function Video({
2029
2179
  }
2030
2180
  ),
2031
2181
  /* @__PURE__ */ jsx("div", { className: "mx-0.5 hidden h-4 w-px bg-white/20 @md:mx-1 @md:block" }),
2032
- audioTracks.length > 1 && /* @__PURE__ */ jsxs("div", { className: "relative", children: [
2033
- /* @__PURE__ */ jsx(
2034
- "button",
2035
- {
2036
- type: "button",
2037
- onClick: () => setOpenMenu(openMenu === "audio" ? null : "audio"),
2038
- className: `grid size-6 place-items-center rounded transition hover:text-white/80 @sm:size-8 ${openMenu === "audio" ? "text-white" : "text-white/60"}`,
2039
- "aria-label": "Audio track",
2040
- children: /* @__PURE__ */ jsx(AudioLines, { className: "size-4 @sm:size-5" })
2041
- }
2042
- ),
2043
- openMenu === "audio" && /* @__PURE__ */ jsx(PopoverMenu, { onClose: () => setOpenMenu(null), children: audioTracks.map((track) => /* @__PURE__ */ jsx(
2044
- PopoverItem,
2045
- {
2046
- active: selectedAudio === track.id,
2047
- onClick: () => changeAudio(track.id),
2048
- children: track.label
2049
- },
2050
- track.id
2051
- )) })
2052
- ] }),
2053
- parsed.subtitles.length > 0 && /* @__PURE__ */ jsxs("div", { className: "relative", children: [
2054
- /* @__PURE__ */ jsx(
2055
- "button",
2056
- {
2057
- type: "button",
2058
- onClick: () => setOpenMenu(openMenu === "captions" ? null : "captions"),
2059
- className: `grid size-6 place-items-center rounded transition hover:text-white/80 @sm:size-8 ${subtitleMode !== "off" || openMenu === "captions" ? "text-white" : "text-white/60"}`,
2060
- "aria-label": "Captions",
2061
- children: /* @__PURE__ */ jsx(Captions, { className: "size-4 @sm:size-5" })
2062
- }
2063
- ),
2064
- openMenu === "captions" && /* @__PURE__ */ jsxs(PopoverMenu, { onClose: () => setOpenMenu(null), children: [
2065
- /* @__PURE__ */ jsx(
2066
- PopoverItem,
2067
- {
2068
- active: subtitleMode === "off",
2069
- onClick: () => {
2070
- setSubtitleMode("off");
2071
- setOpenMenu(null);
2072
- },
2073
- children: "Off"
2074
- }
2075
- ),
2076
- parsed.subtitles.map((subtitle) => /* @__PURE__ */ jsx(
2077
- PopoverItem,
2078
- {
2079
- active: subtitleMode === subtitle.srclang,
2080
- onClick: () => {
2081
- setSubtitleMode(subtitle.srclang);
2082
- setOpenMenu(null);
2083
- },
2084
- children: subtitle.label
2085
- },
2086
- subtitle.srclang
2087
- ))
2088
- ] })
2089
- ] }),
2090
- /* @__PURE__ */ jsxs("div", { className: "relative", children: [
2091
- /* @__PURE__ */ jsxs(
2092
- "button",
2093
- {
2094
- type: "button",
2095
- onClick: () => setOpenMenu(openMenu === "quality" ? null : "quality"),
2096
- className: `flex h-6 items-center gap-1 rounded px-1.5 text-xs font-semibold transition hover:text-white/80 @sm:h-8 @sm:px-2 ${openMenu === "quality" ? "text-white" : "text-white/60"}`,
2097
- "aria-label": "Quality",
2098
- children: [
2099
- /* @__PURE__ */ jsx(Settings, { className: "size-3.5 @sm:size-4" }),
2100
- /* @__PURE__ */ jsx("span", { className: "hidden @sm:inline", children: qualities.find((q) => q.id === selectedQuality)?.label ?? "Auto" })
2101
- ]
2102
- }
2103
- ),
2104
- openMenu === "quality" && /* @__PURE__ */ jsx(PopoverMenu, { onClose: () => setOpenMenu(null), children: [...qualities].reverse().map((quality) => /* @__PURE__ */ jsxs(
2105
- PopoverItem,
2106
- {
2107
- active: selectedQuality === quality.id,
2108
- onClick: () => changeQuality(quality.id),
2109
- children: [
2110
- quality.label,
2111
- quality.id === "auto" && /* @__PURE__ */ jsx("span", { className: "ml-1 text-[10px] text-white/40", children: "ABR" })
2112
- ]
2113
- },
2114
- quality.id
2115
- )) })
2116
- ] }),
2182
+ parsed.subtitles.length > 0 && /* @__PURE__ */ jsx(
2183
+ "button",
2184
+ {
2185
+ type: "button",
2186
+ onClick: () => setSubtitleMode((m) => m === "off" ? parsed.subtitles[0]?.srclang ?? "off" : "off"),
2187
+ className: `grid size-6 place-items-center rounded transition hover:text-white/80 @sm:size-8 ${subtitleMode !== "off" ? "text-white" : "text-white/60"}`,
2188
+ "aria-label": "Captions",
2189
+ children: /* @__PURE__ */ jsx(Captions, { className: "size-4 @sm:size-5" })
2190
+ }
2191
+ ),
2192
+ /* @__PURE__ */ jsx("div", { className: "relative", children: /* @__PURE__ */ jsxs(
2193
+ "button",
2194
+ {
2195
+ type: "button",
2196
+ onClick: () => setSettingsOpen((v) => !v),
2197
+ className: `flex h-6 items-center gap-1 rounded px-1.5 text-xs font-semibold transition hover:text-white/80 @sm:h-8 @sm:px-2 ${settingsOpen ? "text-white" : "text-white/60"}`,
2198
+ "aria-label": "Settings",
2199
+ children: [
2200
+ /* @__PURE__ */ jsx(Settings, { className: "size-3.5 @sm:size-4" }),
2201
+ /* @__PURE__ */ jsx("span", { className: "hidden @sm:inline", children: qualities.find((q) => q.id === selectedQuality)?.label ?? "Auto" })
2202
+ ]
2203
+ }
2204
+ ) }),
2117
2205
  /* @__PURE__ */ jsx(
2118
2206
  "button",
2119
2207
  {
@@ -2130,6 +2218,14 @@ function Video({
2130
2218
  ]
2131
2219
  }
2132
2220
  ),
2221
+ /* @__PURE__ */ jsx(
2222
+ "div",
2223
+ {
2224
+ className: "pointer-events-none absolute inset-0 z-50 grid place-items-center",
2225
+ style: { opacity: clickIcon ? 1 : 0, transition: clickIcon ? "opacity 0.08s ease-in" : "opacity 0.45s ease-out" },
2226
+ children: /* @__PURE__ */ jsx("span", { className: "grid size-14 place-items-center rounded-full bg-black/40 text-white backdrop-blur-sm ring-1 ring-white/20 @sm:size-18 @lg:size-22", children: clickIcon === "pause" ? /* @__PURE__ */ jsx(Pause, { className: "size-6 @sm:size-8 @lg:size-10" }) : /* @__PURE__ */ jsx(Play, { className: "ml-1 size-6 @sm:size-8 @lg:size-10" }) })
2227
+ }
2228
+ ),
2133
2229
  activeCue && /* @__PURE__ */ jsx(
2134
2230
  "div",
2135
2231
  {
@@ -2137,8 +2233,14 @@ function Video({
2137
2233
  children: /* @__PURE__ */ jsx(
2138
2234
  "div",
2139
2235
  {
2140
- className: "max-w-3xl rounded-lg bg-black/75 px-4 py-2 text-center text-sm font-medium leading-snug text-white backdrop-blur-sm @sm:text-base @lg:text-lg",
2141
- style: { textShadow: "0 1px 4px rgba(0,0,0,0.9)" },
2236
+ className: "max-w-3xl rounded-lg px-4 py-2 text-center font-medium leading-snug",
2237
+ style: {
2238
+ fontSize: subtitleStyle.size === "small" ? "0.8rem" : subtitleStyle.size === "large" ? "1.25rem" : "1rem",
2239
+ color: subtitleStyle.color === "yellow" ? "#facc15" : subtitleStyle.color === "cyan" ? "#22d3ee" : "#ffffff",
2240
+ backgroundColor: subtitleStyle.bg === "none" ? "transparent" : subtitleStyle.bg === "solid" ? "rgba(0,0,0,0.9)" : "rgba(0,0,0,0.7)",
2241
+ backdropFilter: subtitleStyle.bg === "semi" ? "blur(4px)" : void 0,
2242
+ textShadow: subtitleStyle.bg === "none" ? "0 1px 6px rgba(0,0,0,1), 0 0 12px rgba(0,0,0,0.8)" : "0 1px 3px rgba(0,0,0,0.6)"
2243
+ },
2142
2244
  children: activeCue
2143
2245
  }
2144
2246
  )
@@ -2151,13 +2253,7 @@ function Video({
2151
2253
  );
2152
2254
  }
2153
2255
  var VideoPlayer = Video;
2154
- function PopoverMenu({ children, onClose }) {
2155
- return /* @__PURE__ */ jsxs(Fragment, { children: [
2156
- /* @__PURE__ */ jsx("div", { className: "fixed inset-0 z-40", onClick: onClose }),
2157
- /* @__PURE__ */ jsx("div", { className: "absolute bottom-full right-0 z-50 mb-2 min-w-35 overflow-hidden rounded-xl border border-white/10 bg-black/85 py-1 shadow-2xl backdrop-blur-xl", children })
2158
- ] });
2159
- }
2160
- function PopoverItem({
2256
+ function SettingsItem({
2161
2257
  children,
2162
2258
  active,
2163
2259
  onClick