@geekapps/silo-elements-nextjs 0.2.28 → 0.2.30

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.
@@ -45,6 +45,8 @@ type VideoProps = {
45
45
  autoHideControls?: boolean;
46
46
  defaultVolume?: number;
47
47
  maxHeight?: string | number;
48
+ /** Fixed height — disables aspect-ratio so the player stays at exactly this height regardless of video dimensions */
49
+ fixedHeight?: string | number;
48
50
  };
49
51
  declare function Sources(_props: SourcesProps): null;
50
52
  declare function Source(_props: SourceProps): null;
@@ -52,7 +54,7 @@ declare function Subtitles(_props: SubtitlesProps): null;
52
54
  declare function Subtitle(_props: SubtitleProps): null;
53
55
  declare function Storyboard(_props: StoryboardProps): null;
54
56
  declare function StoryboardFrame(_props: StoryboardFrameProps): null;
55
- declare function Video({ title, description, poster, children, className, autoHideControls, defaultVolume, maxHeight, }: VideoProps): react__default.JSX.Element;
57
+ declare function Video({ title, description, poster, children, className, autoHideControls, defaultVolume, maxHeight, fixedHeight, }: VideoProps): react__default.JSX.Element;
56
58
  declare const VideoPlayer: typeof Video;
57
59
 
58
60
  export { Source, type SourceProps, Sources, type SourcesProps, Storyboard, StoryboardFrame, type StoryboardFrameProps, type StoryboardProps, Subtitle, type SubtitleProps, Subtitles, type SubtitlesProps, Video, VideoPlayer, type VideoSourceType };
