@xhub-reels/sdk 0.1.14 → 0.1.15
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.cjs +91 -10
- package/dist/index.d.cts +21 -3
- package/dist/index.d.ts +21 -3
- package/dist/index.js +91 -11
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1659,6 +1659,43 @@ function skeletonCircle(size) {
|
|
|
1659
1659
|
background: "rgba(255,255,255,0.1)"
|
|
1660
1660
|
};
|
|
1661
1661
|
}
|
|
1662
|
+
function DefaultDoubleTap({ isDoubleTap }) {
|
|
1663
|
+
if (!isDoubleTap) return null;
|
|
1664
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1665
|
+
"div",
|
|
1666
|
+
{
|
|
1667
|
+
style: {
|
|
1668
|
+
position: "absolute",
|
|
1669
|
+
inset: 0,
|
|
1670
|
+
display: "flex",
|
|
1671
|
+
alignItems: "center",
|
|
1672
|
+
justifyContent: "center",
|
|
1673
|
+
pointerEvents: "none",
|
|
1674
|
+
zIndex: 20
|
|
1675
|
+
},
|
|
1676
|
+
children: [
|
|
1677
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1678
|
+
"div",
|
|
1679
|
+
{
|
|
1680
|
+
style: {
|
|
1681
|
+
fontSize: 80,
|
|
1682
|
+
animation: "reels-sdk-doubleTapHeart 0.6s ease forwards"
|
|
1683
|
+
},
|
|
1684
|
+
children: "\u2764\uFE0F"
|
|
1685
|
+
}
|
|
1686
|
+
),
|
|
1687
|
+
/* @__PURE__ */ jsxRuntime.jsx("style", { children: `
|
|
1688
|
+
@keyframes reels-sdk-doubleTapHeart {
|
|
1689
|
+
0% { opacity: 0; transform: scale(0.5); }
|
|
1690
|
+
30% { opacity: 1; transform: scale(1.2); }
|
|
1691
|
+
60% { opacity: 1; transform: scale(1.0); }
|
|
1692
|
+
100% { opacity: 0; transform: scale(1.1); }
|
|
1693
|
+
}
|
|
1694
|
+
` })
|
|
1695
|
+
]
|
|
1696
|
+
}
|
|
1697
|
+
);
|
|
1698
|
+
}
|
|
1662
1699
|
function VideoSlot({
|
|
1663
1700
|
item,
|
|
1664
1701
|
index,
|
|
@@ -1671,7 +1708,8 @@ function VideoSlot({
|
|
|
1671
1708
|
showFps = false,
|
|
1672
1709
|
renderOverlay,
|
|
1673
1710
|
renderActions,
|
|
1674
|
-
renderPauseIndicator
|
|
1711
|
+
renderPauseIndicator,
|
|
1712
|
+
renderDoubleTap
|
|
1675
1713
|
}) {
|
|
1676
1714
|
const { optimisticManager, adapters } = useSDK();
|
|
1677
1715
|
if (!isVideoItem(item)) {
|
|
@@ -1708,6 +1746,7 @@ function VideoSlot({
|
|
|
1708
1746
|
renderOverlay,
|
|
1709
1747
|
renderActions,
|
|
1710
1748
|
renderPauseIndicator,
|
|
1749
|
+
renderDoubleTap,
|
|
1711
1750
|
optimisticManager,
|
|
1712
1751
|
adapters
|
|
1713
1752
|
}
|
|
@@ -1726,6 +1765,7 @@ function VideoSlotInner({
|
|
|
1726
1765
|
renderOverlay,
|
|
1727
1766
|
renderActions,
|
|
1728
1767
|
renderPauseIndicator,
|
|
1768
|
+
renderDoubleTap,
|
|
1729
1769
|
optimisticManager,
|
|
1730
1770
|
adapters
|
|
1731
1771
|
}) {
|
|
@@ -1944,18 +1984,44 @@ function VideoSlotInner({
|
|
|
1944
1984
|
}, [isActive]);
|
|
1945
1985
|
const showPosterOverlay = isActive ? !isReady && !isActuallyPlaying : canPlayAhead ? !hasPlayedAhead : !isReady;
|
|
1946
1986
|
const [isPaused, setIsPaused] = react.useState(false);
|
|
1987
|
+
const [isDoubleTap, setIsDoubleTap] = react.useState(false);
|
|
1988
|
+
const lastTapTimeRef = react.useRef(0);
|
|
1989
|
+
const doubleTapTimerRef = react.useRef(null);
|
|
1947
1990
|
const handleTap = react.useCallback(() => {
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1991
|
+
if (!isActive) return;
|
|
1992
|
+
const now = Date.now();
|
|
1993
|
+
const delta = now - lastTapTimeRef.current;
|
|
1994
|
+
lastTapTimeRef.current = now;
|
|
1995
|
+
if (delta < 300) {
|
|
1996
|
+
if (doubleTapTimerRef.current !== null) {
|
|
1997
|
+
clearTimeout(doubleTapTimerRef.current);
|
|
1998
|
+
doubleTapTimerRef.current = null;
|
|
1999
|
+
}
|
|
2000
|
+
setIsDoubleTap(true);
|
|
2001
|
+
setTimeout(() => setIsDoubleTap(false), 600);
|
|
1954
2002
|
} else {
|
|
1955
|
-
|
|
1956
|
-
|
|
2003
|
+
doubleTapTimerRef.current = setTimeout(() => {
|
|
2004
|
+
doubleTapTimerRef.current = null;
|
|
2005
|
+
const video = videoRef.current;
|
|
2006
|
+
if (!video) return;
|
|
2007
|
+
if (video.paused) {
|
|
2008
|
+
video.play().catch(() => {
|
|
2009
|
+
});
|
|
2010
|
+
setIsPaused(false);
|
|
2011
|
+
} else {
|
|
2012
|
+
video.pause();
|
|
2013
|
+
setIsPaused(true);
|
|
2014
|
+
}
|
|
2015
|
+
}, 300);
|
|
1957
2016
|
}
|
|
1958
2017
|
}, [isActive]);
|
|
2018
|
+
react.useEffect(() => {
|
|
2019
|
+
return () => {
|
|
2020
|
+
if (doubleTapTimerRef.current !== null) {
|
|
2021
|
+
clearTimeout(doubleTapTimerRef.current);
|
|
2022
|
+
}
|
|
2023
|
+
};
|
|
2024
|
+
}, []);
|
|
1959
2025
|
react.useEffect(() => {
|
|
1960
2026
|
if (isActive) setIsPaused(false);
|
|
1961
2027
|
}, [isActive]);
|
|
@@ -2029,6 +2095,18 @@ function VideoSlotInner({
|
|
|
2029
2095
|
}
|
|
2030
2096
|
}
|
|
2031
2097
|
),
|
|
2098
|
+
(isDoubleTap || renderDoubleTap) && /* @__PURE__ */ jsxRuntime.jsx(
|
|
2099
|
+
"div",
|
|
2100
|
+
{
|
|
2101
|
+
style: {
|
|
2102
|
+
position: "absolute",
|
|
2103
|
+
inset: 0,
|
|
2104
|
+
pointerEvents: "none",
|
|
2105
|
+
zIndex: 20
|
|
2106
|
+
},
|
|
2107
|
+
children: renderDoubleTap ? renderDoubleTap(isDoubleTap) : /* @__PURE__ */ jsxRuntime.jsx(DefaultDoubleTap, { isDoubleTap })
|
|
2108
|
+
}
|
|
2109
|
+
),
|
|
2032
2110
|
isPaused && /* @__PURE__ */ jsxRuntime.jsx(
|
|
2033
2111
|
"div",
|
|
2034
2112
|
{
|
|
@@ -2152,6 +2230,7 @@ function ReelsFeed({
|
|
|
2152
2230
|
renderOverlay,
|
|
2153
2231
|
renderActions,
|
|
2154
2232
|
renderPauseIndicator,
|
|
2233
|
+
renderDoubleTap,
|
|
2155
2234
|
renderLoading,
|
|
2156
2235
|
renderEmpty,
|
|
2157
2236
|
renderError: _renderError,
|
|
@@ -2398,7 +2477,8 @@ function ReelsFeed({
|
|
|
2398
2477
|
showFps: showFps && isActive,
|
|
2399
2478
|
renderOverlay,
|
|
2400
2479
|
renderActions,
|
|
2401
|
-
renderPauseIndicator
|
|
2480
|
+
renderPauseIndicator,
|
|
2481
|
+
renderDoubleTap
|
|
2402
2482
|
}
|
|
2403
2483
|
) : null
|
|
2404
2484
|
},
|
|
@@ -3033,6 +3113,7 @@ exports.DEFAULT_FEED_CONFIG = DEFAULT_FEED_CONFIG;
|
|
|
3033
3113
|
exports.DEFAULT_PLAYER_CONFIG = DEFAULT_PLAYER_CONFIG;
|
|
3034
3114
|
exports.DEFAULT_RESOURCE_CONFIG = DEFAULT_RESOURCE_CONFIG;
|
|
3035
3115
|
exports.DefaultActions = DefaultActions;
|
|
3116
|
+
exports.DefaultDoubleTap = DefaultDoubleTap;
|
|
3036
3117
|
exports.DefaultOverlay = DefaultOverlay;
|
|
3037
3118
|
exports.DefaultSkeleton = DefaultSkeleton;
|
|
3038
3119
|
exports.FeedManager = FeedManager;
|
package/dist/index.d.cts
CHANGED
|
@@ -334,6 +334,13 @@ interface ReelsFeedProps {
|
|
|
334
334
|
* If not provided, SDK uses a default ▶️/⏸️ emoji indicator.
|
|
335
335
|
*/
|
|
336
336
|
renderPauseIndicator?: (isPaused: boolean) => ReactNode;
|
|
337
|
+
/**
|
|
338
|
+
* Custom double-tap overlay rendered when user double-taps a video slot.
|
|
339
|
+
* Receives isDoubleTap boolean (true for the duration of the animation window).
|
|
340
|
+
* Return ReactNode — positioned absolute center (full inset) by SDK.
|
|
341
|
+
* If not provided, SDK uses DefaultDoubleTap (animated ❤️ heart).
|
|
342
|
+
*/
|
|
343
|
+
renderDoubleTap?: (isDoubleTap: boolean) => ReactNode;
|
|
337
344
|
/**
|
|
338
345
|
* Custom loading skeleton shown during initial feed load.
|
|
339
346
|
* If not provided, SDK uses DefaultSkeleton with shimmer animation.
|
|
@@ -724,7 +731,7 @@ interface ReelsProviderProps {
|
|
|
724
731
|
declare function ReelsProvider({ children, adapters, debug }: ReelsProviderProps): react_jsx_runtime.JSX.Element;
|
|
725
732
|
declare function useSDK(): SDKContextValue;
|
|
726
733
|
|
|
727
|
-
declare function ReelsFeed({ renderOverlay, renderActions, renderPauseIndicator, renderLoading, renderEmpty, renderError: _renderError, showFps, loadMoreThreshold, onSlotChange, gestureConfig, snapConfig, }: ReelsFeedProps): string | number | bigint | boolean | Iterable<react.ReactNode> | Promise<string | number | bigint | boolean | react.ReactPortal | react.ReactElement<unknown, string | react.JSXElementConstructor<any>> | Iterable<react.ReactNode> | null | undefined> | react_jsx_runtime.JSX.Element | null | undefined;
|
|
734
|
+
declare function ReelsFeed({ renderOverlay, renderActions, renderPauseIndicator, renderDoubleTap, renderLoading, renderEmpty, renderError: _renderError, showFps, loadMoreThreshold, onSlotChange, gestureConfig, snapConfig, }: ReelsFeedProps): string | number | bigint | boolean | Iterable<react.ReactNode> | Promise<string | number | bigint | boolean | react.ReactPortal | react.ReactElement<unknown, string | react.JSXElementConstructor<any>> | Iterable<react.ReactNode> | null | undefined> | react_jsx_runtime.JSX.Element | null | undefined;
|
|
728
735
|
|
|
729
736
|
/**
|
|
730
737
|
* useHls — React hook for hls.js lifecycle management (3-Tier buffer support)
|
|
@@ -801,8 +808,9 @@ interface VideoSlotProps {
|
|
|
801
808
|
renderOverlay?: (item: ContentItem, actions: SlotActions) => ReactNode;
|
|
802
809
|
renderActions?: (item: ContentItem, actions: SlotActions) => ReactNode;
|
|
803
810
|
renderPauseIndicator?: (isPaused: boolean) => ReactNode;
|
|
811
|
+
renderDoubleTap?: (isDoubleTap: boolean) => ReactNode;
|
|
804
812
|
}
|
|
805
|
-
declare function VideoSlot({ item, index, isActive, isPrefetch, isPreloaded, bufferTier, isMuted, onToggleMute, showFps, renderOverlay, renderActions, renderPauseIndicator, }: VideoSlotProps): react_jsx_runtime.JSX.Element;
|
|
813
|
+
declare function VideoSlot({ item, index, isActive, isPrefetch, isPreloaded, bufferTier, isMuted, onToggleMute, showFps, renderOverlay, renderActions, renderPauseIndicator, renderDoubleTap, }: VideoSlotProps): react_jsx_runtime.JSX.Element;
|
|
806
814
|
|
|
807
815
|
declare function DefaultOverlay({ item }: {
|
|
808
816
|
item: ContentItem;
|
|
@@ -820,6 +828,16 @@ declare function DefaultActions({ item, actions }: {
|
|
|
820
828
|
*/
|
|
821
829
|
declare function DefaultSkeleton(): react_jsx_runtime.JSX.Element;
|
|
822
830
|
|
|
831
|
+
/**
|
|
832
|
+
* DefaultDoubleTap — Default double-tap heart animation overlay
|
|
833
|
+
*
|
|
834
|
+
* Shown when user double-taps a video slot and no renderDoubleTap is provided.
|
|
835
|
+
* Renders an animated ❤️ that fades in/scales up then fades out.
|
|
836
|
+
*/
|
|
837
|
+
declare function DefaultDoubleTap({ isDoubleTap }: {
|
|
838
|
+
isDoubleTap: boolean;
|
|
839
|
+
}): react_jsx_runtime.JSX.Element | null;
|
|
840
|
+
|
|
823
841
|
declare function useFeedSelector<T>(selector: (state: FeedState) => T): T;
|
|
824
842
|
declare function useFeed(): {
|
|
825
843
|
items: NonNullable<ContentItem | undefined>[];
|
|
@@ -1090,4 +1108,4 @@ declare class HttpError extends Error {
|
|
|
1090
1108
|
constructor(status: number, message: string, body?: string | undefined);
|
|
1091
1109
|
}
|
|
1092
1110
|
|
|
1093
|
-
export { type Article, type ArticleImage, type Author, type BufferTier, type CommentItem, type CommentPage, type ContentItem, type ContentStats, DEFAULT_FEED_CONFIG, DEFAULT_PLAYER_CONFIG, DEFAULT_RESOURCE_CONFIG, DefaultActions, DefaultOverlay, DefaultSkeleton, type FeedConfig, type FeedError, FeedManager, type FeedPage, type FeedState, HttpDataSource, type HttpDataSourceConfig, HttpError, type IAnalytics, type ICommentAdapter, type IDataSource, type IInteraction, type ILogger, type INetworkAdapter, type ISessionStorage, type IVideoLoader, type InteractionState, type LogLevel, MockAnalytics, MockCommentAdapter, MockDataSource, MockInteraction, MockLogger, MockNetworkAdapter, MockSessionStorage, MockVideoLoader, type NetworkType, OptimisticManager, type PlayerConfig, PlayerEngine, type PlayerError, type PlayerEvent, type PlayerEventListener, type PlayerState, PlayerStatus, type PointerGestureConfig, type PreloadResult, type PreloadStatus, ReelsFeed, type ReelsFeedProps, ReelsProvider, type ReelsProviderProps, type ResourceConfig, ResourceGovernor, type ResourceState, type SDKAdapters, type SDKContextValue, type SlotActions, type SnapTarget, type UseHlsOptions, type UseHlsReturn, VALID_TRANSITIONS, type VideoItem, type VideoQuality, VideoSlot, type VideoSource, canPause, canPlay, canSeek, isArticle, isValidTransition, isVideoItem, useFeed, useFeedSelector, useHls, usePlayer, usePlayerSelector, usePointerGesture, useResource, useResourceSelector, useSDK, useSnapAnimation };
|
|
1111
|
+
export { type Article, type ArticleImage, type Author, type BufferTier, type CommentItem, type CommentPage, type ContentItem, type ContentStats, DEFAULT_FEED_CONFIG, DEFAULT_PLAYER_CONFIG, DEFAULT_RESOURCE_CONFIG, DefaultActions, DefaultDoubleTap, DefaultOverlay, DefaultSkeleton, type FeedConfig, type FeedError, FeedManager, type FeedPage, type FeedState, HttpDataSource, type HttpDataSourceConfig, HttpError, type IAnalytics, type ICommentAdapter, type IDataSource, type IInteraction, type ILogger, type INetworkAdapter, type ISessionStorage, type IVideoLoader, type InteractionState, type LogLevel, MockAnalytics, MockCommentAdapter, MockDataSource, MockInteraction, MockLogger, MockNetworkAdapter, MockSessionStorage, MockVideoLoader, type NetworkType, OptimisticManager, type PlayerConfig, PlayerEngine, type PlayerError, type PlayerEvent, type PlayerEventListener, type PlayerState, PlayerStatus, type PointerGestureConfig, type PreloadResult, type PreloadStatus, ReelsFeed, type ReelsFeedProps, ReelsProvider, type ReelsProviderProps, type ResourceConfig, ResourceGovernor, type ResourceState, type SDKAdapters, type SDKContextValue, type SlotActions, type SnapTarget, type UseHlsOptions, type UseHlsReturn, VALID_TRANSITIONS, type VideoItem, type VideoQuality, VideoSlot, type VideoSource, canPause, canPlay, canSeek, isArticle, isValidTransition, isVideoItem, useFeed, useFeedSelector, useHls, usePlayer, usePlayerSelector, usePointerGesture, useResource, useResourceSelector, useSDK, useSnapAnimation };
|
package/dist/index.d.ts
CHANGED
|
@@ -334,6 +334,13 @@ interface ReelsFeedProps {
|
|
|
334
334
|
* If not provided, SDK uses a default ▶️/⏸️ emoji indicator.
|
|
335
335
|
*/
|
|
336
336
|
renderPauseIndicator?: (isPaused: boolean) => ReactNode;
|
|
337
|
+
/**
|
|
338
|
+
* Custom double-tap overlay rendered when user double-taps a video slot.
|
|
339
|
+
* Receives isDoubleTap boolean (true for the duration of the animation window).
|
|
340
|
+
* Return ReactNode — positioned absolute center (full inset) by SDK.
|
|
341
|
+
* If not provided, SDK uses DefaultDoubleTap (animated ❤️ heart).
|
|
342
|
+
*/
|
|
343
|
+
renderDoubleTap?: (isDoubleTap: boolean) => ReactNode;
|
|
337
344
|
/**
|
|
338
345
|
* Custom loading skeleton shown during initial feed load.
|
|
339
346
|
* If not provided, SDK uses DefaultSkeleton with shimmer animation.
|
|
@@ -724,7 +731,7 @@ interface ReelsProviderProps {
|
|
|
724
731
|
declare function ReelsProvider({ children, adapters, debug }: ReelsProviderProps): react_jsx_runtime.JSX.Element;
|
|
725
732
|
declare function useSDK(): SDKContextValue;
|
|
726
733
|
|
|
727
|
-
declare function ReelsFeed({ renderOverlay, renderActions, renderPauseIndicator, renderLoading, renderEmpty, renderError: _renderError, showFps, loadMoreThreshold, onSlotChange, gestureConfig, snapConfig, }: ReelsFeedProps): string | number | bigint | boolean | Iterable<react.ReactNode> | Promise<string | number | bigint | boolean | react.ReactPortal | react.ReactElement<unknown, string | react.JSXElementConstructor<any>> | Iterable<react.ReactNode> | null | undefined> | react_jsx_runtime.JSX.Element | null | undefined;
|
|
734
|
+
declare function ReelsFeed({ renderOverlay, renderActions, renderPauseIndicator, renderDoubleTap, renderLoading, renderEmpty, renderError: _renderError, showFps, loadMoreThreshold, onSlotChange, gestureConfig, snapConfig, }: ReelsFeedProps): string | number | bigint | boolean | Iterable<react.ReactNode> | Promise<string | number | bigint | boolean | react.ReactPortal | react.ReactElement<unknown, string | react.JSXElementConstructor<any>> | Iterable<react.ReactNode> | null | undefined> | react_jsx_runtime.JSX.Element | null | undefined;
|
|
728
735
|
|
|
729
736
|
/**
|
|
730
737
|
* useHls — React hook for hls.js lifecycle management (3-Tier buffer support)
|
|
@@ -801,8 +808,9 @@ interface VideoSlotProps {
|
|
|
801
808
|
renderOverlay?: (item: ContentItem, actions: SlotActions) => ReactNode;
|
|
802
809
|
renderActions?: (item: ContentItem, actions: SlotActions) => ReactNode;
|
|
803
810
|
renderPauseIndicator?: (isPaused: boolean) => ReactNode;
|
|
811
|
+
renderDoubleTap?: (isDoubleTap: boolean) => ReactNode;
|
|
804
812
|
}
|
|
805
|
-
declare function VideoSlot({ item, index, isActive, isPrefetch, isPreloaded, bufferTier, isMuted, onToggleMute, showFps, renderOverlay, renderActions, renderPauseIndicator, }: VideoSlotProps): react_jsx_runtime.JSX.Element;
|
|
813
|
+
declare function VideoSlot({ item, index, isActive, isPrefetch, isPreloaded, bufferTier, isMuted, onToggleMute, showFps, renderOverlay, renderActions, renderPauseIndicator, renderDoubleTap, }: VideoSlotProps): react_jsx_runtime.JSX.Element;
|
|
806
814
|
|
|
807
815
|
declare function DefaultOverlay({ item }: {
|
|
808
816
|
item: ContentItem;
|
|
@@ -820,6 +828,16 @@ declare function DefaultActions({ item, actions }: {
|
|
|
820
828
|
*/
|
|
821
829
|
declare function DefaultSkeleton(): react_jsx_runtime.JSX.Element;
|
|
822
830
|
|
|
831
|
+
/**
|
|
832
|
+
* DefaultDoubleTap — Default double-tap heart animation overlay
|
|
833
|
+
*
|
|
834
|
+
* Shown when user double-taps a video slot and no renderDoubleTap is provided.
|
|
835
|
+
* Renders an animated ❤️ that fades in/scales up then fades out.
|
|
836
|
+
*/
|
|
837
|
+
declare function DefaultDoubleTap({ isDoubleTap }: {
|
|
838
|
+
isDoubleTap: boolean;
|
|
839
|
+
}): react_jsx_runtime.JSX.Element | null;
|
|
840
|
+
|
|
823
841
|
declare function useFeedSelector<T>(selector: (state: FeedState) => T): T;
|
|
824
842
|
declare function useFeed(): {
|
|
825
843
|
items: NonNullable<ContentItem | undefined>[];
|
|
@@ -1090,4 +1108,4 @@ declare class HttpError extends Error {
|
|
|
1090
1108
|
constructor(status: number, message: string, body?: string | undefined);
|
|
1091
1109
|
}
|
|
1092
1110
|
|
|
1093
|
-
export { type Article, type ArticleImage, type Author, type BufferTier, type CommentItem, type CommentPage, type ContentItem, type ContentStats, DEFAULT_FEED_CONFIG, DEFAULT_PLAYER_CONFIG, DEFAULT_RESOURCE_CONFIG, DefaultActions, DefaultOverlay, DefaultSkeleton, type FeedConfig, type FeedError, FeedManager, type FeedPage, type FeedState, HttpDataSource, type HttpDataSourceConfig, HttpError, type IAnalytics, type ICommentAdapter, type IDataSource, type IInteraction, type ILogger, type INetworkAdapter, type ISessionStorage, type IVideoLoader, type InteractionState, type LogLevel, MockAnalytics, MockCommentAdapter, MockDataSource, MockInteraction, MockLogger, MockNetworkAdapter, MockSessionStorage, MockVideoLoader, type NetworkType, OptimisticManager, type PlayerConfig, PlayerEngine, type PlayerError, type PlayerEvent, type PlayerEventListener, type PlayerState, PlayerStatus, type PointerGestureConfig, type PreloadResult, type PreloadStatus, ReelsFeed, type ReelsFeedProps, ReelsProvider, type ReelsProviderProps, type ResourceConfig, ResourceGovernor, type ResourceState, type SDKAdapters, type SDKContextValue, type SlotActions, type SnapTarget, type UseHlsOptions, type UseHlsReturn, VALID_TRANSITIONS, type VideoItem, type VideoQuality, VideoSlot, type VideoSource, canPause, canPlay, canSeek, isArticle, isValidTransition, isVideoItem, useFeed, useFeedSelector, useHls, usePlayer, usePlayerSelector, usePointerGesture, useResource, useResourceSelector, useSDK, useSnapAnimation };
|
|
1111
|
+
export { type Article, type ArticleImage, type Author, type BufferTier, type CommentItem, type CommentPage, type ContentItem, type ContentStats, DEFAULT_FEED_CONFIG, DEFAULT_PLAYER_CONFIG, DEFAULT_RESOURCE_CONFIG, DefaultActions, DefaultDoubleTap, DefaultOverlay, DefaultSkeleton, type FeedConfig, type FeedError, FeedManager, type FeedPage, type FeedState, HttpDataSource, type HttpDataSourceConfig, HttpError, type IAnalytics, type ICommentAdapter, type IDataSource, type IInteraction, type ILogger, type INetworkAdapter, type ISessionStorage, type IVideoLoader, type InteractionState, type LogLevel, MockAnalytics, MockCommentAdapter, MockDataSource, MockInteraction, MockLogger, MockNetworkAdapter, MockSessionStorage, MockVideoLoader, type NetworkType, OptimisticManager, type PlayerConfig, PlayerEngine, type PlayerError, type PlayerEvent, type PlayerEventListener, type PlayerState, PlayerStatus, type PointerGestureConfig, type PreloadResult, type PreloadStatus, ReelsFeed, type ReelsFeedProps, ReelsProvider, type ReelsProviderProps, type ResourceConfig, ResourceGovernor, type ResourceState, type SDKAdapters, type SDKContextValue, type SlotActions, type SnapTarget, type UseHlsOptions, type UseHlsReturn, VALID_TRANSITIONS, type VideoItem, type VideoQuality, VideoSlot, type VideoSource, canPause, canPlay, canSeek, isArticle, isValidTransition, isVideoItem, useFeed, useFeedSelector, useHls, usePlayer, usePlayerSelector, usePointerGesture, useResource, useResourceSelector, useSDK, useSnapAnimation };
|
package/dist/index.js
CHANGED
|
@@ -1653,6 +1653,43 @@ function skeletonCircle(size) {
|
|
|
1653
1653
|
background: "rgba(255,255,255,0.1)"
|
|
1654
1654
|
};
|
|
1655
1655
|
}
|
|
1656
|
+
function DefaultDoubleTap({ isDoubleTap }) {
|
|
1657
|
+
if (!isDoubleTap) return null;
|
|
1658
|
+
return /* @__PURE__ */ jsxs(
|
|
1659
|
+
"div",
|
|
1660
|
+
{
|
|
1661
|
+
style: {
|
|
1662
|
+
position: "absolute",
|
|
1663
|
+
inset: 0,
|
|
1664
|
+
display: "flex",
|
|
1665
|
+
alignItems: "center",
|
|
1666
|
+
justifyContent: "center",
|
|
1667
|
+
pointerEvents: "none",
|
|
1668
|
+
zIndex: 20
|
|
1669
|
+
},
|
|
1670
|
+
children: [
|
|
1671
|
+
/* @__PURE__ */ jsx(
|
|
1672
|
+
"div",
|
|
1673
|
+
{
|
|
1674
|
+
style: {
|
|
1675
|
+
fontSize: 80,
|
|
1676
|
+
animation: "reels-sdk-doubleTapHeart 0.6s ease forwards"
|
|
1677
|
+
},
|
|
1678
|
+
children: "\u2764\uFE0F"
|
|
1679
|
+
}
|
|
1680
|
+
),
|
|
1681
|
+
/* @__PURE__ */ jsx("style", { children: `
|
|
1682
|
+
@keyframes reels-sdk-doubleTapHeart {
|
|
1683
|
+
0% { opacity: 0; transform: scale(0.5); }
|
|
1684
|
+
30% { opacity: 1; transform: scale(1.2); }
|
|
1685
|
+
60% { opacity: 1; transform: scale(1.0); }
|
|
1686
|
+
100% { opacity: 0; transform: scale(1.1); }
|
|
1687
|
+
}
|
|
1688
|
+
` })
|
|
1689
|
+
]
|
|
1690
|
+
}
|
|
1691
|
+
);
|
|
1692
|
+
}
|
|
1656
1693
|
function VideoSlot({
|
|
1657
1694
|
item,
|
|
1658
1695
|
index,
|
|
@@ -1665,7 +1702,8 @@ function VideoSlot({
|
|
|
1665
1702
|
showFps = false,
|
|
1666
1703
|
renderOverlay,
|
|
1667
1704
|
renderActions,
|
|
1668
|
-
renderPauseIndicator
|
|
1705
|
+
renderPauseIndicator,
|
|
1706
|
+
renderDoubleTap
|
|
1669
1707
|
}) {
|
|
1670
1708
|
const { optimisticManager, adapters } = useSDK();
|
|
1671
1709
|
if (!isVideoItem(item)) {
|
|
@@ -1702,6 +1740,7 @@ function VideoSlot({
|
|
|
1702
1740
|
renderOverlay,
|
|
1703
1741
|
renderActions,
|
|
1704
1742
|
renderPauseIndicator,
|
|
1743
|
+
renderDoubleTap,
|
|
1705
1744
|
optimisticManager,
|
|
1706
1745
|
adapters
|
|
1707
1746
|
}
|
|
@@ -1720,6 +1759,7 @@ function VideoSlotInner({
|
|
|
1720
1759
|
renderOverlay,
|
|
1721
1760
|
renderActions,
|
|
1722
1761
|
renderPauseIndicator,
|
|
1762
|
+
renderDoubleTap,
|
|
1723
1763
|
optimisticManager,
|
|
1724
1764
|
adapters
|
|
1725
1765
|
}) {
|
|
@@ -1938,18 +1978,44 @@ function VideoSlotInner({
|
|
|
1938
1978
|
}, [isActive]);
|
|
1939
1979
|
const showPosterOverlay = isActive ? !isReady && !isActuallyPlaying : canPlayAhead ? !hasPlayedAhead : !isReady;
|
|
1940
1980
|
const [isPaused, setIsPaused] = useState(false);
|
|
1981
|
+
const [isDoubleTap, setIsDoubleTap] = useState(false);
|
|
1982
|
+
const lastTapTimeRef = useRef(0);
|
|
1983
|
+
const doubleTapTimerRef = useRef(null);
|
|
1941
1984
|
const handleTap = useCallback(() => {
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1985
|
+
if (!isActive) return;
|
|
1986
|
+
const now = Date.now();
|
|
1987
|
+
const delta = now - lastTapTimeRef.current;
|
|
1988
|
+
lastTapTimeRef.current = now;
|
|
1989
|
+
if (delta < 300) {
|
|
1990
|
+
if (doubleTapTimerRef.current !== null) {
|
|
1991
|
+
clearTimeout(doubleTapTimerRef.current);
|
|
1992
|
+
doubleTapTimerRef.current = null;
|
|
1993
|
+
}
|
|
1994
|
+
setIsDoubleTap(true);
|
|
1995
|
+
setTimeout(() => setIsDoubleTap(false), 600);
|
|
1948
1996
|
} else {
|
|
1949
|
-
|
|
1950
|
-
|
|
1997
|
+
doubleTapTimerRef.current = setTimeout(() => {
|
|
1998
|
+
doubleTapTimerRef.current = null;
|
|
1999
|
+
const video = videoRef.current;
|
|
2000
|
+
if (!video) return;
|
|
2001
|
+
if (video.paused) {
|
|
2002
|
+
video.play().catch(() => {
|
|
2003
|
+
});
|
|
2004
|
+
setIsPaused(false);
|
|
2005
|
+
} else {
|
|
2006
|
+
video.pause();
|
|
2007
|
+
setIsPaused(true);
|
|
2008
|
+
}
|
|
2009
|
+
}, 300);
|
|
1951
2010
|
}
|
|
1952
2011
|
}, [isActive]);
|
|
2012
|
+
useEffect(() => {
|
|
2013
|
+
return () => {
|
|
2014
|
+
if (doubleTapTimerRef.current !== null) {
|
|
2015
|
+
clearTimeout(doubleTapTimerRef.current);
|
|
2016
|
+
}
|
|
2017
|
+
};
|
|
2018
|
+
}, []);
|
|
1953
2019
|
useEffect(() => {
|
|
1954
2020
|
if (isActive) setIsPaused(false);
|
|
1955
2021
|
}, [isActive]);
|
|
@@ -2023,6 +2089,18 @@ function VideoSlotInner({
|
|
|
2023
2089
|
}
|
|
2024
2090
|
}
|
|
2025
2091
|
),
|
|
2092
|
+
(isDoubleTap || renderDoubleTap) && /* @__PURE__ */ jsx(
|
|
2093
|
+
"div",
|
|
2094
|
+
{
|
|
2095
|
+
style: {
|
|
2096
|
+
position: "absolute",
|
|
2097
|
+
inset: 0,
|
|
2098
|
+
pointerEvents: "none",
|
|
2099
|
+
zIndex: 20
|
|
2100
|
+
},
|
|
2101
|
+
children: renderDoubleTap ? renderDoubleTap(isDoubleTap) : /* @__PURE__ */ jsx(DefaultDoubleTap, { isDoubleTap })
|
|
2102
|
+
}
|
|
2103
|
+
),
|
|
2026
2104
|
isPaused && /* @__PURE__ */ jsx(
|
|
2027
2105
|
"div",
|
|
2028
2106
|
{
|
|
@@ -2146,6 +2224,7 @@ function ReelsFeed({
|
|
|
2146
2224
|
renderOverlay,
|
|
2147
2225
|
renderActions,
|
|
2148
2226
|
renderPauseIndicator,
|
|
2227
|
+
renderDoubleTap,
|
|
2149
2228
|
renderLoading,
|
|
2150
2229
|
renderEmpty,
|
|
2151
2230
|
renderError: _renderError,
|
|
@@ -2392,7 +2471,8 @@ function ReelsFeed({
|
|
|
2392
2471
|
showFps: showFps && isActive,
|
|
2393
2472
|
renderOverlay,
|
|
2394
2473
|
renderActions,
|
|
2395
|
-
renderPauseIndicator
|
|
2474
|
+
renderPauseIndicator,
|
|
2475
|
+
renderDoubleTap
|
|
2396
2476
|
}
|
|
2397
2477
|
) : null
|
|
2398
2478
|
},
|
|
@@ -3023,4 +3103,4 @@ var HttpError = class extends Error {
|
|
|
3023
3103
|
}
|
|
3024
3104
|
};
|
|
3025
3105
|
|
|
3026
|
-
export { DEFAULT_FEED_CONFIG, DEFAULT_PLAYER_CONFIG, DEFAULT_RESOURCE_CONFIG, DefaultActions, DefaultOverlay, DefaultSkeleton, FeedManager, HttpDataSource, HttpError, MockAnalytics, MockCommentAdapter, MockDataSource, MockInteraction, MockLogger, MockNetworkAdapter, MockSessionStorage, MockVideoLoader, OptimisticManager, PlayerEngine, PlayerStatus, ReelsFeed, ReelsProvider, ResourceGovernor, VALID_TRANSITIONS, VideoSlot, canPause, canPlay, canSeek, isArticle, isValidTransition, isVideoItem, useFeed, useFeedSelector, useHls, usePlayer, usePlayerSelector, usePointerGesture, useResource, useResourceSelector, useSDK, useSnapAnimation };
|
|
3106
|
+
export { DEFAULT_FEED_CONFIG, DEFAULT_PLAYER_CONFIG, DEFAULT_RESOURCE_CONFIG, DefaultActions, DefaultDoubleTap, DefaultOverlay, DefaultSkeleton, FeedManager, HttpDataSource, HttpError, MockAnalytics, MockCommentAdapter, MockDataSource, MockInteraction, MockLogger, MockNetworkAdapter, MockSessionStorage, MockVideoLoader, OptimisticManager, PlayerEngine, PlayerStatus, ReelsFeed, ReelsProvider, ResourceGovernor, VALID_TRANSITIONS, VideoSlot, canPause, canPlay, canSeek, isArticle, isValidTransition, isVideoItem, useFeed, useFeedSelector, useHls, usePlayer, usePlayerSelector, usePointerGesture, useResource, useResourceSelector, useSDK, useSnapAnimation };
|