@xhub-short/sdk 0.1.0-beta.3 → 0.1.0-beta.5

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
@@ -597,6 +597,75 @@ import { VideoSlotOverlay, VideoSlotPoster } from '@xhub-short/ui';
597
597
 
598
598
  ---
599
599
 
600
+ ## 👤 Guest Mode (Chế độ khách)
601
+
602
+ SDK hỗ trợ chế độ khách cho phép người dùng chưa đăng nhập xem video và bình luận (read-only). Các tương tác (Like, Comment, Follow) sẽ bị chặn và trigger callback để Host App xử lý (ví dụ: hiện modal đăng nhập).
603
+
604
+ ### Cấu hình
605
+
606
+ ```tsx
607
+ <ShortVideoRoot
608
+ config={{
609
+ // ...
610
+ guest: {
611
+ /**
612
+ * 'auto': Tự động detect dựa trên auth token (default)
613
+ * true: Force guest mode
614
+ * false: Disable guest mode
615
+ */
616
+ mode: 'auto',
617
+
618
+ /**
619
+ * Callback khi guest thực hiện hành động cần auth (Like, Comment, Follow...)
620
+ */
621
+ onAction: (action, context) => {
622
+ console.log('Guest Action:', action, context);
623
+ // VD: showLoginModal();
624
+ }
625
+ }
626
+ }}
627
+ >
628
+ <VideoFeed />
629
+ </ShortVideoRoot>
630
+ ```
631
+
632
+ ### Các hành động được chặn
633
+ - **Like / Bookmark**: Trigger `onAction`
634
+ - **Follow**: Trigger `onAction`
635
+ - **Comment Input**: Hiển thị nút "Login to comment". Khi click triggers `onAction` (`action='comment'`).
636
+
637
+ ---
638
+
639
+ ## ⚡ Prefetch Data (Tải trước dữ liệu)
640
+
641
+ Cho phép Host App tải trước dữ liệu Feed (Reels) để trải nghiệm hiển thị tức thì (instant loading).
642
+
643
+ ### Cách sử dụng
644
+
645
+ Gọi hàm `prefetchFeed` trước khi mount SDK components (ví dụ: khi hover vào menu Reels hoặc trong route loader).
646
+
647
+ ```tsx
648
+ import { prefetchFeed } from '@xhub-short/sdk';
649
+
650
+ // 1. Prefetch data (lưu vào bộ nhớ tạm)
651
+ // Có thể gọi ở bất kỳ đâu trong Host App
652
+ await prefetchFeed(sdkConfig, { ttl: 5 * 60 * 1000 });
653
+
654
+ // ... Sau đó ...
655
+
656
+ // 2. Khi User vào trang Reels, SDK sẽ tự động dùng data đã fetch
657
+ <ShortVideoRoot config={sdkConfig}>
658
+ <VideoFeed />
659
+ </ShortVideoRoot>
660
+ ```
661
+
662
+ ### Đặc điểm
663
+ - **In-Memory Cache**: Dữ liệu chỉ lưu tạm trong RAM, mất khi refresh trang (đảm bảo fresh data).
664
+ - **Auto-Consume**: `ShortVideoRoot` tự động tiêu thụ cache và xóa sau khi dùng.
665
+ - **Performance**: Giúp giảm thời gian chờ đợi (LCP) xuống gần bằng 0 khi user chuyển trang.
666
+
667
+ ---
668
+
600
669
  ## 🔗 Liên kết với các Packages
601
670
 
602
671
  | Package | Quan hệ với SDK |
package/dist/index.d.ts CHANGED
@@ -379,6 +379,7 @@ declare function TranslatedSheetHeader(props: SheetHeaderProps): ReactElement;
379
379
  declare function TranslatedCommentList(props: CommentListProps): ReactElement;
380
380
  /**
381
381
  * Translated CommentInput - auto-injects i18n strings
382
+ * Handles guest mode by showing login prompt
382
383
  */
383
384
  declare function TranslatedCommentInput(props: CommentInputProps): ReactElement;
