@geekapps/silo-elements-nextjs 0.2.24 → 0.2.26

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
@@ -1260,7 +1260,7 @@ function Video({
1260
1260
  const [audioTracks, setAudioTracks] = useState([]);
1261
1261
  const [selectedAudio, setSelectedAudio] = useState(0);
1262
1262
  const [settingsOpen, setSettingsOpen] = useState(false);
1263
- const [settingsTab, setSettingsTab] = useState("quality");
1263
+ const [settingsTab, setSettingsTab] = useState("root");
1264
1264
  const [playbackRate, setPlaybackRate] = useState(1);
1265
1265
  const [subtitleStyle, setSubtitleStyle] = useState({
1266
1266
  track: initialSubtitleMode,
@@ -1286,6 +1286,7 @@ function Video({
1286
1286
  const [volume, setVolume] = useState(defaultVolume);
1287
1287
  const [isMuted, setIsMuted] = useState(false);
1288
1288
  const [isFullscreen, setIsFullscreen] = useState(false);
1289
+ const [playerHeight, setPlayerHeight] = useState(0);
1289
1290
  const [error, setError] = useState(null);
1290
1291
  const activeSource = parsed.sources[sourceIndex] ?? parsed.sources[0] ?? null;
1291
1292
  const progressPercent = duration ? currentTime / duration * 100 : 0;
@@ -1466,6 +1467,16 @@ function Video({
1466
1467
  video?.removeEventListener("webkitendfullscreen", onFullscreenChange);
1467
1468
  };
1468
1469
  }, []);
1470
+ useEffect(() => {
1471
+ const player = playerRef.current;
1472
+ if (!player) return;
1473
+ const ro = new ResizeObserver((entries) => {
1474
+ const entry = entries[0];
1475
+ if (entry) setPlayerHeight(entry.contentRect.height);
1476
+ });
1477
+ ro.observe(player);
1478
+ return () => ro.disconnect();
1479
+ }, []);
1469
1480
  useEffect(() => {
1470
1481
  let cancelled = false;
1471
1482
  async function loadStoryboard() {
@@ -1937,8 +1948,8 @@ function Video({
1937
1948
  /* @__PURE__ */ jsx("div", { className: "pointer-events-none absolute inset-x-0 bottom-0 h-40 bg-linear-to-t from-black/80 to-transparent" }),
1938
1949
  /* @__PURE__ */ jsxs("header", { onClick: (e) => e.stopPropagation(), className: "relative z-10 flex items-start justify-between gap-4 px-4 pt-4 text-white @sm:px-7 @sm:pt-7 @lg:px-9 @lg:pt-8", children: [
1939
1950
  /* @__PURE__ */ jsxs("div", { children: [
1940
- title && /* @__PURE__ */ jsx("h1", { className: "text-sm font-bold tracking-wide @sm:text-base @md:text-lg @lg:text-xl", style: { textShadow: "0 1px 6px rgba(0,0,0,0.6)" }, children: title }),
1941
- description && /* @__PURE__ */ jsx("p", { className: "mt-1 text-xs font-medium text-white/85 @sm:text-sm", children: description })
1951
+ title && isFullscreen && /* @__PURE__ */ jsx("h1", { className: "text-sm font-bold tracking-wide @sm:text-base @md:text-lg @lg:text-xl", style: { textShadow: "0 1px 6px rgba(0,0,0,0.6)" }, children: title }),
1952
+ description && isFullscreen && /* @__PURE__ */ jsx("p", { className: "mt-1 text-xs font-medium text-white/85 @sm:text-sm", children: description })
1942
1953
  ] }),
1943
1954
  parsed.sources.length > 1 && /* @__PURE__ */ jsx(
1944
1955
  "select",
@@ -1954,111 +1965,143 @@ function Video({
1954
1965
  /* @__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
1966
  settingsOpen && /* @__PURE__ */ jsxs(Fragment, { children: [
1956
1967
  /* @__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",
1968
+ /* @__PURE__ */ jsxs("div", { className: "absolute bottom-full right-3 z-50 mb-2 w-56 overflow-hidden rounded-xl border border-white/10 bg-black/90 shadow-2xl backdrop-blur-xl @sm:right-5 @lg:right-9", children: [
1969
+ /* @__PURE__ */ jsxs(
1970
+ "div",
1960
1971
  {
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
- ]
1972
+ style: {
1973
+ display: settingsTab === "root" ? "block" : "none",
1974
+ animation: settingsTab === "root" ? "settingsSlideIn 0.18s ease" : void 0
1978
1975
  },
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(
1976
+ children: [
1977
+ /* @__PURE__ */ jsx("div", { className: "px-3 py-2 text-[10px] font-semibold uppercase tracking-wider text-white/35", children: "Settings" }),
1978
+ [
1979
+ { id: "quality", label: "Quality", value: qualities.find((q) => q.id === selectedQuality)?.label ?? "Auto" },
1980
+ ...parsed.subtitles.length > 0 ? [{ id: "subtitles", label: "Subtitles / CC", value: subtitleStyle.track === "off" ? "Off" : parsed.subtitles.find((s) => s.srclang === subtitleStyle.track)?.label ?? subtitleStyle.track }] : [],
1981
+ ...audioTracks.length > 1 ? [{ id: "audio", label: "Audio", value: audioTracks.find((t) => t.id === selectedAudio)?.label ?? "" }] : [],
1982
+ { id: "playback", label: "Speed", value: playbackRate === 1 ? "Normal" : `${playbackRate}x` }
1983
+ ].map((item) => /* @__PURE__ */ jsxs(
2015
1984
  "button",
2016
1985
  {
2017
1986
  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 }
1987
+ onClick: () => setSettingsTab(item.id),
1988
+ className: "flex w-full items-center justify-between gap-3 px-4 py-2.5 text-left text-sm font-medium text-white/80 transition hover:bg-white/10 hover:text-white",
1989
+ children: [
1990
+ /* @__PURE__ */ jsx("span", { children: item.label }),
1991
+ /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1 text-xs text-white/40", children: [
1992
+ item.value,
1993
+ /* @__PURE__ */ jsx("svg", { className: "size-3.5 opacity-50", viewBox: "0 0 16 16", fill: "none", children: /* @__PURE__ */ jsx("path", { d: "M6 4l4 4-4 4", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) })
1994
+ ] })
1995
+ ]
2021
1996
  },
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(
1997
+ item.id
1998
+ ))
1999
+ ]
2000
+ },
2001
+ "root"
2002
+ ),
2003
+ ["quality", "subtitles", "audio", "playback"].map((tab) => /* @__PURE__ */ jsxs(
2004
+ "div",
2005
+ {
2006
+ style: {
2007
+ display: settingsTab === tab ? "block" : "none",
2008
+ animation: settingsTab === tab ? "settingsSlideIn 0.18s ease" : void 0
2009
+ },
2010
+ children: [
2011
+ /* @__PURE__ */ jsxs(
2028
2012
  "button",
2029
2013
  {
2030
2014
  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
- ] })
2015
+ onClick: () => setSettingsTab("root"),
2016
+ className: "flex w-full items-center gap-2 border-b border-white/10 px-3 py-2.5 text-xs font-semibold text-white/60 transition hover:text-white",
2017
+ children: [
2018
+ /* @__PURE__ */ jsx("svg", { className: "size-3.5", viewBox: "0 0 16 16", fill: "none", children: /* @__PURE__ */ jsx("path", { d: "M10 4L6 8l4 4", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) }),
2019
+ tab === "quality" ? "Quality" : tab === "subtitles" ? "Subtitles / CC" : tab === "audio" ? "Audio" : "Speed"
2020
+ ]
2021
+ }
2022
+ ),
2023
+ /* @__PURE__ */ jsxs("div", { className: "max-h-52 overflow-y-auto py-1", children: [
2024
+ tab === "quality" && [...qualities].reverse().map((quality) => /* @__PURE__ */ jsxs(SettingsItem, { active: selectedQuality === quality.id, onClick: () => {
2025
+ changeQuality(quality.id);
2026
+ setSettingsTab("root");
2027
+ }, children: [
2028
+ quality.label,
2029
+ quality.id === "auto" && /* @__PURE__ */ jsx("span", { className: "ml-1 text-[10px] text-white/40", children: "ABR" })
2030
+ ] }, quality.id)),
2031
+ tab === "subtitles" && /* @__PURE__ */ jsxs("div", { className: "px-3 py-2 space-y-3", children: [
2032
+ /* @__PURE__ */ jsxs("div", { children: [
2033
+ /* @__PURE__ */ jsx("p", { className: "mb-1.5 text-[10px] font-semibold uppercase tracking-wider text-white/35", children: "Track" }),
2034
+ /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-1", children: [{ srclang: "off", label: "Off" }, ...parsed.subtitles].map((s) => /* @__PURE__ */ jsx(
2035
+ "button",
2036
+ {
2037
+ type: "button",
2038
+ onClick: () => {
2039
+ const next = s.srclang === "off" ? "off" : s.srclang;
2040
+ setSubtitleMode(next);
2041
+ setSubtitleStyle((st) => ({ ...st, track: next }));
2042
+ },
2043
+ 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"}`,
2044
+ children: s.label
2045
+ },
2046
+ s.srclang
2047
+ )) })
2048
+ ] }),
2049
+ /* @__PURE__ */ jsxs("div", { children: [
2050
+ /* @__PURE__ */ jsx("p", { className: "mb-1.5 text-[10px] font-semibold uppercase tracking-wider text-white/35", children: "Size" }),
2051
+ /* @__PURE__ */ jsx("div", { className: "flex gap-1", children: ["small", "medium", "large", "xlarge"].map((s) => /* @__PURE__ */ jsx(
2052
+ "button",
2053
+ {
2054
+ type: "button",
2055
+ onClick: () => setSubtitleStyle((st) => ({ ...st, size: s })),
2056
+ 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"}`,
2057
+ children: s === "xlarge" ? "XL" : s.charAt(0).toUpperCase() + s.slice(1)
2058
+ },
2059
+ s
2060
+ )) })
2061
+ ] }),
2062
+ /* @__PURE__ */ jsxs("div", { children: [
2063
+ /* @__PURE__ */ jsx("p", { className: "mb-1.5 text-[10px] font-semibold uppercase tracking-wider text-white/35", children: "Color" }),
2064
+ /* @__PURE__ */ jsx("div", { className: "flex gap-2", children: [["white", "#fff"], ["yellow", "#facc15"], ["cyan", "#22d3ee"]].map(([c, hex]) => /* @__PURE__ */ jsx(
2065
+ "button",
2066
+ {
2067
+ type: "button",
2068
+ onClick: () => setSubtitleStyle((st) => ({ ...st, color: c })),
2069
+ className: `size-5 rounded-full ring-2 transition ${subtitleStyle.color === c ? "ring-white" : "ring-transparent"}`,
2070
+ style: { backgroundColor: hex }
2071
+ },
2072
+ c
2073
+ )) })
2074
+ ] }),
2075
+ /* @__PURE__ */ jsxs("div", { children: [
2076
+ /* @__PURE__ */ jsx("p", { className: "mb-1.5 text-[10px] font-semibold uppercase tracking-wider text-white/35", children: "Background" }),
2077
+ /* @__PURE__ */ jsx("div", { className: "flex gap-1", children: [["none", "None"], ["semi", "Semi"], ["solid", "Solid"]].map(([v, label]) => /* @__PURE__ */ jsx(
2078
+ "button",
2079
+ {
2080
+ type: "button",
2081
+ onClick: () => setSubtitleStyle((st) => ({ ...st, bg: v })),
2082
+ 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"}`,
2083
+ children: label
2084
+ },
2085
+ v
2086
+ )) })
2087
+ ] })
2088
+ ] }),
2089
+ tab === "audio" && audioTracks.map((track) => /* @__PURE__ */ jsx(SettingsItem, { active: selectedAudio === track.id, onClick: () => {
2090
+ changeAudio(track.id);
2091
+ setSettingsTab("root");
2092
+ }, children: track.label }, track.id)),
2093
+ tab === "playback" && PLAYBACK_SPEEDS.map((speed) => /* @__PURE__ */ jsx(SettingsItem, { active: playbackRate === speed, onClick: () => {
2094
+ setPlaybackRate(speed);
2095
+ setSettingsOpen(false);
2096
+ setSettingsTab("root");
2097
+ }, children: speed === 1 ? "Normal" : `${speed}x` }, speed))
2098
+ ] })
2099
+ ]
2100
+ },
2101
+ tab
2102
+ ))
2103
+ ] }),
2104
+ /* @__PURE__ */ jsx("style", { children: `@keyframes settingsSlideIn{from{opacity:0;transform:translateX(8px)}to{opacity:1;transform:translateX(0)}}` })
2062
2105
  ] }),
2063
2106
  /* @__PURE__ */ jsxs(
2064
2107
  "div",
@@ -2193,7 +2236,10 @@ function Video({
2193
2236
  "button",
2194
2237
  {
2195
2238
  type: "button",
2196
- onClick: () => setSettingsOpen((v) => !v),
2239
+ onClick: () => {
2240
+ setSettingsOpen((v) => !v);
2241
+ setSettingsTab("root");
2242
+ },
2197
2243
  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
2244
  "aria-label": "Settings",
2199
2245
  children: [
@@ -2233,13 +2279,19 @@ function Video({
2233
2279
  children: /* @__PURE__ */ jsx(
2234
2280
  "div",
2235
2281
  {
2236
- className: "max-w-3xl rounded-lg px-4 py-2 text-center font-medium leading-snug",
2282
+ className: "max-w-[80%] rounded-lg px-4 py-1.5 text-center font-medium leading-snug",
2237
2283
  style: {
2238
- fontSize: subtitleStyle.size === "small" ? "0.8rem" : subtitleStyle.size === "large" ? "1.25rem" : "1rem",
2284
+ fontSize: (() => {
2285
+ const base = Math.max(12, Math.min(playerHeight * 0.028, 32));
2286
+ if (subtitleStyle.size === "small") return `${base * 0.75}px`;
2287
+ if (subtitleStyle.size === "large") return `${base * 1.35}px`;
2288
+ if (subtitleStyle.size === "xlarge") return `${base * 1.8}px`;
2289
+ return `${base}px`;
2290
+ })(),
2239
2291
  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)"
2292
+ backgroundColor: subtitleStyle.bg === "none" ? "transparent" : subtitleStyle.bg === "solid" ? "rgba(0,0,0,0.9)" : "rgba(0,0,0,0.55)",
2293
+ backdropFilter: subtitleStyle.bg === "semi" ? "blur(6px)" : void 0,
2294
+ textShadow: subtitleStyle.bg === "none" ? "0 1px 8px rgba(0,0,0,1), 0 0 16px rgba(0,0,0,0.9)" : "0 1px 3px rgba(0,0,0,0.5)"
2243
2295
  },
2244
2296
  children: activeCue
2245
2297
  }