@xhub-reels/sdk 0.1.22 → 0.2.1

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/README.md CHANGED
@@ -111,6 +111,48 @@ function SwipeableFeed() {
111
111
  }
112
112
  ```
113
113
 
114
+ ## Thumbnail grid
115
+
116
+ Headless pre-drawer browsing UX. Mount inside `<ReelsProvider>`. Host provides the
117
+ card visuals via `renderThumbnail`; the SDK ships no default card.
118
+
119
+ ```tsx
120
+ import { ReelsFeedThumbnail } from 'xhub-reels-sdk';
121
+
122
+ <ReelsFeedThumbnail
123
+ renderThumbnail={(videoData) => (
124
+ <article className="aspect-[3/2] rounded-lg overflow-hidden">
125
+ <img src={videoData.poster} alt="" />
126
+ <p>@{videoData.author.name}</p>
127
+ </article>
128
+ )}
129
+ onThumbnailClick={(id) => openDrawer(id)}
130
+ />
131
+ ```
132
+
133
+ Opt-in hover prefetch (warms HLS manifest via `adapters.videoLoader.preloadMetadata`):
134
+
135
+ ```tsx
136
+ <ReelsFeedThumbnail prefetchOnHover renderThumbnail={...} />
137
+ ```
138
+
139
+ On click the SDK calls `ResourceGovernor.setFocusedIndexImmediate(index)` before
140
+ invoking `onThumbnailClick`, so opening `<ReelsFeed>` lands on the tapped item
141
+ without a scroll-to-index flash. Disable with `setFocusOnClick={false}`.
142
+
143
+ Custom slots for the zero-items branches:
144
+
145
+ ```tsx
146
+ <ReelsFeedThumbnail
147
+ renderThumbnail={(item) => <Card item={item} />}
148
+ renderLoading={() => <SkeletonGrid />}
149
+ renderEmpty={() => <EmptyState />}
150
+ renderError={({ message, retry }) => (
151
+ <ErrorBox message={message} onRetry={retry} />
152
+ )}
153
+ />
154
+ ```
155
+
114
156
  ## Architecture
115
157
 
116
158
  ```
package/dist/index.cjs CHANGED
@@ -2499,6 +2499,88 @@ function parsePxTranslateY(el) {
2499
2499
  if (!match || !match[1]) return 0;
2500
2500
  return Number.parseFloat(match[1]);
2501
2501
  }