384
385
  declare const CommentSheet: typeof CommentSheetInner & {
@@ -1272,6 +1273,67 @@ interface AdaptersConfig {
1272
1273
  /** Poster loader adapter for preloading thumbnails */
1273
1274
  posterLoader?: IPosterLoader;
1274
1275
  }
1276
+ /**
1277
+ * Actions that require authentication
1278
+ *
1279
+ * These actions will trigger the `onAction` callback in guest mode
1280
+ * instead of making API requests.
1281
+ */
1282
+ type GuestAction = 'like' | 'unlike' | 'comment' | 'reply' | 'follow' | 'unfollow' | 'bookmark' | 'like_comment';
1283
+ /**
1284
+ * Context for guest action
1285
+ *
1286
+ * Provides information about the resource being acted upon.
1287
+ */
1288
+ interface GuestActionContext {
1289
+ /** Type of resource */
1290
+ resourceType: 'video' | 'comment' | 'author';
1291
+ /** Resource ID */
1292
+ resourceId: string;
1293
+ /** Additional metadata (e.g., videoId for comment, authorId for follow) */
1294
+ metadata?: Record<string, unknown>;
1295
+ }
1296
+ /**
1297
+ * Guest mode configuration
1298
+ *
1299
+ * Controls how the SDK behaves for unauthenticated users.
1300
+ */
1301
+ interface GuestModeConfig {
1302
+ /**
1303
+ * Enable guest mode
1304
+ *
1305
+ * - 'auto': Automatically detect based on getAccessToken() returning null (default)
1306
+ * - true: Force guest mode (always treat user as guest)
1307
+ * - false: Disable guest mode (require authentication)
1308
+ *
1309
+ * @default 'auto'
1310
+ */
1311
+ mode?: 'auto' | boolean;
1312
+ /**
1313
+ * Callback when guest tries to perform authenticated action
1314
+ *
1315
+ * Called instead of making API requests when user is in guest mode.
1316
+ * Host app can use this to show login modal, redirect, etc.
1317
+ *
1318
+ * @param action - The action guest tried to perform
1319
+ * @param context - Context about the resource
1320
+ *
1321
+ * @example
1322
+ * ```tsx
1323
+ * <ShortVideoProvider config={{
1324
+ * guest: {
1325
+ * onAction: (action, context) => {
1326
+ * console.log(`Guest tried to ${action}`, context);
1327
+ * if (action === 'like' || action === 'comment') {
1328
+ * showLoginModal();
1329
+ * }
1330
+ * }
1331
+ * }
1332
+ * }}>
1333
+ * ```
1334
+ */
1335
+ onAction?: (action: GuestAction, context: GuestActionContext) => void;
1336
+ }
1275
1337
  /**
1276
1338
  * SDK Configuration
1277
1339
  *
@@ -1419,6 +1481,30 @@ interface SDKConfig {
1419
1481
  * @default false
1420
1482
  */
1421
1483
  debug?: boolean;
1484
+ /**
1485
+ * Guest mode configuration
1486
+ *
1487
+ * When enabled, SDK allows unauthenticated users to browse content.
1488
+ * Interactive actions (like, comment, follow) will trigger callbacks
1489
+ * instead of making API requests.
1490
+ *
1491
+ * @example
1492
+ * ```tsx
1493
+ * <ShortVideoProvider config={{
1494
+ * guest: {
1495
+ * mode: 'auto',
1496
+ * onAction: (action, context) => {
1497
+ * if (action === 'like' || action === 'comment') {
1498
+ * showLoginModal();
1499
+ * }
1500
+ * }
1501
+ * }
1502
+ * }}>
1503
+ * <App />
1504
+ * </ShortVideoProvider>
1505
+ * ```
1506
+ */
1507
+ guest?: GuestModeConfig;
1422
1508
  }
1423
1509
  /**
1424
1510
  * Props for ShortVideoProvider component
@@ -1861,6 +1947,75 @@ interface UsePlayerReturn {
1861
1947
  * ```
1862
1948
  */
1863
1949
  declare function usePlayer(): UsePlayerReturn;
