@xhub-reels/sdk 0.1.15 → 0.1.18

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.cts CHANGED
@@ -246,6 +246,16 @@ interface IVideoLoader {
246
246
  isPreloaded(videoId: string): boolean;
247
247
  getPreloadStatus(videoId: string): PreloadStatus;
248
248
  clearAll(): void;
249
+ /**
250
+ * Tier 4 cold prefetch — fetch HLS manifest vào HTTP browser cache.
251
+ * Fire-and-forget. Không download segment. Không cần DOM.
252
+ * Optional: nếu không implement, Tier 4 silently skipped.
253
+ *
254
+ * Implementation pattern:
255
+ * fetch(url, { method: 'GET', headers: { Range: 'bytes=0-0' } })
256
+ * // hoặc đơn giản: fetch(url)
257
+ */
258
+ preloadMetadata?(url: string): void;
249
259
  }
250
260
  interface CommentItem {
251
261
  id: string;
@@ -300,47 +310,53 @@ interface SlotActions {
300
310
  share: () => void;
301
311
  /** Current global mute state */
302
312
  isMuted: boolean;
303
- /** Toggle global mute */
313
+ /** Toggle global mute — exposed via SlotActions for use in renderActions button */
304
314
  toggleMute: () => void;
305
- /** Whether the active video is currently paused */
306
- isPaused: boolean;
307
- /** Toggle pause/play on the active video */
308
- togglePause: () => void;
309
315
  /** Whether this slot is the active playing slot */
310
316
  isActive: boolean;
311
317
  /** Slot index in feed */
312
318
  index: number;
313
319
  }
320
+ /**
321
+ * Actions provided to the pauseActionOverlay render callback.
322
+ * Extends SlotActions with play/pause control.
323
+ */
324
+ interface PauseSlotActions extends SlotActions {
325
+ /** Whether the video is currently manually paused (user tapped to pause) */
326
+ isPaused: boolean;
327
+ /** Toggle play/pause for the current video */
328
+ togglePlayPause: () => void;
329
+ }
314
330
  /** Props for the ReelsFeed component */
315
331
  interface ReelsFeedProps {
316
332
  /**
317
333
  * Custom overlay rendered on each video slot.
318
334
  * Receives the content item + actions. Return ReactNode.
319
- * Positioned absolute bottom (bottom-0) left by SDK.
335
+ * Positioned absolute bottom-left by SDK.
320
336
  * If not provided, SDK uses DefaultOverlay showing author + title.
321
337
  */
322
338
  renderOverlay?: (item: ContentItem, actions: SlotActions) => ReactNode;
323
339
  /**
324
340
  * Custom action bar rendered on each video slot.
325
341
  * Receives the content item + actions. Return ReactNode.
326
- * Positioned absolute bottom (bottom-0) right by SDK.
342
+ * Positioned absolute bottom-right by SDK.
327
343
  * If not provided, SDK uses DefaultActions showing like/comment/share emojis.
344
+ * NOTE: Mute/unmute button should live here — access via actions.toggleMute / actions.isMuted.
328
345
  */
329
346
  renderActions?: (item: ContentItem, actions: SlotActions) => ReactNode;
330
347
  /**
331
- * Custom pause/play indicator rendered when user taps to pause/play.
332
- * Receives isPaused state. Return ReactNode.
333
- * Positioned absolute center by SDK.
334
- * If not provided, SDK uses a default ▶️/⏸️ emoji indicator.
335
- */
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).
348
+ * Custom pause overlay rendered in the center of the video when it is manually paused.
349
+ * Only visible when the user taps to pause the active video.
350
+ * If not provided, SDK shows a default semi-transparent Play icon.
351
+ *
352
+ * Return null to suppress the overlay entirely.
353
+ *
354
+ * @example
355
+ * renderPauseAction={(item, actions) => (
356
+ * <PlayIcon size={72} onPress={actions.togglePlayPause} />
357
+ * )}
342
358
  */
343
- renderDoubleTap?: (isDoubleTap: boolean) => ReactNode;
359
+ renderPauseAction?: (item: ContentItem, actions: PauseSlotActions) => ReactNode;
344
360
  /**
345
361
  * Custom loading skeleton shown during initial feed load.
346
362
  * If not provided, SDK uses DefaultSkeleton with shimmer animation.
@@ -384,6 +400,25 @@ interface ReelsFeedProps {
384
400
  duration?: number;
385
401
  easing?: string;
386
402
  };
403
+ /**
404
+ * Initial mute state for video playback.
405
+ *
406
+ * - `true` (default): Videos start muted, satisfying all browser autoplay policies
407
+ * - `false`: SDK attempts unmuted autoplay. If browser blocks it, falls back to muted.
408
+ *
409
+ * Use `false` when you know the user has already interacted with the page
410
+ * (e.g., clicked a link to navigate to the reels page in Flutter WebView).
411
+ *
412
+ * @default true
413
+ */
414
+ initialMuted?: boolean;
415
+ /**
416
+ * Called when unmuted autoplay fails and SDK falls back to muted playback.
417
+ * Use this to show a "tap to unmute" UI hint to the user.
418
+ *
419
+ * Only fires when `initialMuted: false` and browser blocks unmuted autoplay.
420
+ */
421
+ onAutoplayBlocked?: () => void;
387
422
  }
