@geekapps/silo-elements-nextjs 0.2.31 → 0.2.33

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, Pause, VolumeX, Volume2, Captions, Settings, Minimize, Maximize } from 'lucide-react';
3
+ import { Pause, Play, 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 = {
@@ -78,6 +78,8 @@ function Video({
78
78
  const [duration, setDuration] = useState(0);
79
79
  const [currentTime, setCurrentTime] = useState(0);
80
80
  const [bufferedTime, setBufferedTime] = useState(0);
81
+ const [isDragging, setIsDragging] = useState(false);
82
+ const dragPointerIdRef = useRef(null);
81
83
  const [isPlaying, setIsPlaying] = useState(false);
82
84
  const [hasPlayed, setHasPlayed] = useState(false);
83
85
  const [clickIcon, setClickIcon] = useState(null);
@@ -601,44 +603,69 @@ function Video({
601
603
  },
602
604
  [qualities]
603
605
  );
604
- const handleProgressPointerMove = useCallback(
605
- (event) => {
606
+ const seekFromPointer = useCallback(
607
+ (clientX) => {
608
+ const video = videoRef.current;
609
+ const progress = progressRef.current;
610
+ if (!video || !progress || !duration) return;
611
+ const rect = progress.getBoundingClientRect();
612
+ const x = Math.max(0, Math.min(clientX - rect.left, rect.width));
613
+ const nextTime = x / rect.width * duration;
614
+ video.currentTime = nextTime;
615
+ setCurrentTime(nextTime);
616
+ },
617
+ [duration]
618
+ );
619
+ const updatePreview = useCallback(
620
+ (clientX) => {
606
621
  const progress = progressRef.current;
607
622
  if (!progress || !duration || storyboardCues.length === 0) {
608
623
  setPreview(null);
609
624
  return;
610
625
  }
611
626
  const rect = progress.getBoundingClientRect();
612
- const x = Math.max(0, Math.min(event.clientX - rect.left, rect.width));
627
+ const x = Math.max(0, Math.min(clientX - rect.left, rect.width));
613
628
  const time = x / rect.width * duration;
614
629
  const cue = findStoryboardCue(storyboardCues, time);
615
630
  if (!cue) {
616
631
  setPreview(null);
617
632
  return;
618
633
  }
619
- setPreview({
620
- cue,
621
- time,
622
- left: Math.max(80, Math.min(x, rect.width - 80))
623
- });
634
+ setPreview({ cue, time, left: Math.max(80, Math.min(x, rect.width - 80)) });
624
635
  },
625
636
  [duration, storyboardCues]
626
637
  );
638
+ const handleProgressPointerMove = useCallback(
639
+ (event) => {
640
+ updatePreview(event.clientX);
641
+ if (isDragging) seekFromPointer(event.clientX);
642
+ },
643
+ [isDragging, seekFromPointer, updatePreview]
644
+ );
627
645
  const handleProgressPointerLeave = useCallback(() => {
628
- setPreview(null);
629
- }, []);
646
+ if (!isDragging) setPreview(null);
647
+ }, [isDragging]);
630
648
  const handleProgressPointerDown = useCallback(
631
649
  (event) => {
632
- const video = videoRef.current;
633
650
  const progress = progressRef.current;
634
- if (!video || !progress || !duration) return;
635
- const rect = progress.getBoundingClientRect();
636
- const x = Math.max(0, Math.min(event.clientX - rect.left, rect.width));
637
- const nextTime = x / rect.width * duration;
638
- video.currentTime = nextTime;
639
- setCurrentTime(nextTime);
651
+ if (!progress) return;
652
+ progress.setPointerCapture(event.pointerId);
653
+ dragPointerIdRef.current = event.pointerId;
654
+ setIsDragging(true);
655
+ seekFromPointer(event.clientX);
656
+ updatePreview(event.clientX);
640
657
  },
641
- [duration]
658
+ [seekFromPointer, updatePreview]
659
+ );
660
+ const handleProgressPointerUp = useCallback(
661
+ (event) => {
662
+ if (dragPointerIdRef.current === event.pointerId) {
663
+ setIsDragging(false);
664
+ dragPointerIdRef.current = null;
665
+ setPreview(null);
666
+ }
667
+ },
668
+ []
642
669
  );
643
670
  const handleKeyDown = useCallback(
644
671
  (event) => {
@@ -736,8 +763,9 @@ function Video({
736
763
  /* @__PURE__ */ jsx(
737
764
  "div",
738
765
  {
739
- className: `pointer-events-none absolute inset-0 z-10 grid place-items-center transition ${isPlaying ? "opacity-0" : "opacity-100"}`,
740
- children: /* @__PURE__ */ jsx("span", { className: "grid size-10 place-items-center rounded-full bg-white/15 text-white backdrop-blur-xl ring-1 ring-white/20 @sm:size-14 @lg:size-16", children: /* @__PURE__ */ jsx(Play, { className: "ml-0.5 size-4 @sm:size-6 @lg:size-7" }) })
766
+ className: "pointer-events-none absolute inset-0 z-10 grid place-items-center",
767
+ style: { opacity: clickIcon ? 1 : 0, transition: clickIcon ? "opacity 0.08s ease-in" : "opacity 0.45s ease-out" },
768
+ children: /* @__PURE__ */ jsx("span", { className: "grid size-10 place-items-center text-white drop-shadow-[0_2px_12px_rgba(0,0,0,0.8)] @sm:size-14 @lg:size-16", children: clickIcon === "pause" ? /* @__PURE__ */ jsx(Pause, { className: "size-5 @sm:size-7 @lg:size-8" }) : /* @__PURE__ */ jsx(Play, { className: "ml-0.5 size-5 @sm:size-7 @lg:size-8" }) })
741
769
  }
742
770
  ),
743
771
  isLoading && /* @__PURE__ */ jsx("div", { className: "pointer-events-none absolute inset-0 z-20 grid place-items-center bg-black/10", children: /* @__PURE__ */ jsx("div", { className: "size-9 animate-spin rounded-full border-2 border-white/25 border-t-white" }) }),
@@ -757,8 +785,8 @@ function Video({
757
785
  ] }) }),
758
786
  /* @__PURE__ */ jsxs("footer", { onClick: (e) => e.stopPropagation(), className: "relative z-10 px-4 pb-4 text-white", children: [
759
787
  settingsOpen && /* @__PURE__ */ jsxs(Fragment, { children: [
760
- /* @__PURE__ */ jsx("div", { className: "fixed inset-0 z-40", onClick: () => setSettingsOpen(false) }),
761
- /* @__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: [
788
+ /* @__PURE__ */ jsx("div", { className: "fixed inset-0 z-70", onClick: () => setSettingsOpen(false) }),
789
+ /* @__PURE__ */ jsxs("div", { className: "absolute bottom-full right-2 z-70 mb-2 overflow-hidden rounded-2xl bg-[#1c1c1e]/95 shadow-2xl backdrop-blur-xl ring-1 ring-white/10", style: { width: Math.min(224, Math.max(180, (playerWidth || 640) * 0.22)) + "px", animation: "spFadeIn 0.15s ease" }, children: [
762
790
  settingsTab === "root" && /* @__PURE__ */ jsx("div", { children: [
763
791
  { id: "quality", label: "Qualidade", value: qualities.find((q) => q.id === selectedQuality)?.label ?? "Auto" },
764
792
  ...parsed.subtitles.length > 0 ? [{ id: "subtitles", label: "Legendas", value: subtitleStyle.track === "off" ? "Desligado" : parsed.subtitles.find((s) => s.srclang === subtitleStyle.track)?.label ?? subtitleStyle.track }] : [],
@@ -834,7 +862,6 @@ function Video({
834
862
  const next = s.srclang === "off" ? "off" : s.srclang;
835
863
  setSubtitleMode(next);
836
864
  setSubtitleStyle((st) => ({ ...st, track: next }));
837
- setSettingsTab("root");
838
865
  },
839
866
  className: "flex w-full items-center gap-3 px-4 py-2.5 text-sm transition hover:bg-white/8",
840
867
  children: [
@@ -843,7 +870,75 @@ function Video({
843
870
  ]
844
871
  },
845
872
  s.srclang
846
- )) })
873
+ )) }),
874
+ subtitleStyle.track !== "off" && /* @__PURE__ */ jsxs(
875
+ "button",
876
+ {
877
+ type: "button",
878
+ onClick: () => setSettingsTab("subtitles-style"),
879
+ className: "flex w-full items-center justify-between gap-3 border-t border-white/8 px-4 py-3 text-sm transition hover:bg-white/8",
880
+ children: [
881
+ /* @__PURE__ */ jsx("span", { className: "text-white/60", children: "Apar\xEAncia" }),
882
+ /* @__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" }) })
883
+ ]
884
+ }
885
+ )
886
+ ] }),
887
+ settingsTab === "subtitles-style" && /* @__PURE__ */ jsxs("div", { children: [
888
+ /* @__PURE__ */ jsxs(
889
+ "button",
890
+ {
891
+ type: "button",
892
+ onClick: () => setSettingsTab("subtitles"),
893
+ 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",
894
+ children: [
895
+ /* @__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" }) }),
896
+ "Apar\xEAncia"
897
+ ]
898
+ }
899
+ ),
900
+ /* @__PURE__ */ jsxs("div", { className: "px-4 py-3 flex flex-col gap-3", children: [
901
+ /* @__PURE__ */ jsxs("div", { children: [
902
+ /* @__PURE__ */ jsx("p", { className: "mb-1.5 text-xs font-semibold text-white/40 uppercase tracking-wide", children: "Tamanho" }),
903
+ /* @__PURE__ */ jsx("div", { className: "flex gap-1.5", children: ["small", "medium", "large", "xlarge"].map((s) => /* @__PURE__ */ jsx(
904
+ "button",
905
+ {
906
+ type: "button",
907
+ onClick: () => setSubtitleStyle((st) => ({ ...st, size: s })),
908
+ className: `flex-1 rounded-lg py-1.5 text-xs font-medium transition ${subtitleStyle.size === s ? "bg-white/20 text-white" : "text-white/45 hover:bg-white/10"}`,
909
+ children: s === "small" ? "P" : s === "medium" ? "M" : s === "large" ? "G" : "GG"
910
+ },
911
+ s
912
+ )) })
913
+ ] }),
914
+ /* @__PURE__ */ jsxs("div", { children: [
915
+ /* @__PURE__ */ jsx("p", { className: "mb-1.5 text-xs font-semibold text-white/40 uppercase tracking-wide", children: "Cor" }),
916
+ /* @__PURE__ */ jsx("div", { className: "flex gap-1.5", children: [["white", "Branco", "#fff"], ["yellow", "Amarelo", "#facc15"], ["cyan", "Ciano", "#22d3ee"]].map(([val, label, color]) => /* @__PURE__ */ jsx(
917
+ "button",
918
+ {
919
+ type: "button",
920
+ onClick: () => setSubtitleStyle((st) => ({ ...st, color: val })),
921
+ className: `flex-1 rounded-lg py-1.5 text-xs font-medium transition ring-1 ${subtitleStyle.color === val ? "ring-white/40" : "ring-transparent hover:ring-white/15"}`,
922
+ style: { color },
923
+ children: label
924
+ },
925
+ val
926
+ )) })
927
+ ] }),
928
+ /* @__PURE__ */ jsxs("div", { children: [
929
+ /* @__PURE__ */ jsx("p", { className: "mb-1.5 text-xs font-semibold text-white/40 uppercase tracking-wide", children: "Fundo" }),
930
+ /* @__PURE__ */ jsx("div", { className: "flex gap-1.5", children: [["none", "Nenhum"], ["semi", "Semi"], ["solid", "S\xF3lido"]].map(([val, label]) => /* @__PURE__ */ jsx(
931
+ "button",
932
+ {
933
+ type: "button",
934
+ onClick: () => setSubtitleStyle((st) => ({ ...st, bg: val })),
935
+ className: `flex-1 rounded-lg py-1.5 text-xs font-medium transition ${subtitleStyle.bg === val ? "bg-white/20 text-white" : "text-white/45 hover:bg-white/10"}`,
936
+ children: label
937
+ },
938
+ val
939
+ )) })
940
+ ] })
941
+ ] })
847
942
  ] }),
848
943
  settingsTab === "audio" && /* @__PURE__ */ jsxs("div", { children: [
849
944
  /* @__PURE__ */ jsxs(
@@ -909,84 +1004,90 @@ function Video({
909
1004
  ] }),
910
1005
  /* @__PURE__ */ jsx("style", { children: `@keyframes spFadeIn{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:translateY(0)}}` })
911
1006
  ] }),
912
- /* @__PURE__ */ jsx(
1007
+ /* @__PURE__ */ jsxs(
913
1008
  "div",
914
1009
  {
915
1010
  ref: progressRef,
916
1011
  onPointerMove: handleProgressPointerMove,
917
1012
  onPointerLeave: handleProgressPointerLeave,
918
1013
  onPointerDown: handleProgressPointerDown,
919
- className: "group relative mb-2 h-5 cursor-pointer",
920
- 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: [
921
- /* @__PURE__ */ jsx(
1014
+ onPointerUp: handleProgressPointerUp,
1015
+ className: "group relative mb-3 h-7 cursor-pointer",
1016
+ children: [
1017
+ /* @__PURE__ */ jsxs(
922
1018
  "div",
923
1019
  {
924
- className: "absolute inset-y-0 left-0 bg-white/30",
925
- style: { width: `${bufferedPercent}%` }
1020
+ className: "absolute left-0 right-0 top-1/2 -translate-y-1/2 overflow-hidden rounded-full bg-white/22 transition-[height] duration-150",
1021
+ style: { height: isDragging ? "6px" : "3px" },
1022
+ children: [
1023
+ /* @__PURE__ */ jsx("div", { className: "absolute inset-y-0 left-0 rounded-full bg-white/30", style: { width: `${bufferedPercent}%` } }),
1024
+ /* @__PURE__ */ jsx("div", { className: "absolute inset-y-0 left-0 rounded-full bg-white/90", style: { width: `${progressPercent}%` } })
1025
+ ]
926
1026
  }
927
1027
  ),
928
1028
  /* @__PURE__ */ jsx(
929
1029
  "div",
930
1030
  {
931
- className: "absolute inset-y-0 left-0 bg-white/85",
932
- style: { width: `${progressPercent}%` }
1031
+ className: "pointer-events-none absolute top-1/2 -translate-x-1/2 -translate-y-1/2 rounded-full bg-white shadow-md transition-[width,height] duration-100 group-hover:size-4",
1032
+ style: {
1033
+ left: `${progressPercent}%`,
1034
+ width: isDragging ? "16px" : "10px",
1035
+ height: isDragging ? "16px" : "10px"
1036
+ }
933
1037
  }
934
1038
  )
935
- ] })
1039
+ ]
936
1040
  }
937
1041
  ),
938
1042
  /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2", children: [
939
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1 @sm:gap-2", children: [
940
- /* @__PURE__ */ jsx(SeekButton, { seconds: 15, direction: "back", onClick: () => seekRelative(-15) }),
1043
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 @sm:gap-2", children: [
941
1044
  /* @__PURE__ */ jsx(
942
1045
  "button",
943
1046
  {
944
1047
  type: "button",
945
1048
  onClick: togglePlay,
946
- className: "grid size-8 place-items-center text-white transition hover:scale-110 hover:text-white/80 @sm:size-10",
1049
+ className: "grid size-8 place-items-center rounded-full bg-white/15 text-white backdrop-blur-sm ring-1 ring-white/15 transition hover:bg-white/25 @sm:size-9",
947
1050
  "aria-label": isPlaying ? "Pause" : "Play",
948
- children: isPlaying ? /* @__PURE__ */ jsx(Pause, { className: "size-5 @sm:size-6" }) : /* @__PURE__ */ jsx(Play, { className: "ml-0.5 size-5 @sm:size-6" })
1051
+ children: isPlaying ? /* @__PURE__ */ jsx(Pause, { className: "size-4 @sm:size-5" }) : /* @__PURE__ */ jsx(Play, { className: "ml-0.5 size-4 @sm:size-5" })
949
1052
  }
950
1053
  ),
951
- /* @__PURE__ */ jsx(SeekButton, { seconds: 15, direction: "forward", onClick: () => seekRelative(15) }),
952
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1 text-xs font-semibold text-white/75 @sm:text-sm", children: [
953
- /* @__PURE__ */ jsx("span", { children: formatTime(currentTime) }),
954
- /* @__PURE__ */ jsx("span", { className: "text-white/35", children: "/" }),
955
- /* @__PURE__ */ jsxs("span", { className: "text-white/50", children: [
956
- "-",
957
- formatTime(Math.max(0, duration - currentTime))
958
- ] })
1054
+ /* @__PURE__ */ jsxs("span", { className: "text-[11px] font-medium tabular-nums text-white/80", children: [
1055
+ formatTime(currentTime),
1056
+ /* @__PURE__ */ jsx("span", { className: "text-white/30", children: "/" }),
1057
+ /* @__PURE__ */ jsx("span", { className: "text-white/45", children: formatTime(duration) })
959
1058
  ] })
960
1059
  ] }),
961
1060
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-0.5 @sm:gap-1", children: [
962
- /* @__PURE__ */ jsx(
963
- "button",
964
- {
965
- type: "button",
966
- onClick: () => setIsMuted((value) => !value),
967
- className: "grid size-8 place-items-center text-white transition hover:scale-110 hover:text-white/80 @sm:size-10",
968
- "aria-label": isMuted ? "Unmute" : "Mute",
969
- children: isMuted || volume === 0 ? /* @__PURE__ */ jsx(VolumeX, { className: "size-4 @sm:size-5" }) : /* @__PURE__ */ jsx(Volume2, { className: "size-4 @sm:size-5" })
970
- }
971
- ),
972
- /* @__PURE__ */ jsx(
973
- "input",
974
- {
975
- type: "range",
976
- min: "0",
977
- max: "1",
978
- step: "0.01",
979
- value: isMuted ? 0 : volume,
980
- onChange: (event) => {
981
- const nextVolume = Number(event.target.value);
982
- setVolume(nextVolume);
983
- setIsMuted(nextVolume === 0);
984
- },
985
- className: "hidden h-1 w-14 accent-white @md:block @md:w-20",
986
- "aria-label": "Audio level"
987
- }
988
- ),
989
- /* @__PURE__ */ jsx("div", { className: "mx-0.5 hidden h-4 w-px bg-white/20 @md:mx-1 @md:block" }),
1061
+ /* @__PURE__ */ jsxs("div", { className: "group flex items-center", children: [
1062
+ /* @__PURE__ */ jsx(
1063
+ "button",
1064
+ {
1065
+ type: "button",
1066
+ onClick: () => setIsMuted((value) => !value),
1067
+ className: "grid size-8 place-items-center text-white/70 transition hover:text-white @sm:size-9",
1068
+ "aria-label": isMuted ? "Unmute" : "Mute",
1069
+ children: isMuted || volume === 0 ? /* @__PURE__ */ jsx(VolumeX, { className: "size-4 @sm:size-5" }) : /* @__PURE__ */ jsx(Volume2, { className: "size-4 @sm:size-5" })
1070
+ }
1071
+ ),
1072
+ /* @__PURE__ */ jsx("div", { className: "w-0 overflow-hidden transition-all duration-200 group-hover:w-16 @md:group-hover:w-20", children: /* @__PURE__ */ jsx(
1073
+ "input",
1074
+ {
1075
+ type: "range",
1076
+ min: "0",
1077
+ max: "1",
1078
+ step: "0.01",
1079
+ value: isMuted ? 0 : volume,
1080
+ onChange: (event) => {
1081
+ const nextVolume = Number(event.target.value);
1082
+ setVolume(nextVolume);
1083
+ setIsMuted(nextVolume === 0);
1084
+ },
1085
+ className: "h-1 w-14 accent-white @md:w-20",
1086
+ "aria-label": "Audio level"
1087
+ }
1088
+ ) })
1089
+ ] }),
1090
+ /* @__PURE__ */ jsx("div", { className: "mx-0.5 h-4 w-px bg-white/20 @md:mx-1" }),
990
1091
  parsed.subtitles.length > 0 && /* @__PURE__ */ jsx(
991
1092
  "button",
992
1093
  {
@@ -1026,51 +1127,35 @@ function Video({
1026
1127
  ]
1027
1128
  }
1028
1129
  ),
1029
- /* @__PURE__ */ jsx(
1030
- "div",
1031
- {
1032
- className: "pointer-events-none absolute inset-0 z-50 grid place-items-center",
1033
- style: { opacity: clickIcon ? 1 : 0, transition: clickIcon ? "opacity 0.08s ease-in" : "opacity 0.45s ease-out" },
1034
- 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" }) })
1035
- }
1036
- ),
1037
1130
  preview && (() => {
1038
1131
  const srcW = preview.cue.w ?? 160;
1039
1132
  const srcH = preview.cue.h ?? 90;
1040
- const thumbW = Math.max(120, Math.round((playerWidth || 640) * 0.1));
1133
+ const thumbW = Math.max(140, Math.round((playerWidth || 640) * 0.13));
1041
1134
  const thumbH = Math.round(thumbW * (srcH / srcW));
1042
1135
  const scale = thumbW / srcW;
1043
1136
  const isSprite = preview.cue.x != null && preview.cue.y != null;
1044
- return /* @__PURE__ */ jsxs(
1137
+ return /* @__PURE__ */ jsx(
1045
1138
  "div",
1046
1139
  {
1047
- 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",
1048
- style: { bottom: controlsVisible ? "72px" : "16px", left: preview.left, transition: "bottom 0.2s" },
1049
- children: [
1050
- /* @__PURE__ */ jsx("div", { className: "overflow-hidden rounded-lg", style: { width: thumbW, height: thumbH }, children: isSprite ? (
1051
- // Inner div at native tile size, positioned to show the right sprite cell,
1052
- // then scaled up to fill thumbW×thumbH. transformOrigin top-left ensures
1053
- // the clip window aligns correctly.
1054
- /* @__PURE__ */ jsx("div", { style: {
1055
- width: srcW,
1056
- height: srcH,
1057
- backgroundImage: `url(${preview.cue.image})`,
1058
- backgroundPosition: `-${preview.cue.x ?? 0}px -${preview.cue.y ?? 0}px`,
1059
- backgroundSize: "auto",
1060
- backgroundRepeat: "no-repeat",
1061
- transform: `scale(${scale})`,
1062
- transformOrigin: "top left"
1063
- } })
1064
- ) : /* @__PURE__ */ jsx("div", { style: {
1065
- width: thumbW,
1066
- height: thumbH,
1067
- backgroundImage: `url(${preview.cue.image})`,
1068
- backgroundSize: "cover",
1069
- backgroundPosition: "center",
1070
- backgroundRepeat: "no-repeat"
1071
- } }) }),
1072
- /* @__PURE__ */ jsx("div", { className: "pt-1 text-center text-[11px] font-semibold text-white/75", children: formatTime(preview.time) })
1073
- ]
1140
+ className: "pointer-events-none absolute z-60 -translate-x-1/2 -translate-y-2 overflow-hidden rounded-xl shadow-2xl ring-1 ring-white/15",
1141
+ style: { bottom: controlsVisible ? "80px" : "20px", left: preview.left, transition: "bottom 0.2s" },
1142
+ children: isSprite ? /* @__PURE__ */ jsx("div", { style: { width: thumbW, height: thumbH, overflow: "hidden" }, children: /* @__PURE__ */ jsx("div", { style: {
1143
+ width: srcW,
1144
+ height: srcH,
1145
+ backgroundImage: `url(${preview.cue.image})`,
1146
+ backgroundPosition: `-${preview.cue.x ?? 0}px -${preview.cue.y ?? 0}px`,
1147
+ backgroundSize: "auto",
1148
+ backgroundRepeat: "no-repeat",
1149
+ transform: `scale(${scale})`,
1150
+ transformOrigin: "top left"
1151
+ } }) }) : /* @__PURE__ */ jsx("div", { style: {
1152
+ width: thumbW,
1153
+ height: thumbH,
1154
+ backgroundImage: `url(${preview.cue.image})`,
1155
+ backgroundSize: "cover",
1156
+ backgroundPosition: "center",
1157
+ backgroundRepeat: "no-repeat"
1158
+ } })
1074
1159
  }
1075
1160
  );
1076
1161
  })(),
@@ -1107,39 +1192,6 @@ function Video({
1107
1192
  );
1108
1193
  }
1109
1194
  var VideoPlayer = Video;
1110
- function SeekButton({ seconds, direction, onClick }) {
1111
- return /* @__PURE__ */ jsx(
1112
- "button",
1113
- {
1114
- type: "button",
1115
- onClick,
1116
- className: "grid size-8 place-items-center text-white transition hover:scale-110 hover:text-white/80 @sm:size-10",
1117
- "aria-label": `${direction === "back" ? "Rewind" : "Forward"} ${seconds} seconds`,
1118
- children: /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 36 36", fill: "none", className: "size-7 @sm:size-8", children: [
1119
- /* @__PURE__ */ jsx(
1120
- "path",
1121
- {
1122
- d: direction === "back" ? "M18 6C11.373 6 6 11.373 6 18s5.373 12 12 12 12-5.373 12-12" : "M18 6C24.627 6 30 11.373 30 18S24.627 30 18 30 6 24.627 6 18",
1123
- stroke: "currentColor",
1124
- strokeWidth: "2",
1125
- strokeLinecap: "round"
1126
- }
1127
- ),
1128
- /* @__PURE__ */ jsx(
1129
- "path",
1130
- {
1131
- d: direction === "back" ? "M18 6l-4 4 4 4" : "M18 6l4 4-4 4",
1132
- stroke: "currentColor",
1133
- strokeWidth: "2",
1134
- strokeLinecap: "round",
1135
- strokeLinejoin: "round"
1136
- }
1137
- ),
1138
- /* @__PURE__ */ jsx("text", { x: "18", y: "22", textAnchor: "middle", fill: "currentColor", fontSize: "9", fontWeight: "600", fontFamily: "system-ui", children: seconds })
1139
- ] })
1140
- }
1141
- );
1142
- }
1143
1195
  function parseVideoChildren(children) {
1144
1196
  const parsed = {
1145
1197
  sources: [],
@@ -1244,18 +1296,15 @@ function parseVttTimestamp(value) {
1244
1296
  return Number(normalized) || 0;
1245
1297
  }
1246
1298
  function formatTime(seconds) {
1247
- if (!Number.isFinite(seconds)) return "00:00";
1299
+ if (!Number.isFinite(seconds)) return "0:00";
1248
1300
  const safeSeconds = Math.max(0, Math.floor(seconds));
1249
1301
  const hours = Math.floor(safeSeconds / 3600);
1250
1302
  const minutes = Math.floor(safeSeconds % 3600 / 60);
1251
1303
  const secs = safeSeconds % 60;
1252
1304
  if (hours > 0) {
1253
- return `${hours}:${String(minutes).padStart(2, "0")}:${String(secs).padStart(
1254
- 2,
1255
- "0"
1256
- )}`;
1305
+ return `${hours}:${String(minutes).padStart(2, "0")}:${String(secs).padStart(2, "0")}`;
1257
1306
  }
1258
- return `${String(minutes).padStart(2, "0")}:${String(secs).padStart(2, "0")}`;
1307
+ return `${minutes}:${String(secs).padStart(2, "0")}`;
1259
1308
  }
1260
1309
 
1261
1310
  export { Source, Sources, Storyboard, StoryboardFrame, Subtitle, Subtitles, Video, VideoPlayer };