1950
+ /**
1951
+ * Return type for usePlayerCore hook
1952
+ *
1953
+ * This is a subset of UsePlayerReturn that excludes time-based fields
1954
+ * (currentTime, duration, buffered, watchTime, loopCount, progress, bufferProgress)
1955
+ * to prevent re-renders during playback.
1956
+ */
1957
+ interface UsePlayerCoreReturn {
1958
+ /** Currently loaded video */
1959
+ currentVideo: VideoItem | null;
1960
+ /** Player status */
1961
+ status: PlayerStatus;
1962
+ /** Whether audio is muted */
1963
+ muted: boolean;
1964
+ /** Volume level (0-1) */
1965
+ volume: number;
1966
+ /** Current error, if any */
1967
+ error: PlayerError | null;
1968
+ /** Playback speed rate */
1969
+ playbackRate: number;
1970
+ /** Whether video has ended */
1971
+ ended: boolean;
1972
+ /** Whether currently playing */
1973
+ isPlaying: boolean;
1974
+ /** Whether currently paused */
1975
+ isPaused: boolean;
1976
+ /** Whether currently buffering */
1977
+ isBuffering: boolean;
1978
+ /** Whether currently loading */
1979
+ isLoading: boolean;
1980
+ /** Whether in error state */
1981
+ hasError: boolean;
1982
+ /** Whether in idle state */
1983
+ isIdle: boolean;
1984
+ /** Load a video */
1985
+ load: (video: VideoItem) => void;
1986
+ /** Start playback */
1987
+ play: () => boolean;
1988
+ /** Pause playback */
1989
+ pause: () => boolean;
1990
+ /** Toggle play/pause */
1991
+ togglePlay: () => boolean;
1992
+ /** Seek to position */
1993
+ seek: (time: number) => boolean;
1994
+ /** Set muted state */
1995
+ setMuted: (muted: boolean) => void;
1996
+ /** Toggle mute */
1997
+ toggleMute: () => void;
1998
+ /** Set volume (0-1) */
1999
+ setVolume: (volume: number) => void;
2000
+ /** Set playback rate */
2001
+ setPlaybackRate: (rate: number) => void;
2002
+ /** Report time update */
2003
+ onTimeUpdate: (time: number) => void;
2004
+ /** Report buffering started */
2005
+ onBuffering: () => boolean;
2006
+ /** Report buffering ended */
2007
+ onBufferingEnd: () => boolean;
2008
+ /** Report buffer progress */
2009
+ onBufferProgress: (percent: number) => void;
2010
+ /** Report video ended */
2011
+ onEnded: () => void;
2012
+ /** Report error */
2013
+ onError: (error: Error, mediaError?: MediaError) => void;
2014
+ /** Reset player */
2015
+ reset: () => void;
2016
+ /** Pre-built event handlers for <video> element */
2017
+ handlers: VideoElementHandlers;
2018
+ }
1864
2019
  /**
1865
2020
  * Return type for usePlayerForVideo hook
1866
2021
  */
@@ -2082,13 +2237,6 @@ declare function useOptimistic(): {
2082
2237
  };
2083
2238
  type UseOptimisticReturn = ReturnType<typeof useOptimistic>;
2084
2239
 
2085
- /**
2086
- * SDK Factory and Store Management
2087
- *
2088
- * Creates and manages Core Domain managers with Dependency Injection.
2089
- * Supports configurable adapters and manager options.
2090
- */
2091
-
2092
2240
  /**
2093
2241
  * SDK instance containing all managers
2094
2242
  */
@@ -2116,6 +2264,13 @@ interface SDKInstance {
2116
2264
  /** Comment adapter (optional - only if comment feature is enabled) */
2117
2265
  comment?: ICommentAdapter;
2118
2266
  };
2267
+ /** Guest mode configuration */
2268
+ guest: {
2269
+ /** Whether user is currently in guest mode */
2270
+ isGuest: boolean;
2271
+ /** Guest mode config from SDKConfig */
2272
+ config?: GuestModeConfig;
2273
+ };
2119
2274
  /** Destroy all managers and cleanup resources */
2120
2275
  destroy: () => void;