388
423
 
389
424
  /**
@@ -607,6 +642,14 @@ declare class ResourceGovernor {
607
642
  isWarmAllocated(index: number): boolean;
608
643
  shouldRenderVideo(index: number): boolean;
609
644
  isPreloading(index: number): boolean;
645
+ /**
646
+ * Returns the buffer tier (1–4) for a given index.
647
+ * - 1: Active (playing, 10s buffer)
648
+ * - 2: Hot (±bufferWindow, 2s buffer, instant swap)
649
+ * - 3: Warm (manifest + 1 segment, ~300ms show)
650
+ * - 4: Cold (preload queue — manifest in HTTP cache, no DOM)
651
+ */
652
+ getTier(index: number): 1 | 2 | 3 | 4 | null;
610
653
  getActiveAllocations(): number[];
611
654
  getWarmAllocations(): number[];
612
655
  private recalculate;
@@ -674,6 +717,16 @@ interface PointerGestureConfig {
674
717
  onSnap?: (direction: 'forward' | 'backward') => void;
675
718
  /** Called when gesture ends without snap (bounce back) */
676
719
  onBounceBack?: () => void;
720
+ /**
721
+ * Called when drag gesture starts (pointerdown).
722
+ * Use for muting audio during drag to improve gesture performance.
723
+ */
724
+ onDragStart?: () => void;
725
+ /**
726
+ * Called when drag gesture ends (pointerup/pointercancel).
727
+ * Use for unmuting audio after drag completes.
728
+ */
729
+ onDragEnd?: () => void;
677
730
  }