2502
+ var DEFAULT_CLASSNAME = "grid grid-cols-2 gap-3";
2503
+ var defaultGetKey = (item) => item.id;
2504
+ var buttonResetStyle = {
2505
+ all: "unset",
2506
+ display: "block",
2507
+ cursor: "pointer",
2508
+ width: "100%",
2509
+ boxSizing: "border-box"
2510
+ };
2511
+ function ReelsFeedThumbnail({
2512
+ renderThumbnail,
2513
+ onThumbnailClick,
2514
+ renderLoading,
2515
+ renderEmpty,
2516
+ renderError,
2517
+ className = DEFAULT_CLASSNAME,
2518
+ wrap = true,
2519
+ setFocusOnClick = true,
2520
+ prefetchOnHover = false,
2521
+ getKey = defaultGetKey
2522
+ }) {
2523
+ const { items, loading, error, refresh } = useFeed();
2524
+ const { setFocusedIndexImmediate } = useResource();
2525
+ const { adapters } = useSDK();
2526
+ const prefetchedRef = react.useRef(/* @__PURE__ */ new Set());
2527
+ const handleClick = react.useCallback(
2528
+ (item, index) => {
2529
+ if (setFocusOnClick) {
2530
+ setFocusedIndexImmediate(index);
2531
+ }
2532
+ onThumbnailClick?.(item.id, item, index);
2533
+ },
2534
+ [onThumbnailClick, setFocusOnClick, setFocusedIndexImmediate]
2535
+ );
2536
+ const handlePointerEnter = react.useCallback(
2537
+ (item) => {
2538
+ if (!prefetchOnHover) return;
2539
+ if (!isVideoItem(item)) return;
2540
+ if (item.source.type !== "hls") return;
2541
+ if (prefetchedRef.current.has(item.id)) return;
2542
+ const loader = adapters.videoLoader;
2543
+ if (!loader?.preloadMetadata) return;
2544
+ if (loader.isPreloaded(item.id)) {
2545
+ prefetchedRef.current.add(item.id);
2546
+ return;
2547
+ }
2548
+ loader.preloadMetadata(item.source.url);
2549
+ prefetchedRef.current.add(item.id);
2550
+ },
2551
+ [prefetchOnHover, adapters.videoLoader]
2552
+ );
2553
+ const children = react.useMemo(
2554
+ () => items.map((item, index) => {
2555
+ const key = getKey(item, index);
2556
+ const onEnter = prefetchOnHover ? (_e) => handlePointerEnter(item) : void 0;
2557
+ return /* @__PURE__ */ jsxRuntime.jsx(
2558
+ "button",
2559
+ {
2560
+ type: "button",
2561
+ style: buttonResetStyle,
2562
+ "data-thumbnail-index": index,
2563
+ "data-thumbnail-id": item.id,
2564
+ onClick: () => handleClick(item, index),
2565
+ onPointerEnter: onEnter,
2566
+ children: renderThumbnail(item, index)
2567
+ },
2568
+ key
2569
+ );
2570
+ }),
2571
+ [items, getKey, prefetchOnHover, handlePointerEnter, handleClick, renderThumbnail]
2572
+ );
2573
+ if (items.length === 0) {
2574
+ if (loading && renderLoading) return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: renderLoading() });
2575
+ if (error && renderError) {
2576
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: renderError({ message: error.message, retry: refresh }) });
2577
+ }
2578
+ if (!loading && !error && renderEmpty) return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: renderEmpty() });
2579
+ return null;
2580
+ }
2581
+ if (!wrap) return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children });
2582
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className, children });
2583
+ }
2502
2584
  function usePlayerSelector(selector) {
2503
2585
  const { playerEngine } = useSDK();
2504
2586
  const selectorRef = react.useRef(selector);
@@ -3131,6 +3213,7 @@ exports.OptimisticManager = OptimisticManager;
3131
3213
  exports.PlayerEngine = PlayerEngine;
3132
3214
  exports.PlayerStatus = PlayerStatus;
3133
3215
  exports.ReelsFeed = ReelsFeed;
3216
+ exports.ReelsFeedThumbnail = ReelsFeedThumbnail;
3134
3217
  exports.ReelsProvider = ReelsProvider;
3135
3218
  exports.ResourceGovernor = ResourceGovernor;
3136
3219
  exports.VALID_TRANSITIONS = VALID_TRANSITIONS;
package/dist/index.d.cts CHANGED
@@ -875,6 +875,41 @@ interface VideoSlotProps {
875
875
  }
876
876
  declare function VideoSlot({ item, index, isActive, isPrefetch, isPreloaded, bufferTier, isMuted, onToggleMute, onAutoplayBlocked, showFps, isDragging, renderOverlay, renderActions, renderPauseAction, }: VideoSlotProps): react_jsx_runtime.JSX.Element;
877
877
 
878
+ interface ReelsFeedThumbnailProps {
879
+ /** Render function for a single item's visual card. */
880
+ renderThumbnail: (videoData: ContentItem, index: number) => ReactNode;
881
+ /** Click handler — receives the item id, full data, and index in the feed. */
882
+ onThumbnailClick?: (id: string, videoData: ContentItem, index: number) => void;
883
+ /** Rendered when the feed is loading and has zero items yet. */
884
+ renderLoading?: () => ReactNode;
885
+ /** Rendered when the feed has loaded but is empty. */
886
+ renderEmpty?: () => ReactNode;
887
+ /** Rendered when the feed fails with no items — receives a retry callback. */
888
+ renderError?: (error: {
889
+ message: string;
890
+ retry: () => void;
891
+ }) => ReactNode;
892
+ /** Outer wrapper className. Defaults to `grid grid-cols-2 gap-3`. */
893
+ className?: string;
894
+ /** If the host wants to render its own wrapper, pass `false`. */
895
+ wrap?: boolean;
896
+ /**
897
+ * Update ResourceGovernor's focused index on click so the drawer/feed opens
898
+ * already pointing at the tapped item.
899
+ * @default true
900
+ */
901
+ setFocusOnClick?: boolean;
902
+ /**
903
+ * Prefetch HLS metadata for this slot on `pointerenter`. Off by default;
904
+ * only useful on hover-capable devices.
905
+ * @default false
906
+ */
907
+ prefetchOnHover?: boolean;
908
+ /** Key override — useful when host renders multiple lists from the same feed. */
909
+ getKey?: (item: ContentItem, index: number) => string;
910
+ }
911
+ declare function ReelsFeedThumbnail({ renderThumbnail, onThumbnailClick, renderLoading, renderEmpty, renderError, className, wrap, setFocusOnClick, prefetchOnHover, getKey, }: ReelsFeedThumbnailProps): react_jsx_runtime.JSX.Element | null;
912
+
878
913
  declare function DefaultOverlay({ item }: {
879
914
  item: ContentItem;
880
915
  }): react_jsx_runtime.JSX.Element;
@@ -1174,4 +1209,4 @@ declare class HttpError extends Error {
1174
1209
  constructor(status: number, message: string, body?: string | undefined);
1175
1210
  }
1176
1211
 
1177
- 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 };
1212
+ 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, ReelsFeedThumbnail, type ReelsFeedThumbnailProps, 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
@@ -875,6 +875,41 @@ interface VideoSlotProps {
875
875
  }