2121
2276
  }
@@ -2151,6 +2306,22 @@ declare function getSDK(config?: SDKConfig): SDKInstance;
2151
2306
  * or when cleaning up (e.g., in tests).
2152
2307
  */
2153
2308
  declare function destroySDK(): void;
2309
+ /**
2310
+ * Prefetch feed data (Standalone functionality)
2311
+ *
2312
+ * Allows host app to fetch data before mounting the SDK components.
2313
+ * Data is stored in static in-memory cache and automatically consumed
2314
+ * when SDK initializes with the same configuration.
2315
+ *
2316
+ * @example
2317
+ * ```ts
2318
+ * // In routing logic or hover handler
2319
+ * await prefetchFeed(config);
2320
+ * ```
2321
+ */
2322
+ declare function prefetchFeed(config: SDKConfig, options?: {
2323
+ ttl?: number;
2324
+ }): Promise<void>;
2154
2325
 
2155
2326
  declare function useSDK(): SDKInstance;
2156
2327
 
@@ -2520,4 +2691,65 @@ declare function getMessages(locale: string): MessageCatalog;
2520
2691
  */
2521
2692
  declare function isLocaleSupported(locale: string): locale is SupportedLocale;
2522
2693
 
2523
- export { ActionBar, type ActionBarIconSet, type ActionBarProps as ActionBarWiredProps, type AdaptersConfig, AuthorInfo, type AuthorInfoProps as AuthorInfoWiredProps, CommentSheet, type CommentSheetProps, DEFAULT_LOCALE, DefaultSlot, type DefaultSlotProps, type HookReturn, LocalizationAdapter, LocalizationContext, LocalizationProvider, type LocalizationProviderProps, ProgressBar, type ProgressBarProps, type SDKConfig, type SDKInstance, SDKPlayerError, SUPPORTED_LOCALES, ShortVideoProvider, type ShortVideoProviderProps, ShortVideoRoot, type ShortVideoRootProps, type SupportedLocale, type SwipeConfig, type SwipeDirection, type SwipeState, type TranslateFn, type UseCommentOptions, type UseCommentReturn, type UseFeedReturn, type UseLifecycleOptions, type UseLifecycleReturn, type UseOptimisticReturn, type UsePlayerForVideoReturn, type UsePlayerReturn, type UseResourceAllocationReturn, type UseResourceReturn, type UseSwipeGestureReturn, type UseTranslationReturn, type VideoElementHandlers, VideoFeed, type VideoFeedProps, VideoInfo, type VideoInfoWiredProps, VideoPlayer, type VideoPlayerProps, VideoSlot, type VideoSlotWiredProps, type WireConfig, createSDK, createSimpleWireConfig, createWiredComponent, destroySDK, enMessages, getMessages, getSDK, isLocaleSupported, messageCatalogs, parseMessage, resetCommentManager, useComment, useFeed, useFeedSelector, useLifecycle, useLifecycleSelector, useLocalization, useOptimistic, useOptimisticSelector, useOptionalLocalization, useOptionalTranslation, usePlayer, usePlayerForVideo, usePlayerSelector, useResource, useResourceAllocation, useResourceSelector, useSDK, useSwipeGesture, useTranslation, viMessages };
2694
+ /**
2695
+ * useGuestMode Hook
2696
+ *
2697
+ * Detects and manages guest mode state.
2698
+ * Provides utilities for handling guest actions.
2699
+ */
2700
+
2701
+ /**
2702
+ * Return type for useGuestMode hook
2703
+ */
2704
+ interface UseGuestModeReturn {
2705
+ /**
2706
+ * Whether the current user is in guest mode
2707
+ */
2708
+ isGuest: boolean;
2709
+ /**
2710
+ * Trigger a guest action
2711
+ *
2712
+ * If in guest mode, calls the onAction callback.
2713
+ * If authenticated, returns false (action should proceed normally).
2714
+ *
2715
+ * @param action - The action being attempted
2716
+ * @param context - Context about the resource
2717
+ * @returns true if action was handled (guest mode), false if should proceed (authenticated)
2718
+ */
2719
+ handleGuestAction: (action: GuestAction, context: GuestActionContext) => boolean;
2720
+ /**
2721
+ * Check if user is authenticated
2722
+ */
2723
+ isAuthenticated: boolean;
2724
+ }
2725
+ /**
2726
+ * Hook for guest mode detection and handling
2727
+ *
2728
+ * Automatically detects guest mode based on:
2729
+ * 1. config.guest.mode setting
2730
+ * 2. Whether accessToken is available (auto-detection)
2731
+ *
2732
+ * @param guestConfig - Guest mode configuration from SDK config
2733
+ * @returns Guest mode state and utilities
2734
+ *
2735
+ * @example
2736
+ * ```tsx
2737
+ * function ActionBar() {
2738
+ * const { isGuest, handleGuestAction } = useGuestMode(config?.guest);
2739
+ *
2740
+ * const handleLike = () => {
2741
+ * if (handleGuestAction('like', {
2742
+ * resourceType: 'video',
2743
+ * resourceId: video.id
2744
+ * })) {
2745
+ * return; // Guest action handled
2746
+ * }
2747
+ * // Proceed with normal like
2748
+ * toggleLike(video.id);
2749
+ * };
2750
+ * }
2751
+ * ```
2752
+ */
2753
+ declare function useGuestMode(guestConfigOverride?: GuestModeConfig): UseGuestModeReturn;
2754
+
2755
+ export { ActionBar, type ActionBarIconSet, type ActionBarProps as ActionBarWiredProps, type AdaptersConfig, AuthorInfo, type AuthorInfoProps as AuthorInfoWiredProps, CommentSheet, type CommentSheetProps, DEFAULT_LOCALE, DefaultSlot, type DefaultSlotProps, type GuestAction, type GuestActionContext, type GuestModeConfig, type HookReturn, LocalizationAdapter, LocalizationContext, LocalizationProvider, type LocalizationProviderProps, ProgressBar, type ProgressBarProps, type SDKConfig, type SDKInstance, SDKPlayerError, SUPPORTED_LOCALES, ShortVideoProvider, type ShortVideoProviderProps, ShortVideoRoot, type ShortVideoRootProps, type SupportedLocale, type SwipeConfig, type SwipeDirection, type SwipeState, type TranslateFn, type UseCommentOptions, type UseCommentReturn, type UseFeedReturn, type UseGuestModeReturn, type UseLifecycleOptions, type UseLifecycleReturn, type UseOptimisticReturn, type UsePlayerCoreReturn, type UsePlayerForVideoReturn, type UsePlayerReturn, type UseResourceAllocationReturn, type UseResourceReturn, type UseSwipeGestureReturn, type UseTranslationReturn, type VideoElementHandlers, VideoFeed, type VideoFeedProps, VideoInfo, type VideoInfoWiredProps, VideoPlayer, type VideoPlayerProps, VideoSlot, type VideoSlotWiredProps, type WireConfig, createSDK, createSimpleWireConfig, createWiredComponent, destroySDK, enMessages, getMessages, getSDK, isLocaleSupported, messageCatalogs, parseMessage, prefetchFeed, resetCommentManager, useComment, useFeed, useFeedSelector, useGuestMode, useLifecycle, useLifecycleSelector, useLocalization, useOptimistic, useOptimisticSelector, useOptionalLocalization, useOptionalTranslation, usePlayer, usePlayerForVideo, usePlayerSelector, useResource, useResourceAllocation, useResourceSelector, useSDK, useSwipeGesture, useTranslation, viMessages };
package/dist/index.js CHANGED
@@ -117,6 +117,35 @@ function useFeed() {
117
117
  reset
118
118
  };
