@geekapps/silo-elements-nextjs 0.2.42 → 0.2.44

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.d.ts CHANGED
@@ -2,7 +2,7 @@ export { ImageUploader } from './ImageUploader.js';
2
2
  export { VideoUploader } from './VideoUploader.js';
3
3
  export { FileUploader } from './FileUploader.js';
4
4
  export { MediaUploader } from './MediaUploader.js';
5
- export { Source, SourceProps, Sources, SourcesProps, Storyboard, StoryboardFrame, StoryboardFrameProps, StoryboardProps, Subtitle, SubtitleProps, Subtitles, SubtitlesProps, Video, VideoPlayer, VideoSourceType } from './VideoPlayer.js';
5
+ export { Captions, CaptionsProps, Source, SourceProps, Storyboard, StoryboardFrame, StoryboardFrameProps, StoryboardProps, Video, VideoPlayer, VideoSourceType, VideoThumbnail, ThumbnailProps as VideoThumbnailProps } from './VideoPlayer.js';
6
6
  export { DropZone } from './components/DropZone.js';
7
7
  export { ProgressBar } from './components/ProgressBar.js';
8
8
  import * as react from 'react';
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 { Pause, Play, VolumeX, Volume2, Captions, Settings, Minimize, Maximize } from 'lucide-react';
6
+ import { Pause, Play, VolumeX, Volume2, Captions as Captions$1, Settings, Minimize, Maximize } from 'lucide-react';
7
7
 
8
8
  // src/ImageUploader.tsx
9
9
 
@@ -1136,22 +1136,18 @@ var AUTO_QUALITY = {
1136
1136
  type: "auto"
1137
1137
  };
1138
1138
  var PLAYBACK_SPEEDS = [0.25, 0.5, 0.75, 1, 1.25, 1.5, 2];
1139
- function Sources(_props) {
1140
- return null;
1141
- }
1142
- Sources.displayName = "SiloSources";
1143
1139
  function Source(_props) {
1144
1140
  return null;
1145
1141
  }
1146
1142
  Source.displayName = "SiloSource";