876
876
  declare function VideoSlot({ item, index, isActive, isPrefetch, isPreloaded, bufferTier, isMuted, onToggleMute, onAutoplayBlocked, showFps, isDragging, renderOverlay, renderActions, renderPauseAction, }: VideoSlotProps): react_jsx_runtime.JSX.Element;
877
877
 
878
+ interface ReelsFeedThumbnailProps {
879
+ /** Render function for a single item's visual card. */
880
+ renderThumbnail: (videoData: ContentItem, index: number) => ReactNode;
881
+ /** Click handler — receives the item id, full data, and index in the feed. */
882
+ onThumbnailClick?: (id: string, videoData: ContentItem, index: number) => void;
883
+ /** Rendered when the feed is loading and has zero items yet. */
884
+ renderLoading?: () => ReactNode;
885
+ /** Rendered when the feed has loaded but is empty. */
886
+ renderEmpty?: () => ReactNode;
887
+ /** Rendered when the feed fails with no items — receives a retry callback. */
888
+ renderError?: (error: {
889
+ message: string;
890
+ retry: () => void;
891
+ }) => ReactNode;
892
+ /** Outer wrapper className. Defaults to `grid grid-cols-2 gap-3`. */
893
+ className?: string;
894
+ /** If the host wants to render its own wrapper, pass `false`. */
895
+ wrap?: boolean;
896
+ /**
897
+ * Update ResourceGovernor's focused index on click so the drawer/feed opens
898
+ * already pointing at the tapped item.
899
+ * @default true
900
+ */
901
+ setFocusOnClick?: boolean;
902
+ /**
903
+ * Prefetch HLS metadata for this slot on `pointerenter`. Off by default;
904
+ * only useful on hover-capable devices.
905
+ * @default false
906
+ */
907
+ prefetchOnHover?: boolean;
908
+ /** Key override — useful when host renders multiple lists from the same feed. */
909
+ getKey?: (item: ContentItem, index: number) => string;
910
+ }
911
+ declare function ReelsFeedThumbnail({ renderThumbnail, onThumbnailClick, renderLoading, renderEmpty, renderError, className, wrap, setFocusOnClick, prefetchOnHover, getKey, }: ReelsFeedThumbnailProps): react_jsx_runtime.JSX.Element | null;
912
+
878
913
  declare function DefaultOverlay({ item }: {
879
914
  item: ContentItem;
880
915
  }): react_jsx_runtime.JSX.Element;
@@ -1174,4 +1209,4 @@ declare class HttpError extends Error {
1174
1209
  constructor(status: number, message: string, body?: string | undefined);
1175
1210
  }
1176
1211
 
1177
- 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 };
1212
+ 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, ReelsFeedThumbnail, type ReelsFeedThumbnailProps, 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
@@ -2493,6 +2493,88 @@ function parsePxTranslateY(el) {
2493
2493
  if (!match || !match[1]) return 0;
2494
2494
  return Number.parseFloat(match[1]);
2495
2495
  }