@@ -35,7 +35,8 @@ function Video({
35
35
  className,
36
36
  autoHideControls = true,
37
37
  defaultVolume = 0.72,
38
- maxHeight
38
+ maxHeight,
39
+ fixedHeight
39
40
  }) {
40
41
  const parsed = useMemo(() => parseVideoChildren(children), [children]);
41
42
  const initialSourceIndex = useMemo(() => {
@@ -87,6 +88,7 @@ function Video({
87
88
  const [isMuted, setIsMuted] = useState(false);
88
89
  const [isFullscreen, setIsFullscreen] = useState(false);
89
90
  const [playerHeight, setPlayerHeight] = useState(0);
91
+ const [playerWidth, setPlayerWidth] = useState(0);
90
92
  const [error, setError] = useState(null);
91
93
  const activeSource = parsed.sources[sourceIndex] ?? parsed.sources[0] ?? null;
92
94
  const progressPercent = duration ? currentTime / duration * 100 : 0;
@@ -272,7 +274,10 @@ function Video({
272
274
  if (!player) return;
273
275
  const ro = new ResizeObserver((entries) => {
274
276
  const entry = entries[0];
275
- if (entry) setPlayerHeight(entry.contentRect.height);
277
+ if (entry) {
278
+ setPlayerHeight(entry.contentRect.height);
279
+ setPlayerWidth(entry.contentRect.width);
280
+ }
276
281
  });
277
282
  ro.observe(player);
278
283
  return () => ro.disconnect();
@@ -687,7 +692,7 @@ function Video({
687
692
  }
688
693
  },
689
694
  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",
690
- style: maxHeight ? { maxHeight: typeof maxHeight === "number" ? `${maxHeight}px` : maxHeight, aspectRatio: "16/9" } : { aspectRatio: "16/9" },
695
+ style: fixedHeight ? { height: typeof fixedHeight === "number" ? `${fixedHeight}px` : fixedHeight } : maxHeight ? { maxHeight: typeof maxHeight === "number" ? `${maxHeight}px` : maxHeight, aspectRatio: "16/9" } : { aspectRatio: "16/9" },
691
696
  children: [
692
697
  /* @__PURE__ */ jsxs(
693
698
  "video",
@@ -904,7 +909,7 @@ function Video({
904
909
  ] }),
905
910
  /* @__PURE__ */ jsx("style", { children: `@keyframes spFadeIn{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:translateY(0)}}` })
906
911
  ] }),
907
- /* @__PURE__ */ jsxs(
912
+ /* @__PURE__ */ jsx(
908
913
  "div",
909
914
  {
910
915
  ref: progressRef,
@@ -912,56 +917,22 @@ function Video({
912
917
  onPointerLeave: handleProgressPointerLeave,
913
918
  onPointerDown: handleProgressPointerDown,
914
919
  className: "group relative mb-2 h-5 cursor-pointer",
915
- children: [
916
- preview && (() => {
917
- const srcW = preview.cue.w ?? 160;
918
- const srcH = preview.cue.h ?? 90;
919
- const aspect = srcW / srcH;
920
- const thumbH = Math.max(120, Math.min(playerHeight * 0.25, 300));
921
- const thumbW = Math.round(thumbH * aspect);
922
- const scale = thumbH / srcH;
923
- return /* @__PURE__ */ jsxs(
924
- "div",
925
- {
926
- className: "pointer-events-none absolute bottom-10 z-60 -translate-x-1/2 rounded-xl bg-black/80 p-1.5 shadow-2xl ring-1 ring-white/15 backdrop-blur",
927
- style: { left: preview.left },
928
- children: [
929
- /* @__PURE__ */ jsx(
930
- "div",
931
- {
932
- className: "overflow-hidden rounded-lg bg-neutral-900",
933
- style: {
934
- width: thumbW,
935
- height: thumbH,
936
- backgroundImage: `url(${preview.cue.image})`,
937
- backgroundPosition: preview.cue.x != null && preview.cue.y != null ? `-${preview.cue.x * scale}px -${preview.cue.y * scale}px` : "center",
938
- backgroundSize: preview.cue.x != null ? `auto ${thumbH}px` : "cover",
939
- backgroundRepeat: "no-repeat"
940
- }
941
- }
942
- ),
943
- /* @__PURE__ */ jsx("div", { className: "pt-1.5 text-center text-xs font-semibold text-white/80", children: formatTime(preview.time) })
944
- ]
945
- }
946
- );
947
- })(),
948
- /* @__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: [
949
- /* @__PURE__ */ jsx(
950
- "div",
951
- {
952
- className: "absolute inset-y-0 left-0 bg-white/30",
953
- style: { width: `${bufferedPercent}%` }
954
- }
955
- ),
956
- /* @__PURE__ */ jsx(
957
- "div",
958
- {
959
- className: "absolute inset-y-0 left-0 bg-white/85",
960
- style: { width: `${progressPercent}%` }
961
- }
962
- )
963
- ] })
964
- ]
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(
922
+ "div",
923
+ {
924
+ className: "absolute inset-y-0 left-0 bg-white/30",
925
+ style: { width: `${bufferedPercent}%` }
926
+ }
927
+ ),
928
+ /* @__PURE__ */ jsx(
929
+ "div",
930
+ {
931
+ className: "absolute inset-y-0 left-0 bg-white/85",
932
+ style: { width: `${progressPercent}%` }
933
+ }
934
+ )
935
+ ] })
965
936
  }
966
937
  ),
967
938
  /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2", children: [
@@ -1063,10 +1034,50 @@ function Video({
1063
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" }) })
1064
1035
  }
1065
1036
  ),
1037
+ preview && (() => {
1038
+ const srcW = preview.cue.w ?? 160;
1039
+ const srcH = preview.cue.h ?? 90;
1040
+ const thumbW = Math.max(120, Math.round((playerWidth || 640) * 0.1));
1041
+ const thumbH = Math.round(thumbW * (srcH / srcW));
1042
+ const scale = thumbW / srcW;
1043
+ const isSprite = preview.cue.x != null && preview.cue.y != null;
1044
+ return /* @__PURE__ */ jsxs(
1045
+ "div",
1046
+ {
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
+ ]
1074
+ }
1075
+ );
1076
+ })(),
1066
1077
  activeCue && /* @__PURE__ */ jsx(
1067
1078
  "div",
1068
1079
  {
1069
- 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"}`,
1080
+ 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"}`,
1070
1081
  children: /* @__PURE__ */ jsx(
1071
1082
  "div",
1072
1083
  {