1147
- function Subtitles(_props) {
1143
+ function Captions(_props) {
1148
1144
  return null;
1149
1145
  }
1150
- Subtitles.displayName = "SiloSubtitles";
1151
- function Subtitle(_props) {
1146
+ Captions.displayName = "SiloCaptions";
1147
+ function VideoThumbnail(_props) {
1152
1148
  return null;
1153
1149
  }
1154
- Subtitle.displayName = "SiloSubtitle";
1150
+ VideoThumbnail.displayName = "SiloVideoThumbnail";
1155
1151
  function Storyboard(_props) {
1156
1152
  return null;
1157
1153
  }
@@ -1163,7 +1159,6 @@ StoryboardFrame.displayName = "SiloStoryboardFrame";
1163
1159
  function Video({
1164
1160
  title,
1165
1161
  description,
1166
- poster,
1167
1162
  children,
1168
1163
  className,
1169
1164
  autoHideControls = true,
@@ -1172,14 +1167,40 @@ function Video({
1172
1167
  fixedHeight
1173
1168
  }) {
1174
1169
  const parsed = useMemo(() => parseVideoChildren(children), [children]);
1170
+ const [captions, setCaptions] = useState([]);
1171
+ const [poster, setPoster] = useState(void 0);
1172
+ useEffect(() => {
1173
+ if (!parsed.captionsSrc) {
1174
+ setCaptions([]);
1175
+ return;
1176
+ }
1177
+ let cancelled = false;
1178
+ fetch(parsed.captionsSrc, { cache: "no-store" }).then((r) => r.json()).then((data) => {
1179
+ if (!cancelled && Array.isArray(data)) {
1180
+ setCaptions(data.map((c, i) => ({ ...c, default: i === 0 })));
1181
+ }
1182
+ }).catch(() => {
1183
+ if (!cancelled) setCaptions([]);
1184
+ });
1185
+ return () => {
1186
+ cancelled = true;
1187
+ };
1188
+ }, [parsed.captionsSrc]);
1189
+ useEffect(() => {
1190
+ if (!parsed.thumbnailSrc) {
1191
+ setPoster(void 0);
1192
+ return;
1193
+ }
1194
+ setPoster(parsed.thumbnailSrc);
1195
+ }, [parsed.thumbnailSrc]);
1175
1196
  const initialSourceIndex = useMemo(() => {
1176
1197
  const index = parsed.sources.findIndex((source) => source.default);
1177
1198
  return index >= 0 ? index : 0;
1178
1199
  }, [parsed.sources]);
1179
1200
  const initialSubtitleMode = useMemo(() => {
1180
- const track = parsed.subtitles.find((subtitle) => subtitle.default);
1201
+ const track = captions.find((c) => c.default);
1181
1202
  return track?.srclang ?? "off";
1182
- }, [parsed.subtitles]);
1203
+ }, [captions]);
1183
1204
  const containerRef = useRef(null);
1184
1205
  const chromeRef = useRef(null);
1185
1206
  const playerRef = useRef(null);
@@ -1224,7 +1245,6 @@ function Video({
1224
1245
  const [isFullscreen, setIsFullscreen] = useState(false);
1225
1246
  const [playerHeight, setPlayerHeight] = useState(0);
1226
1247
  const [playerWidth, setPlayerWidth] = useState(0);
1227
- const [error, setError] = useState(null);
1228
1248
  const activeSource = parsed.sources[sourceIndex] ?? parsed.sources[0] ?? null;
1229
1249
  const progressPercent = duration ? currentTime / duration * 100 : 0;
1230
1250
  const bufferedPercent = duration ? bufferedTime / duration * 100 : 0;
@@ -1285,10 +1305,10 @@ function Video({
1285
1305
  }
1286
1306
  }, [sourceIndex, parsed.sources.length, initialSourceIndex]);
1287
1307
  useEffect(() => {
1288
- if (subtitleMode !== "off" && !parsed.subtitles.some((subtitle) => subtitle.srclang === subtitleMode)) {
1308
+ if (subtitleMode !== "off" && !captions.some((subtitle) => subtitle.srclang === subtitleMode)) {
1289
1309
  setSubtitleMode(initialSubtitleMode);
1290
1310
  }
1291
- }, [subtitleMode, parsed.subtitles, initialSubtitleMode]);
1311
+ }, [subtitleMode, captions, initialSubtitleMode]);
1292
1312
  useEffect(() => {
1293
1313
  const video = videoRef.current;
1294
1314
  if (!video) return;
@@ -1495,7 +1515,6 @@ function Video({
1495
1515
  return;
1496
1516
  }
1497
1517
  destroyMediaEngines();
1498
- setError(null);
1499
1518
  setIsLoading(true);
1500
1519
  setCurrentTime(0);
1501
1520
  setBufferedTime(0);
@@ -1540,13 +1559,13 @@ function Video({
1540
1559
  setIsLoading(false);
1541
1560
  });
1542
1561
  dash.on(dashjs.MediaPlayer.events.ERROR, () => {
1543
- setError("N\xE3o foi poss\xEDvel reproduzir o stream MPEG-DASH.");
1562
+ console.error("[Silo] MPEG-DASH playback failed");
1544
1563
  setIsLoading(false);
1545
1564
  });
1546
1565
  dash.initialize(video, activeSource.src, false);
1547
1566
  } catch {
1548
1567
  if (!cancelled) {
1549
- setError("N\xE3o foi poss\xEDvel carregar o player MPEG-DASH.");
1568
+ console.error("[Silo] MPEG-DASH player load failed");
1550
1569
  setIsLoading(false);
1551
1570
  }
1552
1571
  }
@@ -1612,7 +1631,7 @@ function Video({
1612
1631
  hls.recoverMediaError();
1613
1632
  return;
1614
1633
  }
1615
- setError("N\xE3o foi poss\xEDvel reproduzir o stream HLS.");
1634
+ console.error("[Silo] HLS playback failed");
1616
1635
  setIsLoading(false);
1617
1636
  });
1618
1637
  return;
@@ -1623,11 +1642,11 @@ function Video({
1623
1642
  setIsLoading(false);
1624
1643
  return;
1625
1644
  }
1626
- setError("Este navegador n\xE3o suporta HLS.");
1645
+ console.error("[Silo] HLS not supported in this browser");
1627
1646
  setIsLoading(false);
1628
1647
  } catch {
1629
1648
  if (!cancelled) {
1630
- setError("N\xE3o foi poss\xEDvel carregar o player HLS.");
1649
+ console.error("[Silo] HLS player load failed");
1631
1650
  setIsLoading(false);
1632
1651
  }
1633
1652
  }
@@ -1649,9 +1668,18 @@ function Video({
1649
1668
  const togglePlay = useCallback(async () => {
1650
1669
  const video = videoRef.current;
1651
1670
  if (!video) return;
1671
+ const wasPaused = video.paused;
1652
1672
  try {
1653
- const wasPaused = video.paused;
1654
1673
  if (wasPaused) {
1674
+ if (video.readyState < HTMLMediaElement.HAVE_FUTURE_DATA) {
1675
+ await new Promise((resolve) => {
1676
+ const onReady = () => {
1677
+ video.removeEventListener("canplay", onReady);
1678
+ resolve();
1679
+ };
1680
+ video.addEventListener("canplay", onReady);
1681
+ });
1682
+ }
1655
1683
  await video.play();
1656
1684
  } else {
1657
1685
  video.pause();
@@ -1664,7 +1692,6 @@ function Video({
1664
1692
  600
1665
1693
  );
1666
1694
  } catch {
1667
- setError("O navegador bloqueou a reprodu\xE7\xE3o autom\xE1tica.");
1668
1695
  }
1669
1696
  }, []);
1670
1697
  const seekRelative = useCallback((seconds) => {
@@ -1718,7 +1745,7 @@ function Video({
1718
1745
  }
1719
1746
  throw new Error("Fullscreen unavailable");
1720
1747
  } catch {
1721
- setError("N\xE3o foi poss\xEDvel alterar o modo fullscreen.");
1748
+ console.error("[Silo] Fullscreen toggle failed");
1722
1749
  }
1723
1750
  }, []);
1724
1751
  const changeAudio = useCallback((trackId) => {
@@ -1905,7 +1932,7 @@ function Video({
1905
1932
  preload: "metadata",
1906
1933
  crossOrigin: "anonymous",
1907
1934
  children: [
1908
- parsed.subtitles.map((subtitle) => /* @__PURE__ */ jsx(
1935
+ captions.map((subtitle) => /* @__PURE__ */ jsx(
1909
1936
  "track",
1910
1937
  {
1911
1938
  kind: "subtitles",
@@ -1953,7 +1980,6 @@ function Video({
1953
1980
  }
1954
1981
  ),
1955
1982
  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" }) }),
1956
- error && /* @__PURE__ */ jsx("div", { className: "absolute inset-x-8 top-1/2 z-40 -translate-y-1/2 rounded-2xl border border-white/10 bg-black/75 p-5 text-center text-sm text-white shadow-2xl backdrop-blur-xl", children: error }),
1957
1983
  /* @__PURE__ */ jsxs(
1958
1984
  "div",
1959
1985
  {
@@ -2013,11 +2039,11 @@ function Video({
2013
2039
  label: "Qualidade",
2014
2040
  value: qualities.find((q) => q.id === selectedQuality)?.label ?? "Auto"
2015
2041
  },
2016
- ...parsed.subtitles.length > 0 ? [
2042
+ ...captions.length > 0 ? [
2017
2043
  {
2018
2044
  id: "subtitles",
2019
2045
  label: "Legendas",
2020
- value: subtitleStyle.track === "off" ? "Desligado" : parsed.subtitles.find(
2046
+ value: subtitleStyle.track === "off" ? "Desligado" : captions.find(
2021
2047
  (s) => s.srclang === subtitleStyle.track
2022
2048
  )?.label ?? subtitleStyle.track
2023
2049
  }
@@ -2174,7 +2200,7 @@ function Video({
2174
2200
  ),
2175
2201
  /* @__PURE__ */ jsx("div", { className: "py-1.5", children: [
2176
2202
  { srclang: "off", label: "Desligado" },
2177
- ...parsed.subtitles
2203
+ ...captions
2178
2204
  ].map((s) => /* @__PURE__ */ jsxs(
2179
2205
  "button",
2180
2206
  {
@@ -2574,16 +2600,16 @@ function Video({
2574
2600
  ) })
2575
2601
  ] }),
2576
2602
  /* @__PURE__ */ jsx("div", { className: "mx-0.5 h-4 w-px bg-white/20 @md:mx-1" }),
2577
- parsed.subtitles.length > 0 && /* @__PURE__ */ jsx(
2603
+ captions.length > 0 && /* @__PURE__ */ jsx(
2578
2604
  "button",
2579
2605
  {
2580
2606
  type: "button",
2581
2607
  onClick: () => setSubtitleMode(
2582
- (m) => m === "off" ? parsed.subtitles[0]?.srclang ?? "off" : "off"
2608
+ (m) => m === "off" ? captions[0]?.srclang ?? "off" : "off"
2583
2609
  ),
2584
2610
  className: `grid size-8 place-items-center rounded transition hover:text-white/80 @sm:size-10${subtitleMode !== "off" ? "text-white" : "text-white/60"}`,
2585
2611
  "aria-label": "Captions",
2586
- children: /* @__PURE__ */ jsx(Captions, { className: "size-4 @sm:size-5" })
2612
+ children: /* @__PURE__ */ jsx(Captions$1, { className: "size-4 @sm:size-5" })
2587
2613
  }
2588
2614
  ),
2589
2615
  /* @__PURE__ */ jsx("div", { className: "relative", children: /* @__PURE__ */ jsx(
@@ -2711,8 +2737,7 @@ function Video({
2711
2737
  var VideoPlayer = Video;
2712
2738
  function parseVideoChildren(children) {
2713
2739
  const parsed = {
2714
- sources: [],
2715
- subtitles: []
2740
+ sources: []
2716
2741
  };
2717
2742
  function dn(child) {
2718
2743
  return child.type?.displayName ?? child.type?.name ?? "";
@@ -2720,25 +2745,17 @@ function parseVideoChildren(children) {
2720
2745
  React.Children.forEach(children, (child) => {
2721
2746
  if (!React.isValidElement(child)) return;
2722
2747
  const name = dn(child);
2723
- if (child.type === Sources || name === "SiloSources") {
2748
+ if (child.type === Source || name === "SiloSource") {
2724
2749
  const element = child;
2725
- React.Children.forEach(element.props.children, (sourceChild) => {
2726
- if (!React.isValidElement(sourceChild)) return;
2727
- const sn = dn(sourceChild);
2728
- if (sourceChild.type !== Source && sn !== "SiloSource") return;
2729
- const sourceElement = sourceChild;
2730
- parsed.sources.push(sourceElement.props);
2731
- });
2750
+ parsed.sources.push(element.props);
2732
2751
  }
2733
- if (child.type === Subtitles || name === "SiloSubtitles") {
2752
+ if (child.type === Captions || name === "SiloCaptions") {
2734
2753
  const element = child;
2735
- React.Children.forEach(element.props.children, (subtitleChild) => {
2736
- if (!React.isValidElement(subtitleChild)) return;
2737
- const sn = dn(subtitleChild);
2738
- if (subtitleChild.type !== Subtitle && sn !== "SiloSubtitle") return;
2739
- const subtitleElement = subtitleChild;
2740
- parsed.subtitles.push(subtitleElement.props);
2741
- });
2754
+ parsed.captionsSrc = element.props.src;
2755
+ }
2756
+ if (child.type === VideoThumbnail || name === "SiloVideoThumbnail") {
2757
+ const element = child;
2758
+ parsed.thumbnailSrc = element.props.src;
2742
2759
  }
2743
2760
  if (child.type === Storyboard || name === "SiloStoryboard") {
2744
2761
  const element = child;
@@ -3298,6 +3315,6 @@ function Badge({ children, muted }) {
3298
3315
  );
3299
3316
  }
3300
3317
 
3301
- export { Avatar, Background, DropZone, FileCard, FileIcon, FilePreview, FileUploader, ImageOptions, ImageUploader, MediaUploader, ProgressBar, Source, Sources, Storyboard, StoryboardFrame, Subtitle, Subtitles, Thumbnail, Video, VideoOptions, VideoPlayer, VideoUploader, defaultTheme, resolveTheme };
3318
+ export { Avatar, Background, Captions, DropZone, FileCard, FileIcon, FilePreview, FileUploader, ImageOptions, ImageUploader, MediaUploader, ProgressBar, Source, Storyboard, StoryboardFrame, Thumbnail, Video, VideoOptions, VideoPlayer, VideoThumbnail, VideoUploader, defaultTheme, resolveTheme };
3302
3319
  //# sourceMappingURL=index.js.map
3303
3320
  //# sourceMappingURL=index.js.map