119
119
  }
120
+ function useGuestMode(guestConfigOverride) {
121
+ const sdk = useSDK();
122
+ const config = guestConfigOverride ?? sdk.guest.config;
123
+ const isGuest = useMemo(() => {
124
+ if (guestConfigOverride?.mode !== void 0) {
125
+ if (guestConfigOverride.mode === true) return true;
126
+ if (guestConfigOverride.mode === false) return false;
127
+ }
128
+ return sdk.guest.isGuest;
129
+ }, [guestConfigOverride?.mode, sdk.guest.isGuest]);
130
+ const isAuthenticated = !isGuest;
131
+ const handleGuestAction = useCallback(
132
+ (action, context) => {
133
+ if (!isGuest) {
134
+ return false;
135
+ }
136
+ if (config?.onAction) {
137
+ config.onAction(action, context);
138
+ }
139
+ return true;
140
+ },
141
+ [isGuest, config]
142
+ );
143
+ return {
144
+ isGuest,
145
+ isAuthenticated,
146
+ handleGuestAction
147
+ };
148
+ }
120
149
  function useOptimisticSelector(selector) {
121
150
  const { optimisticManager } = useSDK();
122
151
  return useSyncExternalStore(
@@ -246,11 +275,18 @@ function ActionBar({
246
275
  isLikePending
247
276
  };
248
277
  }, [overrideState, currentVideo, isLikePending]);
278
+ const { handleGuestAction } = useGuestMode();
249
279
  const handleToggleLike = useCallback(() => {
280
+ if (handleGuestAction("like", {
281
+ resourceType: "video",
282
+ resourceId: video.id
283
+ })) {
284
+ return;
285
+ }
250
286
  const wasLiked = currentVideo.isLiked;
251
287
  toggleLike(video.id);
252
288
  onLikeToggle?.(!wasLiked, video.id);
253
- }, [currentVideo.isLiked, video.id, toggleLike, onLikeToggle]);
289
+ }, [currentVideo.isLiked, video.id, toggleLike, onLikeToggle, handleGuestAction]);
254
290
  const handleOpenComments = useCallback(() => {
255
291
  onOpenComments?.(video.id);
256
292
  }, [onOpenComments, video.id]);