678
731
  interface PointerGestureBind {
679
732
  onPointerDown: (e: React.PointerEvent) => void;
@@ -731,7 +784,7 @@ interface ReelsProviderProps {
731
784
  declare function ReelsProvider({ children, adapters, debug }: ReelsProviderProps): react_jsx_runtime.JSX.Element;
732
785
  declare function useSDK(): SDKContextValue;
733
786
 
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;
787
+ declare function ReelsFeed({ renderOverlay, renderActions, renderPauseAction, renderLoading, renderEmpty, renderError: _renderError, showFps, loadMoreThreshold, onSlotChange, gestureConfig, snapConfig, initialMuted, onAutoplayBlocked, }: 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;
735
788
 
736
789
  /**
737
790
  * useHls — React hook for hls.js lifecycle management (3-Tier buffer support)
@@ -782,12 +835,6 @@ interface UseHlsOptions {
782
835
  interface UseHlsReturn {
783
836
  /** Whether hls.js is being used (false = native HLS on Safari) */
784
837
  isHlsJs: boolean;
785
- /**
786
- * Whether the device uses native HLS (Safari / iOS WebView).
787
- * When true, play-ahead (video.play() on non-active slots) must be skipped —
788
- * iOS only allows one concurrently-playing video element at a time.
789
- */
790
- isNativeHls: boolean;
791
838
  /** Whether the video has buffered enough data to play without black flash */
792
839
  isReady: boolean;
793
840
  /** Destroy the HLS instance manually (also called automatically on unmount) */
@@ -804,13 +851,14 @@ interface VideoSlotProps {
804
851
  bufferTier: BufferTier;
805
852
  isMuted: boolean;
806
853
  onToggleMute: () => void;
854
+ /** Called when unmuted autoplay fails and SDK falls back to muted playback */
855
+ onAutoplayBlocked?: () => void;
807
856
  showFps?: boolean;
808
- renderOverlay?: (item: ContentItem, actions: SlotActions) => ReactNode;
809
- renderActions?: (item: ContentItem, actions: SlotActions) => ReactNode;
810
- renderPauseIndicator?: (isPaused: boolean) => ReactNode;
811
- renderDoubleTap?: (isDoubleTap: boolean) => ReactNode;
857
+ renderOverlay?: (item: ContentItem, actions: SlotActions) => react.ReactNode;
858
+ renderActions?: (item: ContentItem, actions: SlotActions) => react.ReactNode;
859
+ renderPauseAction?: (item: ContentItem, actions: PauseSlotActions) => react.ReactNode;
812
860
  }
813
- declare function VideoSlot({ item, index, isActive, isPrefetch, isPreloaded, bufferTier, isMuted, onToggleMute, showFps, renderOverlay, renderActions, renderPauseIndicator, renderDoubleTap, }: VideoSlotProps): react_jsx_runtime.JSX.Element;
861
+ declare function VideoSlot({ item, index, isActive, isPrefetch, isPreloaded, bufferTier, isMuted, onToggleMute, onAutoplayBlocked, showFps, renderOverlay, renderActions, renderPauseAction, }: VideoSlotProps): react_jsx_runtime.JSX.Element;
814
862
 
815
863
  declare function DefaultOverlay({ item }: {
816
864
  item: ContentItem;
@@ -829,14 +877,14 @@ declare function DefaultActions({ item, actions }: {
829
877
  declare function DefaultSkeleton(): react_jsx_runtime.JSX.Element;
830
878
 
831
879
  /**
832
- * DefaultDoubleTap — Default double-tap heart animation overlay
880
+ * DefaultPauseAction — Default play icon shown when video is manually paused
833
881
  *
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.
882
+ * Renders a semi-transparent circular play button in the center of the slot.
883
+ * Fades in smoothly when isPaused = true. Matches TikTok / Instagram Reels UX.
884
+ *
885
+ * Used when host app does not provide renderPauseAction prop.
836
886
  */
837
- declare function DefaultDoubleTap({ isDoubleTap }: {
838
- isDoubleTap: boolean;
839
- }): react_jsx_runtime.JSX.Element | null;
887
+ declare function DefaultPauseAction(): react_jsx_runtime.JSX.Element;
840
888
 
841
889
  declare function useFeedSelector<T>(selector: (state: FeedState) => T): T;
842
890
  declare function useFeed(): {
@@ -900,6 +948,7 @@ declare function useResource(): {
900
948
  networkType: NetworkType;
901
949
  isActive: boolean;
902
950
  prefetchIndex: number | null;
951
+ preloadQueue: number[];
903
952
  setFocusedIndex: (i: number) => void;
904
953
  setFocusedIndexImmediate: (i: number) => void;
905
954
  setTotalItems: (n: number) => void;
@@ -907,6 +956,7 @@ declare function useResource(): {
907
956
  isAllocated: (i: number) => boolean;
908
957
  isWarmAllocated: (i: number) => boolean;
909
958
  setPrefetchIndex: (i: number | null) => void;
959
+ getTier: (index: number) => 3 | 1 | 2 | 4 | null;
910
960
  };
911
961
 
912
962
  /**
@@ -970,6 +1020,7 @@ declare class MockVideoLoader implements IVideoLoader {
970
1020
  isPreloaded(videoId: string): boolean;
971
1021
  getPreloadStatus(videoId: string): "idle" | "loading" | "loaded";
972
1022
  clearAll(): void;
1023
+ preloadMetadata(_url: string): void;
973
1024
  }
974
1025
  declare class MockDataSource implements IDataSource {
975
1026
  private totalItems;
@@ -1108,4 +1159,4 @@ declare class HttpError extends Error {
1108
1159
  constructor(status: number, message: string, body?: string | undefined);
1109
1160
  }
1110
1161
 
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 };
1162
+ 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, DefaultPauseAction, 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 PauseSlotActions, 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
@@ -246,6 +246,16 @@ interface IVideoLoader {
246
246
  isPreloaded(videoId: string): boolean;
247
247
  getPreloadStatus(videoId: string): PreloadStatus;
248
248
  clearAll(): void;
249
+ /**
250
+ * Tier 4 cold prefetch — fetch HLS manifest vào HTTP browser cache.
251
+ * Fire-and-forget. Không download segment. Không cần DOM.
252
+ * Optional: nếu không implement, Tier 4 silently skipped.
253
+ *
254
+ * Implementation pattern:
255
+ * fetch(url, { method: 'GET', headers: { Range: 'bytes=0-0' } })
256
+ * // hoặc đơn giản: fetch(url)
257
+ */
258
+ preloadMetadata?(url: string): void;
249
259
  }
250
260
  interface CommentItem {
251
261
  id: string;
@@ -300,47 +310,53 @@ interface SlotActions {
300
310
  share: () => void;
301
311
  /** Current global mute state */
302
312
  isMuted: boolean;
303
- /** Toggle global mute */
313
+ /** Toggle global mute — exposed via SlotActions for use in renderActions button */
304
314
  toggleMute: () => void;
305
- /** Whether the active video is currently paused */
306
- isPaused: boolean;
307
- /** Toggle pause/play on the active video */
308
- togglePause: () => void;
309
315
  /** Whether this slot is the active playing slot */
310
316
  isActive: boolean;
311
317
  /** Slot index in feed */
312
318
  index: number;
313
319
  }
320
+ /**
321
+ * Actions provided to the pauseActionOverlay render callback.
322
+ * Extends SlotActions with play/pause control.
323
+ */
324
+ interface PauseSlotActions extends SlotActions {
325
+ /** Whether the video is currently manually paused (user tapped to pause) */
326
+ isPaused: boolean;
327
+ /** Toggle play/pause for the current video */
328
+ togglePlayPause: () => void;
329
+ }
314
330
  /** Props for the ReelsFeed component */
315
331
  interface ReelsFeedProps {
316
332
  /**
317
333
  * Custom overlay rendered on each video slot.
318
334
  * Receives the content item + actions. Return ReactNode.
319
- * Positioned absolute bottom (bottom-0) left by SDK.
335
+ * Positioned absolute bottom-left by SDK.
320
336
  * If not provided, SDK uses DefaultOverlay showing author + title.
321
337
  */
322
338
  renderOverlay?: (item: ContentItem, actions: SlotActions) => ReactNode;
323
339
  /**
324
340
  * Custom action bar rendered on each video slot.
325
341
  * Receives the content item + actions. Return ReactNode.
326
- * Positioned absolute bottom (bottom-0) right by SDK.
342
+ * Positioned absolute bottom-right by SDK.
327
343
  * If not provided, SDK uses DefaultActions showing like/comment/share emojis.
344
+ * NOTE: Mute/unmute button should live here — access via actions.toggleMute / actions.isMuted.
328
345
  */
329
346
  renderActions?: (item: ContentItem, actions: SlotActions) => ReactNode;
330
347
  /**
331
- * Custom pause/play indicator rendered when user taps to pause/play.
332
- * Receives isPaused state. Return ReactNode.
333
- * Positioned absolute center by SDK.
334
- * If not provided, SDK uses a default ▶️/⏸️ emoji indicator.
335
- */
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).
348
+ * Custom pause overlay rendered in the center of the video when it is manually paused.
349
+ * Only visible when the user taps to pause the active video.
350
+ * If not provided, SDK shows a default semi-transparent Play icon.
351
+ *
352
+ * Return null to suppress the overlay entirely.
353
+ *
354
+ * @example
355
+ * renderPauseAction={(item, actions) => (
356
+ * <PlayIcon size={72} onPress={actions.togglePlayPause} />
357
+ * )}
342
358
  */
343
- renderDoubleTap?: (isDoubleTap: boolean) => ReactNode;
359
+ renderPauseAction?: (item: ContentItem, actions: PauseSlotActions) => ReactNode;
344
360
  /**
345
361
  * Custom loading skeleton shown during initial feed load.
346
362
  * If not provided, SDK uses DefaultSkeleton with shimmer animation.
@@ -384,6 +400,25 @@ interface ReelsFeedProps {
384
400
  duration?: number;
385
401
  easing?: string;
386
402
  };
403
+ /**
404
+ * Initial mute state for video playback.
405
+ *
406
+ * - `true` (default): Videos start muted, satisfying all browser autoplay policies
407
+ * - `false`: SDK attempts unmuted autoplay. If browser blocks it, falls back to muted.
408
+ *
409
+ * Use `false` when you know the user has already interacted with the page
410
+ * (e.g., clicked a link to navigate to the reels page in Flutter WebView).
411
+ *
412
+ * @default true
413
+ */
414
+ initialMuted?: boolean;
415
+ /**
416
+ * Called when unmuted autoplay fails and SDK falls back to muted playback.
417
+ * Use this to show a "tap to unmute" UI hint to the user.
418
+ *
419
+ * Only fires when `initialMuted: false` and browser blocks unmuted autoplay.
420
+ */
421
+ onAutoplayBlocked?: () => void;
387
422
  }
388
423
 
389
424
  /**
@@ -607,6 +642,14 @@ declare class ResourceGovernor {
607
642
  isWarmAllocated(index: number): boolean;
608
643
  shouldRenderVideo(index: number): boolean;
609
644
  isPreloading(index: number): boolean;
645
+ /**
646
+ * Returns the buffer tier (1–4) for a given index.
647
+ * - 1: Active (playing, 10s buffer)
648
+ * - 2: Hot (±bufferWindow, 2s buffer, instant swap)
649
+ * - 3: Warm (manifest + 1 segment, ~300ms show)
650
+ * - 4: Cold (preload queue — manifest in HTTP cache, no DOM)
651
+ */
652
+ getTier(index: number): 1 | 2 | 3 | 4 | null;
610
653
  getActiveAllocations(): number[];
611
654
  getWarmAllocations(): number[];
612
655
  private recalculate;
@@ -674,6 +717,16 @@ interface PointerGestureConfig {
674
717
  onSnap?: (direction: 'forward' | 'backward') => void;
675
718
  /** Called when gesture ends without snap (bounce back) */
676
719
  onBounceBack?: () => void;
720
+ /**
721
+ * Called when drag gesture starts (pointerdown).
722
+ * Use for muting audio during drag to improve gesture performance.
723
+ */
724
+ onDragStart?: () => void;
725
+ /**
726
+ * Called when drag gesture ends (pointerup/pointercancel).
727
+ * Use for unmuting audio after drag completes.
728
+ */
729
+ onDragEnd?: () => void;
677
730
  }
678
731
  interface PointerGestureBind {
679
732
  onPointerDown: (e: React.PointerEvent) => void;
@@ -731,7 +784,7 @@ interface ReelsProviderProps {
731
784
  declare function ReelsProvider({ children, adapters, debug }: ReelsProviderProps): react_jsx_runtime.JSX.Element;
732
785
  declare function useSDK(): SDKContextValue;
733
786
 
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;
787
+ declare function ReelsFeed({ renderOverlay, renderActions, renderPauseAction, renderLoading, renderEmpty, renderError: _renderError, showFps, loadMoreThreshold, onSlotChange, gestureConfig, snapConfig, initialMuted, onAutoplayBlocked, }: 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;
735
788
 
736
789
  /**
737
790
  * useHls — React hook for hls.js lifecycle management (3-Tier buffer support)
@@ -782,12 +835,6 @@ interface UseHlsOptions {
782
835
  interface UseHlsReturn {
783
836
  /** Whether hls.js is being used (false = native HLS on Safari) */
784
837
  isHlsJs: boolean;
785
- /**
786
- * Whether the device uses native HLS (Safari / iOS WebView).
787
- * When true, play-ahead (video.play() on non-active slots) must be skipped —
788
- * iOS only allows one concurrently-playing video element at a time.
789
- */
790
- isNativeHls: boolean;
791
838
  /** Whether the video has buffered enough data to play without black flash */
792
839
  isReady: boolean;
793
840
  /** Destroy the HLS instance manually (also called automatically on unmount) */
@@ -804,13 +851,14 @@ interface VideoSlotProps {
804
851
  bufferTier: BufferTier;
805
852
  isMuted: boolean;
806
853
  onToggleMute: () => void;
854
+ /** Called when unmuted autoplay fails and SDK falls back to muted playback */
855
+ onAutoplayBlocked?: () => void;
807
856
  showFps?: boolean;
808
- renderOverlay?: (item: ContentItem, actions: SlotActions) => ReactNode;
809
- renderActions?: (item: ContentItem, actions: SlotActions) => ReactNode;
810
- renderPauseIndicator?: (isPaused: boolean) => ReactNode;
811
- renderDoubleTap?: (isDoubleTap: boolean) => ReactNode;
857
+ renderOverlay?: (item: ContentItem, actions: SlotActions) => react.ReactNode;
858
+ renderActions?: (item: ContentItem, actions: SlotActions) => react.ReactNode;
859
+ renderPauseAction?: (item: ContentItem, actions: PauseSlotActions) => react.ReactNode;
812
860
  }
813
- declare function VideoSlot({ item, index, isActive, isPrefetch, isPreloaded, bufferTier, isMuted, onToggleMute, showFps, renderOverlay, renderActions, renderPauseIndicator, renderDoubleTap, }: VideoSlotProps): react_jsx_runtime.JSX.Element;
861
+ declare function VideoSlot({ item, index, isActive, isPrefetch, isPreloaded, bufferTier, isMuted, onToggleMute, onAutoplayBlocked, showFps, renderOverlay, renderActions, renderPauseAction, }: VideoSlotProps): react_jsx_runtime.JSX.Element;
814
862
 
815
863
  declare function DefaultOverlay({ item }: {
816
864
  item: ContentItem;
@@ -829,14 +877,14 @@ declare function DefaultActions({ item, actions }: {
829
877
  declare function DefaultSkeleton(): react_jsx_runtime.JSX.Element;
830
878
 
831
879
  /**
832
- * DefaultDoubleTap — Default double-tap heart animation overlay
880
+ * DefaultPauseAction — Default play icon shown when video is manually paused
833
881
  *
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.
882
+ * Renders a semi-transparent circular play button in the center of the slot.
883
+ * Fades in smoothly when isPaused = true. Matches TikTok / Instagram Reels UX.
884
+ *
885
+ * Used when host app does not provide renderPauseAction prop.
836
886
  */
837
- declare function DefaultDoubleTap({ isDoubleTap }: {
838
- isDoubleTap: boolean;
839
- }): react_jsx_runtime.JSX.Element | null;
887
+ declare function DefaultPauseAction(): react_jsx_runtime.JSX.Element;
840
888
 
841
889
  declare function useFeedSelector<T>(selector: (state: FeedState) => T): T;
842
890
  declare function useFeed(): {
@@ -900,6 +948,7 @@ declare function useResource(): {
900
948
  networkType: NetworkType;
901
949
  isActive: boolean;
902
950
  prefetchIndex: number | null;
951
+ preloadQueue: number[];
903
952
  setFocusedIndex: (i: number) => void;
904
953
  setFocusedIndexImmediate: (i: number) => void;
905
954
  setTotalItems: (n: number) => void;
@@ -907,6 +956,7 @@ declare function useResource(): {
907
956
  isAllocated: (i: number) => boolean;
908
957
  isWarmAllocated: (i: number) => boolean;
909
958
  setPrefetchIndex: (i: number | null) => void;
959
+ getTier: (index: number) => 3 | 1 | 2 | 4 | null;
910
960
  };
911
961
 
912
962
  /**
@@ -970,6 +1020,7 @@ declare class MockVideoLoader implements IVideoLoader {
970
1020
  isPreloaded(videoId: string): boolean;
971
1021
  getPreloadStatus(videoId: string): "idle" | "loading" | "loaded";
972
1022
  clearAll(): void;
1023
+ preloadMetadata(_url: string): void;
973
1024
  }
974
1025
  declare class MockDataSource implements IDataSource {
975
1026
  private totalItems;
@@ -1108,4 +1159,4 @@ declare class HttpError extends Error {
1108
1159
  constructor(status: number, message: string, body?: string | undefined);
1109
1160
  }
1110
1161
 
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 };
1162
+ 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, DefaultPauseAction, 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 PauseSlotActions, 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 };