@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 +12 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.js +24 -6
- package/dist/index.mjs +24 -6
- package/package.json +3 -3
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: "
|
|
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 =
|
|
423
|
+
videoEl.muted = initialMuted;
|
|
423
424
|
try {
|
|
424
425
|
await videoEl.play();
|
|
425
426
|
} catch (err) {
|
|
426
|
-
|
|
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:
|
|
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: "
|
|
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 =
|
|
422
|
+
videoEl.muted = initialMuted;
|
|
422
423
|
try {
|
|
423
424
|
await videoEl.play();
|
|
424
425
|
} catch (err) {
|
|
425
|
-
|
|
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:
|
|
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.
|
|
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/
|
|
40
|
-
"@xhub-reel/
|
|
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",
|