@@ -266,8 +302,14 @@ function ActionBar({
266
302
  [handleToggleLike, handleOpenComments, handleShare]
267
303
  );
268
304
  const handleBookmarkToggle = useCallback(() => {
305
+ if (handleGuestAction("bookmark", {
306
+ resourceType: "video",
307
+ resourceId: video.id
308
+ })) {
309
+ return;
310
+ }
269
311
  onBookmarkToggle?.(!isBookmarked, video.id);
270
- }, [onBookmarkToggle, isBookmarked, video.id]);
312
+ }, [onBookmarkToggle, isBookmarked, video.id, handleGuestAction]);
271
313
  return /* @__PURE__ */ jsxs(
272
314
  ActionBarHeadless,
273
315
  {
@@ -388,7 +430,11 @@ var enMessages = {
388
430
  "aria.addMedia": "Add media",
389
431
  "aria.submitComment": "Submit comment",
390
432
  "aria.openEmoji": "Open emoji",
391
- "aria.cancelReply": "Cancel reply"
433
+ "aria.cancelReply": "Cancel reply",
434
+ // ═══════════════════════════════════════════════════════════════════════════
435
+ // Guest Mode
436
+ // ═══════════════════════════════════════════════════════════════════════════
437
+ "guest.loginToComment": "Log in to comment"
392
438
  };
393
439
 
394
440
  // src/localization/messages/vi.ts
@@ -482,7 +528,11 @@ var viMessages = {
482
528
  "aria.addMedia": "Th\xEAm \u1EA3nh",
483
529
  "aria.submitComment": "G\u1EEDi b\xECnh lu\u1EADn",
484
530
  "aria.openEmoji": "M\u1EDF emoji",
485
- "aria.cancelReply": "H\u1EE7y tr\u1EA3 l\u1EDDi"
531
+ "aria.cancelReply": "H\u1EE7y tr\u1EA3 l\u1EDDi",
532
+ // ═══════════════════════════════════════════════════════════════════════════
533
+ // Guest Mode
534
+ // ═══════════════════════════════════════════════════════════════════════════
535
+ "guest.loginToComment": "\u0110\u0103ng nh\u1EADp \u0111\u1EC3 b\xECnh lu\u1EADn"
486
536
  };
487
537
 
488
538
  // src/localization/messages/index.ts
@@ -795,7 +845,15 @@ function AuthorInfoRoot({
795
845
  isFollowPending
796
846
  };
797
847
  }, [overrideState, currentVideo.author, currentVideo.isFollowing, isFollowPending]);
848
+ const { handleGuestAction } = useGuestMode();
798
849
  const handleToggleFollow = useCallback(async () => {
850
+ if (handleGuestAction("follow", {
851
+ resourceType: "author",
852
+ resourceId: currentVideo.author.id,
853
+ metadata: { authorId: currentVideo.author.id }
854
+ })) {
855
+ return;
856
+ }
799
857
  const wasFollowing = currentVideo.isFollowing;
800
858
  try {
801
859
  const success = await toggleFollow(video.id);
@@ -804,7 +862,14 @@ function AuthorInfoRoot({
804
862
  }
805
863
  } catch {
806
864
  }
807
- }, [currentVideo.isFollowing, currentVideo.author.id, video.id, toggleFollow, onFollowToggle]);
865
+ }, [
866
+ currentVideo.isFollowing,
867
+ currentVideo.author.id,
868
+ video.id,
869
+ toggleFollow,
870
+ onFollowToggle,
871
+ handleGuestAction
872
+ ]);
808
873
  const handleOpenProfile = useCallback(() => {
809
874
  onOpenProfile?.(currentVideo.author);
810
875
  }, [onOpenProfile, currentVideo.author]);
