@xhub-reel/feed 0.2.0 → 0.2.2

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.mts CHANGED
@@ -38,6 +38,8 @@ interface VideoFeedProps {
38
38
  gesturesDisabled?: boolean;
39
39
  /** Enable haptic feedback on swipe */
40
40
  hapticEnabled?: boolean;
41
+ /** Whether video should start muted (default: true for browser autoplay policy) */
42
+ initialMuted?: boolean;
41
43
  /** Custom styles override */
42
44
  style?: CSSProperties;
43
45
  /** Custom className (for external CSS if needed) */
@@ -128,6 +130,8 @@ interface VideoFeedItemProps {
128
130
  isActive?: boolean;
129
131
  /** Preload priority */
130
132
  priority?: PreloadPriority;
133
+ /** Whether video should start muted (default: true for browser autoplay policy) */
134
+ initialMuted?: boolean;
131
135
  /** Show timeline (default: true, only used with default children) */
132
136
  showTimeline?: boolean;
133
137
  /** Called when video is liked */
@@ -192,6 +196,8 @@ interface VideoFeedItemContextValue {
192
196
  preload: '' | 'none' | 'metadata' | 'auto';
193
197
  /** Video has been preloaded and first frame is ready */
194
198
  isPreloaded: boolean;
199
+ /** Whether video should start muted (default: true for browser autoplay policy) */
200
+ initialMuted: boolean;
195
201
  containerRef: RefObject<HTMLDivElement | null>;
196
202
  videoRef: RefObject<HTMLVideoElement | null>;
197
203
  isPlaying: boolean;
@@ -259,6 +265,12 @@ interface ConnectedVideoFeedProps extends Omit<VideoFeedProps, 'videos' | 'isLoa
259
265
  * Initial videos to show while loading (optional)
260
266
  */
261
267
  initialVideos?: Video[];
268
+ /**
269
+ * Whether video should start muted
270
+ * Set to false if you have already handled browser autoplay policy
271
+ * @default true
272
+ */
273
+ initialMuted?: boolean;
262
274
  /**
263
275
  * Called when videos are successfully fetched
264
276
  */
package/dist/index.d.ts CHANGED
@@ -38,6 +38,8 @@ interface VideoFeedProps {
38
38
  gesturesDisabled?: boolean;
39
39
  /** Enable haptic feedback on swipe */
40
40
  hapticEnabled?: boolean;
41
+ /** Whether video should start muted (default: true for browser autoplay policy) */
42
+ initialMuted?: boolean;
41
43
  /** Custom styles override */
42
44
  style?: CSSProperties;
43
45
  /** Custom className (for external CSS if needed) */
@@ -128,6 +130,8 @@ interface VideoFeedItemProps {
128
130
  isActive?: boolean;
129
131
  /** Preload priority */
130
132
  priority?: PreloadPriority;
133
+ /** Whether video should start muted (default: true for browser autoplay policy) */
134
+ initialMuted?: boolean;
131
135
  /** Show timeline (default: true, only used with default children) */
132
136
  showTimeline?: boolean;
133
137
  /** Called when video is liked */
@@ -192,6 +196,8 @@ interface VideoFeedItemContextValue {
192
196
  preload: '' | 'none' | 'metadata' | 'auto';
193
197
  /** Video has been preloaded and first frame is ready */
194
198
  isPreloaded: boolean;
199
+ /** Whether video should start muted (default: true for browser autoplay policy) */
200
+ initialMuted: boolean;
195
201
  containerRef: RefObject<HTMLDivElement | null>;
196
202
  videoRef: RefObject<HTMLVideoElement | null>;
197
203
  isPlaying: boolean;
@@ -259,6 +265,12 @@ interface ConnectedVideoFeedProps extends Omit<VideoFeedProps, 'videos' | 'isLoa
259
265
  * Initial videos to show while loading (optional)
260
266
  */
261
267
  initialVideos?: Video[];
268
+ /**
269
+ * Whether video should start muted
270
+ * Set to false if you have already handled browser autoplay policy
271
+ * @default true
272
+ */
273
+ initialMuted?: boolean;
262
274
  /**
263
275
  * Called when videos are successfully fetched
264
276
  */
package/dist/index.js CHANGED
@@ -21,7 +21,7 @@ var videoFeedItemStyles = {
21
21
  inset: 0,
22
22
  width: "100%",
23
23
  height: "100%",
24
- objectFit: "cover"
24
+ objectFit: "contain"
25
25
  },
26
26
  placeholder: {
27
27
  position: "absolute",
@@ -359,6 +359,7 @@ function useVideoFeedItemState({
359
359
  video,
360
360
  isActive,
361
361
  priority,
362
+ initialMuted = true,
362
363
  onLike,
363
364
  onComment,
364
365
  onShare,
@@ -419,14 +420,24 @@ function useVideoFeedItemState({
419
420
  const play = react.useCallback(async () => {
420
421
  const videoEl = videoRef.current;
421
422
  if (videoEl) {
422
- videoEl.muted = true;
423
+ videoEl.muted = initialMuted;
423
424
  try {
424
425
  await videoEl.play();
425
426
  } catch (err) {
426
- console.warn("[VideoFeedItem] Play failed:", err.message);
427
+ if (err.name === "NotAllowedError" && !initialMuted) {
428
+ console.warn("[VideoFeedItem] Autoplay blocked, falling back to muted");
429
+ videoEl.muted = true;
430
+ try {
431
+ await videoEl.play();
432
+ } catch (mutedErr) {
433
+ console.warn("[VideoFeedItem] Play failed even muted:", mutedErr.message);
434
+ }
435
+ } else {
436
+ console.warn("[VideoFeedItem] Play failed:", err.message);
437
+ }
427
438
  }
428
439
  }
429
- }, []);
440
+ }, [initialMuted]);
430
441
  const pause = react.useCallback(() => {
431
442
  const videoEl = videoRef.current;
432
443
  if (videoEl) {
@@ -604,6 +615,7 @@ function useVideoFeedItemState({
604
615
  shouldRenderVideo,
605
616
  preload,
606
617
  isPreloaded,
618
+ initialMuted,
607
619
  containerRef,
608
620
  videoRef,
609
621
  isPlaying: effectiveIsPlaying,
@@ -628,7 +640,7 @@ function useVideoFeedItemState({
628
640
  }
629
641
  var VideoFeedItemPlayer = react.forwardRef(
630
642
  ({ placeholder, ...props }, ref) => {
631
- const { video, videoRef, shouldRenderVideo, preload, isPreloaded } = useVideoFeedItemContext();
643
+ const { video, videoRef, shouldRenderVideo, preload, isPreloaded, initialMuted } = useVideoFeedItemContext();
632
644
  if (!shouldRenderVideo) {
633
645
  return placeholder ?? /* @__PURE__ */ jsxRuntime.jsx(
634
646
  "div",
@@ -659,7 +671,7 @@ var VideoFeedItemPlayer = react.forwardRef(
659
671
  preload,
660
672
  loop: true,
661
673
  playsInline: true,
662
- muted: true,
674
+ muted: initialMuted,
663
675
  style: videoFeedItemStyles.video
664
676
  }
665
677
  );
@@ -852,6 +864,7 @@ var VideoFeedItem = react.forwardRef(
852
864
  video,
853
865
  isActive = false,
854
866
  priority = "none",
867
+ initialMuted = true,
855
868
  showTimeline = true,
856
869
  onLike,
857
870
  onComment,
@@ -865,6 +878,7 @@ var VideoFeedItem = react.forwardRef(
865
878
  video,
866
879
  isActive,
867
880
  priority,
881
+ initialMuted,
868
882
  onLike,
869
883
  onComment,
870
884
  onShare,
@@ -1113,6 +1127,7 @@ var VideoFeed = react.forwardRef(
1113
1127
  velocityThreshold = DEFAULT_VELOCITY_THRESHOLD,
1114
1128
  gesturesDisabled = false,
1115
1129
  hapticEnabled = true,
1130
+ initialMuted = true,
1116
1131
  style,
1117
1132
  className = ""
1118
1133
  }, ref) => {
@@ -1386,6 +1401,7 @@ var VideoFeed = react.forwardRef(
1386
1401
  video,
1387
1402
  isActive,
1388
1403
  priority,
1404
+ initialMuted,
1389
1405
  onLike: () => onLike?.(video),
1390
1406
  onComment: () => onComment?.(video),
1391
1407
  onShare: () => onShare?.(video),
@@ -1609,6 +1625,7 @@ var ConnectedVideoFeed = react.forwardRef(
1609
1625
  searchQuery,
1610
1626
  pageSize = 10,
1611
1627
  initialVideos,
1628
+ initialMuted = true,
1612
1629
  onFetchSuccess,
1613
1630
  onFetchError,
1614
1631
  renderLoading = () => /* @__PURE__ */ jsxRuntime.jsx(DefaultLoading, {}),
@@ -1676,6 +1693,7 @@ var ConnectedVideoFeed = react.forwardRef(
1676
1693
  onComment,
1677
1694
  onShare,
1678
1695
  onAuthorClick,
1696
+ initialMuted,
1679
1697
  ...videoFeedProps
1680
1698
  }
1681
1699
  );
package/dist/index.mjs CHANGED
@@ -20,7 +20,7 @@ var videoFeedItemStyles = {
20
20
  inset: 0,
21
21
  width: "100%",
22
22
  height: "100%",
23
- objectFit: "cover"
23
+ objectFit: "contain"
24
24
  },
25
25
  placeholder: {
26
26
  position: "absolute",
@@ -358,6 +358,7 @@ function useVideoFeedItemState({
358
358
  video,
359
359
  isActive,
360
360
  priority,
361
+ initialMuted = true,
361
362
  onLike,
362
363
  onComment,
363
364
  onShare,
@@ -418,14 +419,24 @@ function useVideoFeedItemState({
418
419
  const play = useCallback(async () => {
419
420
  const videoEl = videoRef.current;
420
421
  if (videoEl) {
421
- videoEl.muted = true;
422
+ videoEl.muted = initialMuted;
422
423
  try {
423
424
  await videoEl.play();
424
425
  } catch (err) {
425
- console.warn("[VideoFeedItem] Play failed:", err.message);
426
+ if (err.name === "NotAllowedError" && !initialMuted) {
427
+ console.warn("[VideoFeedItem] Autoplay blocked, falling back to muted");
428
+ videoEl.muted = true;
429
+ try {
430
+ await videoEl.play();
431
+ } catch (mutedErr) {
432
+ console.warn("[VideoFeedItem] Play failed even muted:", mutedErr.message);
433
+ }
434
+ } else {
435
+ console.warn("[VideoFeedItem] Play failed:", err.message);
436
+ }
426
437
  }
427
438
  }
428
- }, []);
439
+ }, [initialMuted]);
429
440
  const pause = useCallback(() => {
430
441
  const videoEl = videoRef.current;
431
442
  if (videoEl) {
@@ -603,6 +614,7 @@ function useVideoFeedItemState({
603
614
  shouldRenderVideo,
604
615
  preload,
605
616
  isPreloaded,
617
+ initialMuted,
606
618
  containerRef,
607
619
  videoRef,
608
620
  isPlaying: effectiveIsPlaying,
@@ -627,7 +639,7 @@ function useVideoFeedItemState({
627
639
  }
628
640
  var VideoFeedItemPlayer = forwardRef(
629
641
  ({ placeholder, ...props }, ref) => {
630
- const { video, videoRef, shouldRenderVideo, preload, isPreloaded } = useVideoFeedItemContext();
642
+ const { video, videoRef, shouldRenderVideo, preload, isPreloaded, initialMuted } = useVideoFeedItemContext();
631
643
  if (!shouldRenderVideo) {
632
644
  return placeholder ?? /* @__PURE__ */ jsx(
633
645
  "div",
@@ -658,7 +670,7 @@ var VideoFeedItemPlayer = forwardRef(
658
670
  preload,
659
671
  loop: true,
660
672
  playsInline: true,
661
- muted: true,
673
+ muted: initialMuted,
662
674
  style: videoFeedItemStyles.video
663
675
  }
664
676
  );
@@ -851,6 +863,7 @@ var VideoFeedItem = forwardRef(
851
863
  video,
852
864
  isActive = false,
853
865
  priority = "none",
866
+ initialMuted = true,
854
867
  showTimeline = true,
855
868
  onLike,
856
869
  onComment,
@@ -864,6 +877,7 @@ var VideoFeedItem = forwardRef(
864
877
  video,
865
878
  isActive,
866
879
  priority,
880
+ initialMuted,
867
881
  onLike,
868
882
  onComment,
869
883
  onShare,
@@ -1112,6 +1126,7 @@ var VideoFeed = forwardRef(
1112
1126
  velocityThreshold = DEFAULT_VELOCITY_THRESHOLD,
1113
1127
  gesturesDisabled = false,
1114
1128
  hapticEnabled = true,
1129
+ initialMuted = true,
1115
1130
  style,
1116
1131
  className = ""
1117
1132
  }, ref) => {
@@ -1385,6 +1400,7 @@ var VideoFeed = forwardRef(
1385
1400
  video,
1386
1401
  isActive,
1387
1402
  priority,
1403
+ initialMuted,
1388
1404
  onLike: () => onLike?.(video),
1389
1405
  onComment: () => onComment?.(video),
1390
1406
  onShare: () => onShare?.(video),
@@ -1608,6 +1624,7 @@ var ConnectedVideoFeed = forwardRef(
1608
1624
  searchQuery,
1609
1625
  pageSize = 10,
1610
1626
  initialVideos,
1627
+ initialMuted = true,
1611
1628
  onFetchSuccess,
1612
1629
  onFetchError,
1613
1630
  renderLoading = () => /* @__PURE__ */ jsx(DefaultLoading, {}),
@@ -1675,6 +1692,7 @@ var ConnectedVideoFeed = forwardRef(
1675
1692
  onComment,
1676
1693
  onShare,
1677
1694
  onAuthorClick,
1695
+ initialMuted,
1678
1696
  ...videoFeedProps
1679
1697
  }
1680
1698
  );
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xhub-reel/feed",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "description": "Virtualized video feed for XHubReel",
5
5
  "license": "MIT",
6
6
  "author": "XHubReel Team",
@@ -36,8 +36,8 @@
36
36
  },
37
37
  "dependencies": {
38
38
  "@xhub-reel/core": "0.2.0",
39
- "@xhub-reel/player": "0.2.0",
40
- "@xhub-reel/gestures": "0.2.0"
39
+ "@xhub-reel/gestures": "0.2.0",
40
+ "@xhub-reel/player": "0.2.0"
41
41
  },
42
42
  "peerDependencies": {
43
43
  "react": ">=18.0.0",