2496
+ var DEFAULT_CLASSNAME = "grid grid-cols-2 gap-3";
2497
+ var defaultGetKey = (item) => item.id;
2498
+ var buttonResetStyle = {
2499
+ all: "unset",
2500
+ display: "block",
2501
+ cursor: "pointer",
2502
+ width: "100%",
2503
+ boxSizing: "border-box"
2504
+ };
2505
+ function ReelsFeedThumbnail({
2506
+ renderThumbnail,
2507
+ onThumbnailClick,
2508
+ renderLoading,
2509
+ renderEmpty,
2510
+ renderError,
2511
+ className = DEFAULT_CLASSNAME,
2512
+ wrap = true,
2513
+ setFocusOnClick = true,
2514
+ prefetchOnHover = false,
2515
+ getKey = defaultGetKey
2516
+ }) {
2517
+ const { items, loading, error, refresh } = useFeed();
2518
+ const { setFocusedIndexImmediate } = useResource();
2519
+ const { adapters } = useSDK();
2520
+ const prefetchedRef = useRef(/* @__PURE__ */ new Set());
2521
+ const handleClick = useCallback(
2522
+ (item, index) => {
2523
+ if (setFocusOnClick) {
2524
+ setFocusedIndexImmediate(index);
2525
+ }
2526
+ onThumbnailClick?.(item.id, item, index);
2527
+ },
2528
+ [onThumbnailClick, setFocusOnClick, setFocusedIndexImmediate]
2529
+ );
2530
+ const handlePointerEnter = useCallback(
2531
+ (item) => {
2532
+ if (!prefetchOnHover) return;
2533
+ if (!isVideoItem(item)) return;
2534
+ if (item.source.type !== "hls") return;
2535
+ if (prefetchedRef.current.has(item.id)) return;
2536
+ const loader = adapters.videoLoader;
2537
+ if (!loader?.preloadMetadata) return;
2538
+ if (loader.isPreloaded(item.id)) {
2539
+ prefetchedRef.current.add(item.id);
2540
+ return;
2541
+ }
2542
+ loader.preloadMetadata(item.source.url);
2543
+ prefetchedRef.current.add(item.id);
2544
+ },
2545
+ [prefetchOnHover, adapters.videoLoader]
2546
+ );
2547
+ const children = useMemo(
2548
+ () => items.map((item, index) => {
2549
+ const key = getKey(item, index);
2550
+ const onEnter = prefetchOnHover ? (_e) => handlePointerEnter(item) : void 0;
2551
+ return /* @__PURE__ */ jsx(
2552
+ "button",
2553
+ {
2554
+ type: "button",
2555
+ style: buttonResetStyle,
2556
+ "data-thumbnail-index": index,
2557
+ "data-thumbnail-id": item.id,
2558
+ onClick: () => handleClick(item, index),
2559
+ onPointerEnter: onEnter,
2560
+ children: renderThumbnail(item, index)
2561
+ },
2562
+ key
2563
+ );
2564
+ }),
2565
+ [items, getKey, prefetchOnHover, handlePointerEnter, handleClick, renderThumbnail]
2566
+ );
2567
+ if (items.length === 0) {
2568
+ if (loading && renderLoading) return /* @__PURE__ */ jsx(Fragment, { children: renderLoading() });
2569
+ if (error && renderError) {
2570
+ return /* @__PURE__ */ jsx(Fragment, { children: renderError({ message: error.message, retry: refresh }) });
2571
+ }
2572
+ if (!loading && !error && renderEmpty) return /* @__PURE__ */ jsx(Fragment, { children: renderEmpty() });
2573
+ return null;
2574
+ }
2575
+ if (!wrap) return /* @__PURE__ */ jsx(Fragment, { children });
2576
+ return /* @__PURE__ */ jsx("div", { className, children });
2577
+ }
2496
2578
  function usePlayerSelector(selector) {
2497
2579
  const { playerEngine } = useSDK();
2498
2580
  const selectorRef = useRef(selector);
@@ -3103,4 +3185,4 @@ var HttpError = class extends Error {
3103
3185
  }
3104
3186
  };
3105
3187
 
3106
- export { DEFAULT_FEED_CONFIG, DEFAULT_PLAYER_CONFIG, DEFAULT_RESOURCE_CONFIG, DefaultActions, DefaultOverlay, DefaultPauseAction, 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 };
3188
+ export { DEFAULT_FEED_CONFIG, DEFAULT_PLAYER_CONFIG, DEFAULT_RESOURCE_CONFIG, DefaultActions, DefaultOverlay, DefaultPauseAction, DefaultSkeleton, FeedManager, HttpDataSource, HttpError, MockAnalytics, MockCommentAdapter, MockDataSource, MockInteraction, MockLogger, MockNetworkAdapter, MockSessionStorage, MockVideoLoader, OptimisticManager, PlayerEngine, PlayerStatus, ReelsFeed, ReelsFeedThumbnail, ReelsProvider, ResourceGovernor, VALID_TRANSITIONS, VideoSlot, canPause, canPlay, canSeek, isArticle, isValidTransition, isVideoItem, useFeed, useFeedSelector, useHls, usePlayer, usePlayerSelector, usePointerGesture, useResource, useResourceSelector, useSDK, useSnapAnimation };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xhub-reels/sdk",
3
- "version": "0.1.22",
3
+ "version": "0.2.1",
4
4
  "description": "High-performance Short Video / Reels SDK for React — optimized for Flutter WebView",
5
5
  "license": "MIT",
6
6
  "type": "module",