@@ -1148,6 +1213,44 @@ function TranslatedCommentList(props) {
1148
1213
  }
1149
1214
  function TranslatedCommentInput(props) {
1150
1215
  const i18n = useOptionalTranslation();
1216
+ const { isGuest, handleGuestAction } = useGuestMode();
1217
+ const handleGuestClick = useCallback(() => {
1218
+ handleGuestAction("comment", {
1219
+ resourceType: "comment",
1220
+ resourceId: "guest-intent"
1221
+ // Fallback ID since we don't have videoId here
1222
+ });
1223
+ }, [handleGuestAction]);
1224
+ if (isGuest) {
1225
+ return /* @__PURE__ */ jsx(
1226
+ "div",
1227
+ {
1228
+ className: "sv-comment-input-guest",
1229
+ onClick: handleGuestClick,
1230
+ onKeyDown: (e) => {
1231
+ if (e.key === "Enter" || e.key === " ") {
1232
+ handleGuestClick();
1233
+ }
1234
+ },
1235
+ role: "button",
1236
+ tabIndex: 0,
1237
+ style: {
1238
+ padding: "16px",
1239
+ borderTop: "1px solid rgba(0,0,0,0.1)",
1240
+ display: "flex",
1241
+ alignItems: "center",
1242
+ justifyContent: "center",
1243
+ cursor: "pointer",
1244
+ background: "var(--sv-bg-surface, #fff)",
1245
+ color: "var(--sv-color-primary, #fe2c55)",
1246
+ fontWeight: 600,
1247
+ fontSize: "14px",
1248
+ width: "100%"
1249
+ },
1250
+ children: i18n?.t("guest.loginToComment") ?? "Log in to comment"
1251
+ }
1252
+ );
1253
+ }
1151
1254
  return /* @__PURE__ */ jsx(
1152
1255
  CommentInput,
1153
1256
  {
@@ -3470,6 +3573,10 @@ function createSDK(config) {
3470
3573
  posterLoader,
3471
3574
  comment
3472
3575
  },
3576
+ guest: {
3577
+ isGuest: config?.guest?.mode === true,
3578
+ config: config?.guest
3579
+ },
3473
3580
  destroy
3474
3581
  };
3475
3582
  }
@@ -3492,6 +3599,11 @@ function destroySDK() {
3492
3599
  sdkInstance = null;
3493
3600
  }
3494
3601
  }
