@geekapps/silo-elements-nextjs 0.2.27 → 0.2.29

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.
@@ -1,6 +1,6 @@
1
1
  import React, { useMemo, useRef, useState, useCallback, useEffect } from 'react';
2
2
  import gsap from 'gsap';
3
- import { Play, Settings, Captions, Volume2, Pause, VolumeX, Minimize, Maximize } from 'lucide-react';
3
+ import { Play, Pause, VolumeX, Volume2, Captions, Settings, Minimize, Maximize } from 'lucide-react';
4
4
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
5
5
 
6
6
  var AUTO_QUALITY = {
@@ -87,6 +87,7 @@ function Video({
87
87
  const [isMuted, setIsMuted] = useState(false);
88
88
  const [isFullscreen, setIsFullscreen] = useState(false);
89
89
  const [playerHeight, setPlayerHeight] = useState(0);
90
+ const [playerWidth, setPlayerWidth] = useState(0);
90
91
  const [error, setError] = useState(null);
91
92
  const activeSource = parsed.sources[sourceIndex] ?? parsed.sources[0] ?? null;
92
93
  const progressPercent = duration ? currentTime / duration * 100 : 0;
@@ -272,7 +273,10 @@ function Video({
272
273
  if (!player) return;
273
274
  const ro = new ResizeObserver((entries) => {
274
275
  const entry = entries[0];
275
- if (entry) setPlayerHeight(entry.contentRect.height);
276
+ if (entry) {
277
+ setPlayerHeight(entry.contentRect.height);
278
+ setPlayerWidth(entry.contentRect.width);
279
+ }
276
280
  });
277
281
  ro.observe(player);
278
282
  return () => ro.disconnect();
@@ -742,7 +746,7 @@ function Video({
742
746
  {
743
747
  ref: chromeRef,
744
748
  onClick: togglePlay,
745
- className: `absolute inset-0 z-30 flex flex-col justify-between transition-opacity duration-200 ${controlsVisible ? "opacity-100" : "opacity-0 pointer-events-none"}`,
749
+ className: `absolute inset-0 z-30 flex flex-col transition-opacity duration-200 ${isFullscreen ? "justify-between" : "justify-end"} ${controlsVisible ? "opacity-100" : "opacity-0 pointer-events-none"}`,
746
750
  children: [
747
751
  isFullscreen && /* @__PURE__ */ jsx("div", { className: "pointer-events-none absolute inset-x-0 top-0 h-32 bg-linear-to-b from-black/70 to-transparent" }),
748
752
  /* @__PURE__ */ jsx("div", { className: "pointer-events-none absolute inset-x-0 bottom-0 h-40 bg-linear-to-t from-black/80 to-transparent" }),
@@ -753,20 +757,52 @@ function Video({
753
757
  /* @__PURE__ */ jsxs("footer", { onClick: (e) => e.stopPropagation(), className: "relative z-10 px-4 pb-4 text-white", children: [
754
758
  settingsOpen && /* @__PURE__ */ jsxs(Fragment, { children: [
755
759
  /* @__PURE__ */ jsx("div", { className: "fixed inset-0 z-40", onClick: () => setSettingsOpen(false) }),
756
- /* @__PURE__ */ jsxs("div", { className: "absolute bottom-full right-0 z-50 mb-3 flex flex-col gap-2.5", style: { animation: "spFadeIn 0.15s ease" }, children: [
757
- /* @__PURE__ */ jsxs("div", { className: "w-52 overflow-hidden rounded-2xl bg-[#1a1a1a]/95 shadow-2xl backdrop-blur-xl ring-1 ring-white/8", children: [
758
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2.5 px-4 py-3 border-b border-white/8", children: [
759
- /* @__PURE__ */ jsx(Settings, { className: "size-4 text-white/60" }),
760
- /* @__PURE__ */ jsx("span", { className: "text-sm font-semibold text-white", children: "Video Quality" })
761
- ] }),
760
+ /* @__PURE__ */ jsxs("div", { className: "absolute bottom-full right-0 z-50 mb-2 w-56 overflow-hidden rounded-2xl bg-[#1c1c1e]/95 shadow-2xl backdrop-blur-xl ring-1 ring-white/10", style: { animation: "spFadeIn 0.15s ease" }, children: [
761
+ settingsTab === "root" && /* @__PURE__ */ jsx("div", { children: [
762
+ { id: "quality", label: "Qualidade", value: qualities.find((q) => q.id === selectedQuality)?.label ?? "Auto" },
763
+ ...parsed.subtitles.length > 0 ? [{ id: "subtitles", label: "Legendas", value: subtitleStyle.track === "off" ? "Desligado" : parsed.subtitles.find((s) => s.srclang === subtitleStyle.track)?.label ?? subtitleStyle.track }] : [],
764
+ ...audioTracks.length > 1 ? [{ id: "audio", label: "\xC1udio", value: audioTracks.find((t) => t.id === selectedAudio)?.label ?? "" }] : [],
765
+ { id: "playback", label: "Velocidade", value: playbackRate === 1 ? "Normal" : `${playbackRate}\xD7` }
766
+ ].map((item) => /* @__PURE__ */ jsxs(
767
+ "button",
768
+ {
769
+ type: "button",
770
+ onClick: () => setSettingsTab(item.id),
771
+ className: "flex w-full items-center justify-between gap-3 px-4 py-3 text-sm transition hover:bg-white/8 first:pt-3.5 last:pb-3.5",
772
+ children: [
773
+ /* @__PURE__ */ jsx("span", { className: "text-white/80", children: item.label }),
774
+ /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1.5 text-xs text-white/40", children: [
775
+ item.value,
776
+ /* @__PURE__ */ jsx("svg", { className: "size-3 opacity-50", viewBox: "0 0 12 12", fill: "none", children: /* @__PURE__ */ jsx("path", { d: "M4.5 3l3 3-3 3", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) })
777
+ ] })
778
+ ]
779
+ },
780
+ item.id
781
+ )) }),
782
+ settingsTab === "quality" && /* @__PURE__ */ jsxs("div", { children: [
783
+ /* @__PURE__ */ jsxs(
784
+ "button",
785
+ {
786
+ type: "button",
787
+ onClick: () => setSettingsTab("root"),
788
+ className: "flex w-full items-center gap-2 border-b border-white/8 px-4 py-3 text-xs font-semibold text-white/50 transition hover:text-white",
789
+ children: [
790
+ /* @__PURE__ */ jsx("svg", { className: "size-3.5", viewBox: "0 0 12 12", fill: "none", children: /* @__PURE__ */ jsx("path", { d: "M7.5 3L4.5 6l3 3", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) }),
791
+ "Qualidade"
792
+ ]
793
+ }
794
+ ),
762
795
  /* @__PURE__ */ jsx("div", { className: "py-1.5", children: [...qualities].reverse().map((quality) => /* @__PURE__ */ jsxs(
763
796
  "button",
764
797
  {
765
798
  type: "button",
766
- onClick: () => changeQuality(quality.id),
767
- className: "flex w-full items-center gap-3 px-4 py-2 text-sm transition hover:bg-white/8",
799
+ onClick: () => {
800
+ changeQuality(quality.id);
801
+ setSettingsTab("root");
802
+ },
803
+ className: "flex w-full items-center gap-3 px-4 py-2.5 text-sm transition hover:bg-white/8",
768
804
  children: [
769
- /* @__PURE__ */ jsx("span", { className: `size-4 shrink-0 ${selectedQuality === quality.id ? "text-white" : "text-transparent"}`, children: /* @__PURE__ */ jsx("svg", { viewBox: "0 0 16 16", fill: "none", children: /* @__PURE__ */ jsx("path", { d: "M3 8l3.5 3.5L13 4.5", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round", strokeLinejoin: "round" }) }) }),
805
+ /* @__PURE__ */ jsx("svg", { className: `size-4 shrink-0 ${selectedQuality === quality.id ? "text-white" : "text-transparent"}`, viewBox: "0 0 16 16", fill: "none", children: /* @__PURE__ */ jsx("path", { d: "M3 8l3.5 3.5L13 4.5", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round", strokeLinejoin: "round" }) }),
770
806
  /* @__PURE__ */ jsxs("span", { className: selectedQuality === quality.id ? "font-semibold text-white" : "text-white/55", children: [
771
807
  quality.label,
772
808
  quality.id === "auto" ? " (ABR)" : ""
@@ -776,78 +812,103 @@ function Video({
776
812
  quality.id
777
813
  )) })
778
814
  ] }),
779
- (parsed.subtitles.length > 0 || audioTracks.length > 1) && /* @__PURE__ */ jsx("div", { className: `overflow-hidden rounded-2xl bg-[#1a1a1a]/95 shadow-2xl backdrop-blur-xl ring-1 ring-white/8 ${parsed.subtitles.length > 0 && audioTracks.length > 1 ? "w-80" : "w-52"}`, children: /* @__PURE__ */ jsxs("div", { className: `grid ${parsed.subtitles.length > 0 && audioTracks.length > 1 ? "grid-cols-2 divide-x divide-white/8" : "grid-cols-1"}`, children: [
780
- parsed.subtitles.length > 0 && /* @__PURE__ */ jsxs("div", { children: [
781
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2.5 px-4 py-3 border-b border-white/8", children: [
782
- /* @__PURE__ */ jsx(Captions, { className: "size-4 text-white/60" }),
783
- /* @__PURE__ */ jsx("span", { className: "text-sm font-semibold text-white", children: "Subtitles" })
784
- ] }),
785
- /* @__PURE__ */ jsx("div", { className: "py-1.5", children: [{ srclang: "off", label: "Off" }, ...parsed.subtitles].map((s) => /* @__PURE__ */ jsxs(
786
- "button",
787
- {
788
- type: "button",
789
- onClick: () => {
790
- const next = s.srclang === "off" ? "off" : s.srclang;
791
- setSubtitleMode(next);
792
- setSubtitleStyle((st) => ({ ...st, track: next }));
793
- },
794
- className: "flex w-full items-center gap-3 px-4 py-2 text-sm transition hover:bg-white/8",
795
- children: [
796
- /* @__PURE__ */ jsx("span", { className: `size-4 shrink-0 ${subtitleStyle.track === s.srclang ? "text-white" : "text-transparent"}`, children: /* @__PURE__ */ jsx("svg", { viewBox: "0 0 16 16", fill: "none", children: /* @__PURE__ */ jsx("path", { d: "M3 8l3.5 3.5L13 4.5", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round", strokeLinejoin: "round" }) }) }),
797
- /* @__PURE__ */ jsx("span", { className: subtitleStyle.track === s.srclang ? "font-semibold text-white" : "text-white/55", children: s.label })
798
- ]
815
+ settingsTab === "subtitles" && /* @__PURE__ */ jsxs("div", { children: [
816
+ /* @__PURE__ */ jsxs(
817
+ "button",
818
+ {
819
+ type: "button",
820
+ onClick: () => setSettingsTab("root"),
821
+ className: "flex w-full items-center gap-2 border-b border-white/8 px-4 py-3 text-xs font-semibold text-white/50 transition hover:text-white",
822
+ children: [
823
+ /* @__PURE__ */ jsx("svg", { className: "size-3.5", viewBox: "0 0 12 12", fill: "none", children: /* @__PURE__ */ jsx("path", { d: "M7.5 3L4.5 6l3 3", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) }),
824
+ "Legendas"
825
+ ]
826
+ }
827
+ ),
828
+ /* @__PURE__ */ jsx("div", { className: "py-1.5", children: [{ srclang: "off", label: "Desligado" }, ...parsed.subtitles].map((s) => /* @__PURE__ */ jsxs(
829
+ "button",
830
+ {
831
+ type: "button",
832
+ onClick: () => {
833
+ const next = s.srclang === "off" ? "off" : s.srclang;
834
+ setSubtitleMode(next);
835
+ setSubtitleStyle((st) => ({ ...st, track: next }));
836
+ setSettingsTab("root");
799
837
  },
800
- s.srclang
801
- )) })
802
- ] }),
803
- audioTracks.length > 1 && /* @__PURE__ */ jsxs("div", { children: [
804
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2.5 px-4 py-3 border-b border-white/8", children: [
805
- /* @__PURE__ */ jsx(Volume2, { className: "size-4 text-white/60" }),
806
- /* @__PURE__ */ jsx("span", { className: "text-sm font-semibold text-white", children: "Audio" })
807
- ] }),
808
- /* @__PURE__ */ jsx("div", { className: "py-1.5", children: audioTracks.map((track) => /* @__PURE__ */ jsxs(
809
- "button",
810
- {
811
- type: "button",
812
- onClick: () => changeAudio(track.id),
813
- className: "flex w-full items-center gap-3 px-4 py-2 text-sm transition hover:bg-white/8",
814
- children: [
815
- /* @__PURE__ */ jsx("span", { className: `size-4 shrink-0 ${selectedAudio === track.id ? "text-white" : "text-transparent"}`, children: /* @__PURE__ */ jsx("svg", { viewBox: "0 0 16 16", fill: "none", children: /* @__PURE__ */ jsx("path", { d: "M3 8l3.5 3.5L13 4.5", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round", strokeLinejoin: "round" }) }) }),
816
- /* @__PURE__ */ jsx("span", { className: selectedAudio === track.id ? "font-semibold text-white" : "text-white/55", children: track.label })
817
- ]
838
+ className: "flex w-full items-center gap-3 px-4 py-2.5 text-sm transition hover:bg-white/8",
839
+ children: [
840
+ /* @__PURE__ */ jsx("svg", { className: `size-4 shrink-0 ${subtitleStyle.track === s.srclang ? "text-white" : "text-transparent"}`, viewBox: "0 0 16 16", fill: "none", children: /* @__PURE__ */ jsx("path", { d: "M3 8l3.5 3.5L13 4.5", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round", strokeLinejoin: "round" }) }),
841
+ /* @__PURE__ */ jsx("span", { className: subtitleStyle.track === s.srclang ? "font-semibold text-white" : "text-white/55", children: s.label })
842
+ ]
843
+ },
844
+ s.srclang
845
+ )) })
846
+ ] }),
847
+ settingsTab === "audio" && /* @__PURE__ */ jsxs("div", { children: [
848
+ /* @__PURE__ */ jsxs(
849
+ "button",
850
+ {
851
+ type: "button",
852
+ onClick: () => setSettingsTab("root"),
853
+ className: "flex w-full items-center gap-2 border-b border-white/8 px-4 py-3 text-xs font-semibold text-white/50 transition hover:text-white",
854
+ children: [
855
+ /* @__PURE__ */ jsx("svg", { className: "size-3.5", viewBox: "0 0 12 12", fill: "none", children: /* @__PURE__ */ jsx("path", { d: "M7.5 3L4.5 6l3 3", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) }),
856
+ "\xC1udio"
857
+ ]
858
+ }
859
+ ),
860
+ /* @__PURE__ */ jsx("div", { className: "py-1.5", children: audioTracks.map((track) => /* @__PURE__ */ jsxs(
861
+ "button",
862
+ {
863
+ type: "button",
864
+ onClick: () => {
865
+ changeAudio(track.id);
866
+ setSettingsTab("root");
818
867
  },
819
- track.id
820
- )) })
821
- ] })
822
- ] }) }),
823
- /* @__PURE__ */ jsxs("div", { className: "w-64 overflow-hidden rounded-2xl bg-[#1a1a1a]/95 shadow-2xl backdrop-blur-xl ring-1 ring-white/8", children: [
824
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2.5 px-4 py-3 border-b border-white/8", children: [
825
- /* @__PURE__ */ jsxs("svg", { className: "size-4 text-white/60", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
826
- /* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "9" }),
827
- /* @__PURE__ */ jsx("path", { d: "M12 12l-2-4M12 12l3.5-1.5", strokeLinecap: "round" })
828
- ] }),
829
- /* @__PURE__ */ jsx("span", { className: "text-sm font-semibold text-white", children: "Playback Speed" })
830
- ] }),
831
- /* @__PURE__ */ jsxs("div", { className: "px-4 pb-4 pt-3", children: [
832
- /* @__PURE__ */ jsx(
833
- "input",
834
- {
835
- type: "range",
836
- min: 0,
837
- max: PLAYBACK_SPEEDS.length - 1,
838
- step: 1,
839
- value: PLAYBACK_SPEEDS.indexOf(playbackRate) === -1 ? PLAYBACK_SPEEDS.indexOf(1) : PLAYBACK_SPEEDS.indexOf(playbackRate),
840
- onChange: (e) => setPlaybackRate(PLAYBACK_SPEEDS[Number(e.target.value)] ?? 1),
841
- className: "w-full accent-white"
842
- }
843
- ),
844
- /* @__PURE__ */ jsx("div", { className: "mt-1.5 flex justify-between", children: PLAYBACK_SPEEDS.map((s) => /* @__PURE__ */ jsx("span", { className: `text-[10px] font-medium ${playbackRate === s ? "text-white font-bold" : "text-white/40"}`, children: s === 1 ? "1x" : `${s}x` }, s)) })
845
- ] })
868
+ className: "flex w-full items-center gap-3 px-4 py-2.5 text-sm transition hover:bg-white/8",
869
+ children: [
870
+ /* @__PURE__ */ jsx("svg", { className: `size-4 shrink-0 ${selectedAudio === track.id ? "text-white" : "text-transparent"}`, viewBox: "0 0 16 16", fill: "none", children: /* @__PURE__ */ jsx("path", { d: "M3 8l3.5 3.5L13 4.5", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round", strokeLinejoin: "round" }) }),
871
+ /* @__PURE__ */ jsx("span", { className: selectedAudio === track.id ? "font-semibold text-white" : "text-white/55", children: track.label })
872
+ ]
873
+ },
874
+ track.id
875
+ )) })
876
+ ] }),
877
+ settingsTab === "playback" && /* @__PURE__ */ jsxs("div", { children: [
878
+ /* @__PURE__ */ jsxs(
879
+ "button",
880
+ {
881
+ type: "button",
882
+ onClick: () => setSettingsTab("root"),
883
+ className: "flex w-full items-center gap-2 border-b border-white/8 px-4 py-3 text-xs font-semibold text-white/50 transition hover:text-white",
884
+ children: [
885
+ /* @__PURE__ */ jsx("svg", { className: "size-3.5", viewBox: "0 0 12 12", fill: "none", children: /* @__PURE__ */ jsx("path", { d: "M7.5 3L4.5 6l3 3", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) }),
886
+ "Velocidade"
887
+ ]
888
+ }
889
+ ),
890
+ /* @__PURE__ */ jsx("div", { className: "py-1.5", children: PLAYBACK_SPEEDS.map((speed) => /* @__PURE__ */ jsxs(
891
+ "button",
892
+ {
893
+ type: "button",
894
+ onClick: () => {
895
+ setPlaybackRate(speed);
896
+ setSettingsOpen(false);
897
+ setSettingsTab("root");
898
+ },
899
+ className: "flex w-full items-center gap-3 px-4 py-2.5 text-sm transition hover:bg-white/8",
900
+ children: [
901
+ /* @__PURE__ */ jsx("svg", { className: `size-4 shrink-0 ${playbackRate === speed ? "text-white" : "text-transparent"}`, viewBox: "0 0 16 16", fill: "none", children: /* @__PURE__ */ jsx("path", { d: "M3 8l3.5 3.5L13 4.5", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round", strokeLinejoin: "round" }) }),
902
+ /* @__PURE__ */ jsx("span", { className: playbackRate === speed ? "font-semibold text-white" : "text-white/55", children: speed === 1 ? "Normal" : `${speed}\xD7` })
903
+ ]
904
+ },
905
+ speed
906
+ )) })
846
907
  ] })
847
908
  ] }),
848
909
  /* @__PURE__ */ jsx("style", { children: `@keyframes spFadeIn{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:translateY(0)}}` })
849
910
  ] }),
850
- /* @__PURE__ */ jsxs(
911
+ /* @__PURE__ */ jsx(
851
912
  "div",
852
913
  {
853
914
  ref: progressRef,
@@ -855,48 +916,22 @@ function Video({
855
916
  onPointerLeave: handleProgressPointerLeave,
856
917
  onPointerDown: handleProgressPointerDown,
857
918
  className: "group relative mb-2 h-5 cursor-pointer",
858
- children: [
859
- preview && /* @__PURE__ */ jsxs(
919
+ children: /* @__PURE__ */ jsxs("div", { className: "absolute left-0 right-0 top-1/2 -translate-y-1/2 overflow-hidden rounded-full bg-white/22 transition-[height] duration-150 group-hover:h-1", style: { height: "2px" }, children: [
920
+ /* @__PURE__ */ jsx(
860
921
  "div",
861
922
  {
862
- className: "pointer-events-none absolute bottom-8 z-50 -translate-x-1/2 rounded-lg bg-black/80 p-1 shadow-2xl ring-1 ring-white/15 backdrop-blur",
863
- style: { left: preview.left },
864
- children: [
865
- /* @__PURE__ */ jsx(
866
- "div",
867
- {
868
- className: "overflow-hidden rounded-md bg-neutral-900",
869
- style: {
870
- width: preview.cue.w ?? 160,
871
- height: preview.cue.h ?? 90,
872
- backgroundImage: `url(${preview.cue.image})`,
873
- backgroundPosition: preview.cue.x != null && preview.cue.y != null ? `-${preview.cue.x}px -${preview.cue.y}px` : "center",
874
- backgroundSize: preview.cue.x != null ? "auto" : "cover",
875
- backgroundRepeat: "no-repeat"
876
- }
877
- }
878
- ),
879
- /* @__PURE__ */ jsx("div", { className: "pt-1 text-center text-[11px] font-semibold text-white/80", children: formatTime(preview.time) })
880
- ]
923
+ className: "absolute inset-y-0 left-0 bg-white/30",
924
+ style: { width: `${bufferedPercent}%` }
881
925
  }
882
926
  ),
883
- /* @__PURE__ */ jsxs("div", { className: "absolute left-0 right-0 top-1/2 -translate-y-1/2 overflow-hidden rounded-full bg-white/22 transition-[height] duration-150 group-hover:h-1", style: { height: "2px" }, children: [
884
- /* @__PURE__ */ jsx(
885
- "div",
886
- {
887
- className: "absolute inset-y-0 left-0 bg-white/30",
888
- style: { width: `${bufferedPercent}%` }
889
- }
890
- ),
891
- /* @__PURE__ */ jsx(
892
- "div",
893
- {
894
- className: "absolute inset-y-0 left-0 bg-white/85",
895
- style: { width: `${progressPercent}%` }
896
- }
897
- )
898
- ] })
899
- ]
927
+ /* @__PURE__ */ jsx(
928
+ "div",
929
+ {
930
+ className: "absolute inset-y-0 left-0 bg-white/85",
931
+ style: { width: `${progressPercent}%` }
932
+ }
933
+ )
934
+ ] })
900
935
  }
901
936
  ),
902
937
  /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2", children: [
@@ -998,10 +1033,50 @@ function Video({
998
1033
  children: /* @__PURE__ */ jsx("span", { className: "grid size-10 place-items-center rounded-full bg-black/40 text-white backdrop-blur-sm ring-1 ring-white/20 @sm:size-14 @lg:size-16", children: clickIcon === "pause" ? /* @__PURE__ */ jsx(Pause, { className: "size-4 @sm:size-6 @lg:size-7" }) : /* @__PURE__ */ jsx(Play, { className: "ml-0.5 size-4 @sm:size-6 @lg:size-7" }) })
999
1034
  }
1000
1035
  ),
1036
+ preview && (() => {
1037
+ const srcW = preview.cue.w ?? 160;
1038
+ const srcH = preview.cue.h ?? 90;
1039
+ const thumbW = Math.max(120, Math.round((playerWidth || 640) * 0.1));
1040
+ const thumbH = Math.round(thumbW * (srcH / srcW));
1041
+ const scale = thumbW / srcW;
1042
+ const isSprite = preview.cue.x != null && preview.cue.y != null;
1043
+ return /* @__PURE__ */ jsxs(
1044
+ "div",
1045
+ {
1046
+ className: "pointer-events-none absolute z-50 -translate-x-1/2 rounded-xl bg-black/75 p-1 shadow-2xl ring-1 ring-white/15 backdrop-blur-sm",
1047
+ style: { bottom: controlsVisible ? "72px" : "16px", left: preview.left, transition: "bottom 0.2s" },
1048
+ children: [
1049
+ /* @__PURE__ */ jsx("div", { className: "overflow-hidden rounded-lg", style: { width: thumbW, height: thumbH }, children: isSprite ? (
1050
+ // Inner div at native tile size, positioned to show the right sprite cell,
1051
+ // then scaled up to fill thumbW×thumbH. transformOrigin top-left ensures
1052
+ // the clip window aligns correctly.
1053
+ /* @__PURE__ */ jsx("div", { style: {
1054
+ width: srcW,
1055
+ height: srcH,
1056
+ backgroundImage: `url(${preview.cue.image})`,
1057
+ backgroundPosition: `-${preview.cue.x ?? 0}px -${preview.cue.y ?? 0}px`,
1058
+ backgroundSize: "auto",
1059
+ backgroundRepeat: "no-repeat",
1060
+ transform: `scale(${scale})`,
1061
+ transformOrigin: "top left"
1062
+ } })
1063
+ ) : /* @__PURE__ */ jsx("div", { style: {
1064
+ width: thumbW,
1065
+ height: thumbH,
1066
+ backgroundImage: `url(${preview.cue.image})`,
1067
+ backgroundSize: "cover",
1068
+ backgroundPosition: "center",
1069
+ backgroundRepeat: "no-repeat"
1070
+ } }) }),
1071
+ /* @__PURE__ */ jsx("div", { className: "pt-1 text-center text-[11px] font-semibold text-white/75", children: formatTime(preview.time) })
1072
+ ]
1073
+ }
1074
+ );
1075
+ })(),
1001
1076
  activeCue && /* @__PURE__ */ jsx(
1002
1077
  "div",
1003
1078
  {
1004
- className: `pointer-events-none absolute inset-x-0 z-35 flex justify-center px-4 transition-all duration-200 ${controlsVisible ? "bottom-20 @sm:bottom-24 @lg:bottom-28" : "bottom-4 @sm:bottom-6"}`,
1079
+ className: `pointer-events-none absolute inset-x-0 z-40 flex justify-center px-4 transition-all duration-200 ${controlsVisible ? "bottom-20 @sm:bottom-24 @lg:bottom-28" : "bottom-4 @sm:bottom-6"}`,
1005
1080
  children: /* @__PURE__ */ jsx(
1006
1081
  "div",
1007
1082
  {