3602
+ async function prefetchFeed(config, options) {
3603
+ const debug = config.debug ?? false;
3604
+ const { dataSource } = resolveAdapters(config, debug);
3605
+ await FeedManager.prefetch(dataSource, options);
3606
+ }
3495
3607
  function ShortVideoProvider({
3496
3608
  children,
3497
3609
  config,
@@ -3998,4 +4110,4 @@ function ShortVideoRoot({
3998
4110
  }
3999
4111
  ShortVideoRoot.displayName = "ShortVideoRoot";
4000
4112
 
4001
- export { ActionBar, AuthorInfo, CommentSheet, DEFAULT_LOCALE, DefaultSlot, LocalizationAdapter, LocalizationContext, LocalizationProvider, ProgressBar, SDKPlayerError, SUPPORTED_LOCALES, ShortVideoProvider, ShortVideoRoot, VideoFeed, VideoInfo, VideoPlayer, VideoSlot, createSDK, createSimpleWireConfig, createWiredComponent, destroySDK, enMessages, getMessages, getSDK, isLocaleSupported, messageCatalogs, parseMessage, resetCommentManager, useComment, useFeed, useFeedSelector, useLifecycle, useLifecycleSelector, useLocalization, useOptimistic, useOptimisticSelector, useOptionalLocalization, useOptionalTranslation, usePlayer, usePlayerForVideo, usePlayerSelector, useResource, useResourceAllocation, useResourceSelector, useSDK, useSwipeGesture, useTranslation, viMessages };
4113
+ export { ActionBar, AuthorInfo, CommentSheet, DEFAULT_LOCALE, DefaultSlot, LocalizationAdapter, LocalizationContext, LocalizationProvider, ProgressBar, SDKPlayerError, SUPPORTED_LOCALES, ShortVideoProvider, ShortVideoRoot, VideoFeed, VideoInfo, VideoPlayer, VideoSlot, createSDK, createSimpleWireConfig, createWiredComponent, destroySDK, enMessages, getMessages, getSDK, isLocaleSupported, messageCatalogs, parseMessage, prefetchFeed, resetCommentManager, useComment, useFeed, useFeedSelector, useGuestMode, useLifecycle, useLifecycleSelector, useLocalization, useOptimistic, useOptimisticSelector, useOptionalLocalization, useOptionalTranslation, usePlayer, usePlayerForVideo, usePlayerSelector, useResource, useResourceAllocation, useResourceSelector, useSDK, useSwipeGesture, useTranslation, viMessages };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@xhub-short/sdk",
3
3
  "sideEffects": false,
4
- "version": "0.1.0-beta.3",
4
+ "version": "0.1.0-beta.5",
5
5
  "type": "module",
6
6
  "publishConfig": {
7
7
  "access": "public"
@@ -20,13 +20,13 @@
20
20
  "dist"
21
21
  ],
22
22
  "dependencies": {
23
- "@xhub-short/adapters": "0.1.0-beta.3",
24
- "@xhub-short/contracts": "0.1.0-beta.3",
25
- "@xhub-short/ui": "0.1.0-beta.3",
26
- "@xhub-short/core": "0.1.0-beta.3"
23
+ "@xhub-short/contracts": "0.1.0-beta.5",
24
+ "@xhub-short/adapters": "0.1.0-beta.5",
25
+ "@xhub-short/core": "0.1.0-beta.5",
26
+ "@xhub-short/ui": "0.1.0-beta.5"
27
27
  },
28
28
  "optionalDependencies": {
29
- "@xhub-short/bridge": "0.0.1-beta.3"
29
+ "@xhub-short/bridge": "0.0.1-beta.5"
30
30
  },
31
31
  "peerDependencies": {
32
32
  "react": "^19.0.0",
@@ -42,8 +42,8 @@
42
42
  "tsup": "^8.3.0",
43
43
  "typescript": "^5.7.0",
44
44
  "vitest": "^2.1.0",
45
- "@xhub-short/tsconfig": "0.0.0",
46
- "@xhub-short/vitest-config": "0.0.1-beta.2"
45
+ "@xhub-short/vitest-config": "0.0.1-beta.4",
46
+ "@xhub-short/tsconfig": "0.0.0"
47
47
  },
48
48
  "scripts": {
49
49
  "build": "tsup",