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

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
@@ -257,9 +257,24 @@ SDK đảm bảo hoạt động với Server-Side Rendering:
257
257
  ├── @xhub-short/contracts (types, interfaces)
258
258
  ├── @xhub-short/core (domain logic)
259
259
  ├── @xhub-short/adapters (mock + preset adapters)
260
- └── react (peer dependency)
260
+ ├── @xhub-short/ui (headless components)
261
+ ├── react (peer dependency)
262
+ └── zustand (peer dependency)
261
263
  ```
262
264
 
265
+ ### Host App Installation
266
+
267
+ ```bash
268
+ npm install @xhub-short/sdk
269
+ ```
270
+
271
+ **That's it!** No other dependencies needed.
272
+
273
+ **Bundled internally:**
274
+ - `zustand` - state management (bundled in @xhub-short/core)
275
+ - `clsx` - class names utility (bundled in @xhub-short/ui)
276
+ - Custom `useTouchDrag` hook - gesture handling (bundled in @xhub-short/sdk)
277
+
263
278
  ---
264
279
 
265
280
  ## ✨ Chức năng chính
package/dist/index.d.ts CHANGED
@@ -1,10 +1,10 @@
1
1
  import * as react from 'react';
2
- import { ComponentType, ReactNode, CSSProperties, ReactElement, SyntheticEvent } from 'react';
3
- import { ActionBarHeadlessProps, VideoItem, UIInteractionState, AuthorInfoHeadlessProps, UIAuthorState, UIAuthorActions, Author, ProgressBarHeadlessProps, UIFeedState, UISwipeState, VideoInfoProps, VideoSlotProps, IDataSource, IInteraction, ISessionStorage, IAnalytics, ILogger, INetworkAdapter, IVideoLoader, IPosterLoader } from '@xhub-short/contracts';
4
- export { ActionBarHeadlessProps, ActionBarProps, ActionButtonHeadlessProps, AnalyticsEvent, AnalyticsEventType, Author, AuthorInfoHeadlessProps, AuthorInfoProps, ErrorBoundaryProps, FeedResponse, IAnalytics, IDataSource, IInteraction, ILogger, INetworkAdapter, IPosterLoader, ISessionStorage, IStorage, IVideoLoader, LogEntry, LogLevel, SessionSnapshot, SkeletonProps, UIAuthorActions, UIAuthorState, UIFeedState, UIInteractionActions, UIInteractionState, UIPlayerControls, UIPlayerState, UIResourceState, UISwipeState, UIVideoInfoActions, UIVideoInfoState, VideoFeedHeadlessProps, VideoInfoHeadlessProps, VideoInfoProps, VideoItem, VideoPlayerHeadlessProps, VideoSlotHeadlessProps, VideoSlotProps, VideoSource, VideoStats } from '@xhub-short/contracts';
2
+ import { ComponentType, ReactNode, ReactElement, CSSProperties, SyntheticEvent } from 'react';
3
+ import { ActionBarHeadlessProps, VideoItem, UIInteractionState, AuthorInfoHeadlessProps, UIAuthorState, UIAuthorActions, Author, CommentAuthor, CommentConfig, ProgressBarHeadlessProps, UIFeedState, UISwipeState, VideoInfoProps, VideoSlotProps, IDataSource, IInteraction, ICommentAdapter, ISessionStorage, IAnalytics, ILogger, INetworkAdapter, IVideoLoader, IPosterLoader, LocalizationConfig, UICommentState, UICommentActions, ILocalization, MessageKey, MessageValues, MessageCatalog } from '@xhub-short/contracts';
4
+ export { ActionBarHeadlessProps, ActionBarProps, ActionButtonHeadlessProps, AnalyticsEvent, AnalyticsEventType, Author, AuthorInfoHeadlessProps, AuthorInfoProps, CommentAuthor, CommentConfig, CommentItem, ErrorBoundaryProps, FeedResponse, IAnalytics, ICommentAdapter, IDataSource, IInteraction, ILocalization, ILogger, INetworkAdapter, IPosterLoader, ISessionStorage, IStorage, IVideoLoader, LocalizationConfig, LogEntry, LogLevel, MessageCatalog, MessageKey, MessageValue, MessageValues, PartialMessageCatalog, ReplyItem, SessionSnapshot, SkeletonProps, UIAuthorActions, UIAuthorState, UICommentActions, UICommentState, UIFeedState, UIInteractionActions, UIInteractionState, UIPlayerControls, UIPlayerState, UIResourceState, UISwipeState, UIVideoInfoActions, UIVideoInfoState, VideoFeedHeadlessProps, VideoInfoHeadlessProps, VideoInfoProps, VideoItem, VideoPlayerHeadlessProps, VideoSlotHeadlessProps, VideoSlotProps, VideoSource, VideoStats } from '@xhub-short/contracts';
5
5
  import * as react_jsx_runtime from 'react/jsx-runtime';
6
- import { AuthorAvatar, AuthorName, AuthorDescription, FollowButton, VideoAuthorName, VideoCaption, VideoHashtags, VideoLocation, VideoMusic, VideoPlayerHeadlessExtendedProps, ErrorMode, ErrorBoundaryProps } from '@xhub-short/ui';
7
- import { useDrag } from '@use-gesture/react';
6
+ import { AuthorAvatar, AuthorName, AuthorDescription, FollowButtonProps, SheetHeaderProps, CommentListProps, CommentInputProps, VideoAuthorName, VideoCaption, VideoHashtags, VideoLocation, VideoMusic, VideoPlayerHeadlessExtendedProps, ErrorMode, ErrorBoundaryProps } from '@xhub-short/ui';
7
+ export { CommentInputProps, CommentListProps, SheetHeaderProps } from '@xhub-short/ui';
8
8
  import { PlayerError, FeedConfig, PlayerConfig, ResourceConfig, LifecycleConfig, OptimisticConfig, RestoreResult, FeedError, FeedState, PlayerStatus, PlayerState, NetworkType, AllocationResult, PrefetchConfig, ResourceState, PendingAction, ActionType, OptimisticState, FeedManager, PlayerEngine, ResourceGovernor, LifecycleManager, OptimisticManager, LifecycleState } from '@xhub-short/core';
9
9
  export { ActionType, AllocationResult, FeedConfig, FeedError, FeedState, LifecycleConfig, LifecycleState, NetworkType, OptimisticConfig, OptimisticState, PendingAction, PlayerConfig, PlayerError, PlayerState, PlayerStatus, PrefetchConfig, ResourceConfig, ResourceState, RestoreResult } from '@xhub-short/core';
10
10
  import { BrowserAdaptersConfig } from '@xhub-short/adapters';
@@ -288,6 +288,10 @@ declare function AuthorInfoContent({ className, children, }: {
288
288
  className?: string;
289
289
  children?: ReactNode;
290
290
  }): react_jsx_runtime.JSX.Element;
291
+ /**
292
+ * Translated FollowButton - auto-injects i18n strings
293
+ */
294
+ declare function TranslatedFollowButton(props: FollowButtonProps): React.ReactElement;
291
295
  /**
292
296
  * AuthorInfo with compound sub-components
293
297
  *
@@ -308,12 +312,84 @@ declare const AuthorInfo: typeof AuthorInfoRoot & {
308
312
  Name: typeof AuthorName;
309
313
  /** Description/bio sub-component */
310
314
  Description: typeof AuthorDescription;
311
- /** Follow button sub-component */
312
- FollowButton: typeof FollowButton;
315
+ /** Follow button sub-component (auto-translated) */
316
+ FollowButton: typeof TranslatedFollowButton;
313
317
  /** Content wrapper for name + description */
314
318
  Content: typeof AuthorInfoContent;
315
319
  };
316
320
 
321
+ /**
322
+ * CommentSheet - Wired SDK component
323
+ *
324
+ * TikTok-style bottom sheet for comments with SDK integration.
325
+ *
326
+ * @example Basic usage
327
+ * ```tsx
328
+ * <CommentSheet
329
+ * videoId={currentVideoId}
330
+ * isOpen={showComments}
331
+ * onClose={() => setShowComments(false)}
332
+ * />
333
+ * ```
334
+ *
335
+ * @example Custom composition
336
+ * ```tsx
337
+ * <CommentSheet videoId={videoId} isOpen={isOpen} onClose={onClose}>
338
+ * <CommentSheet.Header titleLabel="Bình luận" />
339
+ * <CommentSheet.List />
340
+ * <CommentSheet.Input placeholder="Aa..." />
341
+ * </CommentSheet>
342
+ * ```
343
+ */
344
+
345
+ interface CommentSheetProps {
346
+ /** Video ID to show comments for */
347
+ videoId: string;
348
+ /** Whether sheet is open */
349
+ isOpen: boolean;
350
+ /** Close callback */
351
+ onClose: () => void;
352
+ /** Current user info (required for optimistic UI when posting) */
353
+ currentUser?: CommentAuthor;
354
+ /** Config overrides */
355
+ config?: Partial<CommentConfig>;
356
+ /** Initial count from video data (displayed before API loads) */
357
+ initialCount?: number;
358
+ /** Auto load comments when opened */
359
+ autoLoad?: boolean;
360
+ /** Custom children for compound pattern */
361
+ children?: ReactNode;
362
+ /** Root class name */
363
+ className?: string;
364
+ /** Backdrop class name */
365
+ backdropClassName?: string;
366
+ /** Close on backdrop click (default: true) */
367
+ closeOnBackdropClick?: boolean;
368
+ /** Close on escape key (default: true) */
369
+ closeOnEscape?: boolean;
370
+ }
371
+ declare function CommentSheetInner({ videoId, isOpen, onClose, currentUser, config, initialCount, autoLoad, children, className, backdropClassName, closeOnBackdropClick, closeOnEscape, }: CommentSheetProps): ReactElement;
372
+ /**
373
+ * Translated SheetHeader - auto-injects i18n strings
374
+ */
375
+ declare function TranslatedSheetHeader(props: SheetHeaderProps): ReactElement;
376
+ /**
377
+ * Translated CommentList - auto-injects i18n strings
378
+ */
379
+ declare function TranslatedCommentList(props: CommentListProps): ReactElement;
380
+ /**
381
+ * Translated CommentInput - auto-injects i18n strings
382
+ */
383
+ declare function TranslatedCommentInput(props: CommentInputProps): ReactElement;
384
+ declare const CommentSheet: typeof CommentSheetInner & {
385
+ /** Sheet header with title and close button (auto-translated) */
386
+ Header: typeof TranslatedSheetHeader;
387
+ /** Scrollable comment list with infinite loading (auto-translated) */
388
+ List: typeof TranslatedCommentList;
389
+ /** Input area with emoji bar and submit (auto-translated) */
390
+ Input: typeof TranslatedCommentInput;
391
+ };
392
+
317
393
  /**
318
394
  * Wired ProgressBar Component (P11)
319
395
  *
@@ -382,6 +458,17 @@ interface ProgressBarProps extends Omit<ProgressBarHeadlessProps, 'currentTime'
382
458
  * @default false
383
459
  */
384
460
  minimal?: boolean;
461
+ /**
462
+ * Auto-hide progress bar when video is playing
463
+ *
464
+ * When enabled:
465
+ * - Hidden when video is playing
466
+ * - Visible when video is paused
467
+ * - Visible when user hovers (via CSS)
468
+ *
469
+ * @default true
470
+ */
471
+ autoHide?: boolean;
385
472
  /**
386
473
  * Additional CSS class
387
474
  */
@@ -393,16 +480,24 @@ interface ProgressBarProps extends Omit<ProgressBarHeadlessProps, 'currentTime'
393
480
  * Connects to PlayerEngine for automatic state updates.
394
481
  * Uses Direct DOM Update for 60fps smooth progress animation.
395
482
  */
396
- declare function ProgressBar({ seekable, showTime, showTooltip, minimal, className, onSeekStart, onSeekEnd, }: ProgressBarProps): React.ReactElement | null;
483
+ declare function ProgressBar({ seekable, showTime, showTooltip, minimal, autoHide, className, onSeekStart, onSeekEnd, }: ProgressBarProps): React.ReactElement | null;
397
484
  declare namespace ProgressBar {
398
485
  var displayName: string;
399
486
  }
400
487
 
488
+ interface DragBind {
489
+ onPointerDown?: (e: React.PointerEvent) => void;
490
+ onTouchStart?: (e: React.TouchEvent) => void;
491
+ style?: {
492
+ touchAction: string;
493
+ };
494
+ }
495
+
401
496
  /**
402
497
  * Swipe Gesture Hook
403
498
  *
404
499
  * Headless hook for vertical swipe gestures in video feeds.
405
- * Wraps @use-gesture/react with direction locking and velocity-based snap.
500
+ * Uses custom lightweight touch handler (~1KB instead of @use-gesture/react ~20KB).
406
501
  *
407
502
  * Features:
408
503
  * - Touch and mouse support
@@ -506,7 +601,7 @@ interface UseSwipeGestureReturn {
506
601
  * return <div {...bind()}>...</div>;
507
602
  * ```
508
603
  */
509
- bind: ReturnType<typeof useDrag>;
604
+ bind: () => DragBind;
510
605
  /**
511
606
  * Get current swipe state (ref-based, no re-render).
512
607
  * Use this for reading state during animations or imperative code.
@@ -543,6 +638,11 @@ interface UseSwipeGestureReturn {
543
638
  * ```
544
639
  */
545
640
  dragOffsetRef: React.RefObject<number>;
641
+ /**
642
+ * Ref indicating if current index change is from restore (vs user swipe).
643
+ * Use this to skip animations when restoring session.
644
+ */
645
+ isRestoreTransitionRef: React.RefObject<boolean>;
546
646
  }
547
647
  /**
548
648
  * Headless hook for vertical swipe gestures
@@ -750,7 +850,7 @@ interface VideoFeedProps {
750
850
  * React re-renders. The `dragOffset` in swipeState is always 0 because
751
851
  * real-time offset is stored in a ref and applied directly to DOM elements.
752
852
  */
753
- declare function VideoFeed({ height, className, renderSlot, onIndexChange, onEndReached, endReachedThreshold, bufferSize, loadingText, emptyText, endText, autoLoad, autoLoadMore, swipeThreshold, velocityThreshold, snapDuration, onSwipe, feedState: feedStateProp, swipeState: swipeStateProp, containerStyle, }: VideoFeedProps): React.ReactElement;
853
+ declare function VideoFeed({ height, className, renderSlot, onIndexChange, onEndReached, endReachedThreshold, bufferSize, loadingText: loadingTextProp, emptyText: emptyTextProp, endText: endTextProp, autoLoad, autoLoadMore, swipeThreshold, velocityThreshold, snapDuration, onSwipe, feedState: feedStateProp, swipeState: swipeStateProp, containerStyle, }: VideoFeedProps): React.ReactElement;
754
854
  declare namespace VideoFeed {
755
855
  var displayName: string;
756
856
  }
@@ -847,11 +947,17 @@ declare const VideoInfo: typeof VideoInfoRoot & {
847
947
  *
848
948
  * VideoPlayer (Wired) -> VideoPlayerHeadless (UI)
849
949
  *
850
- * - Auto-connects to PlayerEngine via usePlayer()
950
+ * - Auto-connects to PlayerEngine via usePlayerCore() (optimized)
851
951
  * - Auto-loads video when video prop changes
852
952
  * - Reports playback events back to PlayerEngine
853
953
  * - Can detect VideoSlot context for embedded use
854
954
  *
955
+ * ## Re-render Optimization
956
+ *
957
+ * Uses `usePlayerCore()` instead of `usePlayer()` to avoid re-renders
958
+ * during playback. This hook excludes time-based state (currentTime,
959
+ * duration, buffered, watchTime) which update ~4 times per second.
960
+ *
855
961
  * ## Important: Standalone vs Isolated
856
962
  *
857
963
  * **Standalone mode does NOT mean isolated player.**
@@ -1065,6 +1171,10 @@ interface DefaultSlotProps {
1065
1171
  index: number;
1066
1172
  /** Show poster before video plays (default: true) */
1067
1173
  showPoster?: boolean;
1174
+ /** Show play/pause indicator on tap (default: true) */
1175
+ showPlayIndicator?: boolean;
1176
+ /** Keep play icon visible while video is paused - YouTube style (default: true) */
1177
+ persistPlayIndicatorWhenPaused?: boolean;
1068
1178
  /** Show like animation on double-tap (default: true) */
1069
1179
  showLikeAnimation?: boolean;
1070
1180
  /** Show author info - avatar + follow badge (default: true) */
@@ -1081,6 +1191,8 @@ interface DefaultSlotProps {
1081
1191
  showTooltip?: boolean;
1082
1192
  /** Show bookmark button (default: false) */
1083
1193
  showBookmark?: boolean;
1194
+ /** Show comment sheet when comment button is clicked (default: true) */
1195
+ showCommentSheet?: boolean;
1084
1196
  /** Show debug info (default: false) */
1085
1197
  showDebug?: boolean;
1086
1198
  /** Called when comments button is clicked */
@@ -1107,8 +1219,14 @@ interface DefaultSlotProps {
1107
1219
  renderVideoInfo?: (props: VideoInfoWiredProps) => ReactNode;
1108
1220
  /** Custom ProgressBar renderer */
1109
1221
  renderProgressBar?: (props: ProgressBarProps) => ReactNode;
1222
+ /** Custom CommentSheet renderer */
1223
+ renderCommentSheet?: (props: CommentSheetProps) => ReactNode;
1110
1224
  /** Custom Error renderer */
1111
1225
  renderError?: (error: Error, retry: () => void) => ReactNode;
1226
+ /** Current user info for optimistic UI when posting comments */
1227
+ currentUser?: CommentAuthor;
1228
+ /** Comment configuration (pageSize, maxLength, etc.) */
1229
+ commentConfig?: Partial<CommentConfig>;
1112
1230
  /** Like animation style (default: 'float') */
1113
1231
  likeAnimationStyle?: 'float' | 'burst' | 'scale' | 'bounce';
1114
1232
  /** Like animation duration in ms (default: 1200) */
@@ -1139,6 +1257,8 @@ interface AdaptersConfig {
1139
1257
  dataSource?: IDataSource;
1140
1258
  /** Interaction adapter for like/follow/comment actions */
1141
1259
  interaction?: IInteraction;
1260
+ /** Comment adapter for comment operations (read/write/like) */
1261
+ comment?: ICommentAdapter;
1142
1262
  /** Storage adapter for session persistence */
1143
1263
  storage?: ISessionStorage;
1144
1264
  /** Analytics adapter for tracking events */
@@ -1232,6 +1352,67 @@ interface SDKConfig {
1232
1352
  * @see OptimisticConfig
1233
1353
  */
1234
1354
  optimistic?: Partial<OptimisticConfig>;
1355
+ /**
1356
+ * Comment feature configuration
1357
+ * @see CommentConfig
1358
+ */
1359
+ comment?: Partial<CommentConfig>;
1360
+ /**
1361
+ * Prefetch cache configuration for instant feed loading
1362
+ *
1363
+ * When enabled, SDK caches the last N videos from the feed.
1364
+ * On fresh load (reload/new tab), cached videos are shown instantly
1365
+ * while fresh data is fetched in the background.
1366
+ *
1367
+ * @example
1368
+ * ```tsx
1369
+ * <ShortVideoRoot
1370
+ * config={{
1371
+ * prefetchCache: {
1372
+ * enabled: true,
1373
+ * maxVideos: 15,
1374
+ * }
1375
+ * }}
1376
+ * />
1377
+ * ```
1378
+ */
1379
+ prefetchCache?: {
1380
+ /** Enable instant loading from cache (default: true) */
1381
+ enabled?: boolean;
1382
+ /** Number of videos to cache (default: 10) */
1383
+ maxVideos?: number;
1384
+ /**
1385
+ * Enable dynamic cache eviction (default: true)
1386
+ * When user scrolls past cached videos, remove them from cache
1387
+ * Prevents user from rewatching same videos on reload
1388
+ */
1389
+ enableDynamicEviction?: boolean;
1390
+ /**
1391
+ * Throttle duration (ms) for dynamic eviction (default: 2000)
1392
+ * Reduces storage writes during fast scrolling
1393
+ */
1394
+ evictionThrottleMs?: number;
1395
+ };
1396
+ /**
1397
+ * Localization configuration
1398
+ *
1399
+ * Configure locale and custom messages for i18n support.
1400
+ *
1401
+ * @example
1402
+ * ```tsx
1403
+ * <ShortVideoProvider config={{
1404
+ * localization: {
1405
+ * locale: 'vi',
1406
+ * messages: {
1407
+ * 'feed.empty': 'Hiện chưa có video nào',
1408
+ * },
1409
+ * },
1410
+ * }}>
1411
+ * <App />
1412
+ * </ShortVideoProvider>
1413
+ * ```
1414
+ */
1415
+ localization?: LocalizationConfig;
1235
1416
  /**
1236
1417
  * Enable debug mode
1237
1418
  * When true, enables verbose logging
@@ -1932,6 +2113,8 @@ interface SDKInstance {
1932
2113
  network: INetworkAdapter;
1933
2114
  videoLoader: IVideoLoader;
1934
2115
  posterLoader: IPosterLoader;
2116
+ /** Comment adapter (optional - only if comment feature is enabled) */
2117
+ comment?: ICommentAdapter;
1935
2118
  };
1936
2119
  /** Destroy all managers and cleanup resources */
1937
2120
  destroy: () => void;
@@ -2051,6 +2234,12 @@ interface UseLifecycleOptions {
2051
2234
  * - Session restore on mount
2052
2235
  * - State tracking during usage
2053
2236
  * - Session save on unmount/visibility hidden
2237
+ *
2238
+ * ## Session-Only Restore
2239
+ *
2240
+ * By default, restore only happens when user navigates within the app
2241
+ * (e.g., going to another page and coming back). Fresh loads (reload,
2242
+ * new tab, direct URL) will NOT restore to prevent stale data issues.
2054
2243
  */
2055
2244
  declare function useLifecycle(options?: UseLifecycleOptions): UseLifecycleReturn;
2056
2245
  /**
@@ -2064,4 +2253,271 @@ declare function useLifecycle(options?: UseLifecycleOptions): UseLifecycleReturn
2064
2253
  */
2065
2254
  declare function useLifecycleSelector<T>(selector: (state: LifecycleState) => T): T;
2066
2255
 
2067
- export { ActionBar, type ActionBarIconSet, type ActionBarProps as ActionBarWiredProps, type AdaptersConfig, AuthorInfo, type AuthorInfoProps as AuthorInfoWiredProps, DefaultSlot, type DefaultSlotProps, type HookReturn, ProgressBar, type ProgressBarProps, type SDKConfig, type SDKInstance, SDKPlayerError, ShortVideoProvider, type ShortVideoProviderProps, ShortVideoRoot, type ShortVideoRootProps, type SwipeConfig, type SwipeDirection, type SwipeState, type UseFeedReturn, type UseLifecycleOptions, type UseLifecycleReturn, type UseOptimisticReturn, type UsePlayerForVideoReturn, type UsePlayerReturn, type UseResourceAllocationReturn, type UseResourceReturn, type UseSwipeGestureReturn, type VideoElementHandlers, VideoFeed, type VideoFeedProps, VideoInfo, type VideoInfoWiredProps, VideoPlayer, type VideoPlayerProps, VideoSlot, type VideoSlotWiredProps, type WireConfig, createSDK, createSimpleWireConfig, createWiredComponent, destroySDK, getSDK, useFeed, useFeedSelector, useLifecycle, useLifecycleSelector, useOptimistic, useOptimisticSelector, usePlayer, usePlayerForVideo, usePlayerSelector, useResource, useResourceAllocation, useResourceSelector, useSDK, useSwipeGesture };
2256
+ /**
2257
+ * useComment Hook - SDK integration for Comment feature
2258
+ *
2259
+ * Provides comment state and actions for a specific video.
2260
+ * Uses CommentManager from @xhub-short/core with Zustand store.
2261
+ *
2262
+ * @example
2263
+ * ```tsx
2264
+ * function CommentSheet({ videoId }) {
2265
+ * const { state, actions, isReady } = useComment({ videoId, autoLoad: true });
2266
+ *
2267
+ * if (!isReady) return null;
2268
+ *
2269
+ * return (
2270
+ * <>
2271
+ * {state.isLoading ? <Spinner /> : null}
2272
+ * {state.comments.map(c => <Comment key={c.id} {...c} />)}
2273
+ * </>
2274
+ * );
2275
+ * }
2276
+ * ```
2277
+ */
2278
+
2279
+ interface UseCommentOptions {
2280
+ /** Video ID to load comments for */
2281
+ videoId: string;
2282
+ /** Auto load comments when hook mounts (default: false) */
2283
+ autoLoad?: boolean;
2284
+ /** Current user info (required for posting) */
2285
+ currentUser?: CommentAuthor;
2286
+ /** Config overrides */
2287
+ config?: Partial<CommentConfig>;
2288
+ }
2289
+ interface UseCommentReturn {
2290
+ /** Comment state */
2291
+ state: UICommentState;
2292
+ /** Comment actions */
2293
+ actions: UICommentActions;
2294
+ /** Whether hook is ready (adapter configured) */
2295
+ isReady: boolean;
2296
+ }
2297
+ declare function resetCommentManager(): void;
2298
+ declare function useComment(options: UseCommentOptions): UseCommentReturn;
2299
+
2300
+ /**
2301
+ * Localization Context
2302
+ *
2303
+ * Holds the ILocalization instance for the SDK.
2304
+ */
2305
+ declare const LocalizationContext: react.Context<ILocalization | null>;
2306
+ interface LocalizationProviderProps {
2307
+ /**
2308
+ * Localization configuration
2309
+ */
2310
+ config?: LocalizationConfig;
2311
+ /**
2312
+ * Children components
2313
+ */
2314
+ children: ReactNode;
2315
+ }
2316
+ /**
2317
+ * Localization Provider
2318
+ *
2319
+ * Wraps SDK components with i18n support.
2320
+ *
2321
+ * @example
2322
+ * <LocalizationProvider config={{ locale: 'vi' }}>
2323
+ * <VideoFeed />
2324
+ * </LocalizationProvider>
2325
+ */
2326
+ declare function LocalizationProvider({ config, children, }: LocalizationProviderProps): React.ReactElement;
2327
+ /**
2328
+ * Get localization instance from context
2329
+ *
2330
+ * @throws Error if used outside LocalizationProvider
2331
+ */
2332
+ declare function useLocalization(): ILocalization;
2333
+ /**
2334
+ * Get localization instance (nullable)
2335
+ *
2336
+ * For components that may be used outside SDK context.
2337
+ */
2338
+ declare function useOptionalLocalization(): ILocalization | null;
2339
+
2340
+ /**
2341
+ * useTranslation Hook
2342
+ *
2343
+ * Main hook for accessing i18n functions in SDK components.
2344
+ */
2345
+
2346
+ /**
2347
+ * Translation function type
2348
+ */
2349
+ type TranslateFn = (key: MessageKey, values?: MessageValues) => string;
2350
+ /**
2351
+ * Return type of useTranslation hook
2352
+ */
2353
+ interface UseTranslationReturn {
2354
+ /** Current locale */
2355
+ locale: string;
2356
+ /** Translate function */
2357
+ t: TranslateFn;
2358
+ /** Format number with locale separators */
2359
+ formatNumber: (value: number) => string;
2360
+ /** Format compact number (1K, 1M, 1B) */
2361
+ formatCompact: (value: number) => string;
2362
+ /** Format relative time */
2363
+ formatRelativeTime: (date: Date | number) => string;
2364
+ }
2365
+ /**
2366
+ * Hook to access translation functions
2367
+ *
2368
+ * Must be used within ShortVideoProvider.
2369
+ *
2370
+ * @example
2371
+ * const { t, formatCompact } = useTranslation();
2372
+ *
2373
+ * // Simple translation
2374
+ * t('feed.loading') // "Đang tải..."
2375
+ *
2376
+ * // With interpolation
2377
+ * t('comment.replyTo', { name: 'John' }) // "Đang trả lời John"
2378
+ *
2379
+ * // Plural
2380
+ * t('comment.count', { count: 5 }) // "5 Bình luận"
2381
+ *
2382
+ * // Compact number
2383
+ * formatCompact(15000) // "15N" (Vietnamese) or "15K" (English)
2384
+ */
2385
+ declare function useTranslation(): UseTranslationReturn;
2386
+ /**
2387
+ * Hook to access translation functions (nullable)
2388
+ *
2389
+ * Returns null if used outside ShortVideoProvider.
2390
+ * Useful for components that may be used standalone.
2391
+ *
2392
+ * NOTE: This hook always runs all internal hooks unconditionally
2393
+ * to comply with Rules of Hooks. The null check happens at the end.
2394
+ */
2395
+ declare function useOptionalTranslation(): UseTranslationReturn | null;
2396
+
2397
+ /**
2398
+ * Default Localization Adapter
2399
+ *
2400
+ * Built-in implementation using lightweight ICU-like parser.
2401
+ * Zero external dependencies.
2402
+ */
2403
+
2404
+ /**
2405
+ * Default Localization Adapter
2406
+ *
2407
+ * Provides i18n support with:
2408
+ * - ICU-like message format (plural, select, interpolation)
2409
+ * - Compact number formatting (1K, 1M, 1B)
2410
+ * - Relative time formatting
2411
+ *
2412
+ * @example
2413
+ * const l10n = new LocalizationAdapter({ locale: 'vi' });
2414
+ * l10n.t('comment.count', { count: 5 }); // "5 Bình luận"
2415
+ * l10n.formatCompact(15000); // "15N"
2416
+ */
2417
+ declare class LocalizationAdapter implements ILocalization {
2418
+ readonly locale: string;
2419
+ private readonly messages;
2420
+ private readonly fallbackMessages;
2421
+ constructor(config?: LocalizationConfig);
2422
+ /**
2423
+ * Translate a message key with optional interpolation
2424
+ */
2425
+ t(key: MessageKey, values?: MessageValues): string;
2426
+ /**
2427
+ * Format number with locale-aware separators
2428
+ */
2429
+ formatNumber(value: number): string;
2430
+ /**
2431
+ * Format number in compact form (1K, 1M, 1B)
2432
+ */
2433
+ formatCompact(value: number): string;
2434
+ /**
2435
+ * Format relative time (e.g., "2 hours ago")
2436
+ */
2437
+ formatRelativeTime(date: Date | number): string;
2438
+ }
2439
+
2440
+ /**
2441
+ * Lightweight ICU-like Message Parser
2442
+ *
2443
+ * Custom implementation - NO external dependencies.
2444
+ * Bundle size: ~0.5KB gzipped
2445
+ *
2446
+ * Supported syntax:
2447
+ * - Simple interpolation: {name}
2448
+ * - Plural: {count, plural, =0 {none} =1 {one} one {# item} other {# items}}
2449
+ * - Select: {gender, select, male {He} female {She} other {They}}
2450
+ *
2451
+ * Note: This is a simplified parser that covers 95% of i18n use cases.
2452
+ * For full ICU compliance, use FormatJS.
2453
+ */
2454
+
2455
+ /**
2456
+ * Parse ICU-like message format
2457
+ *
2458
+ * @param message - Message template with ICU placeholders
2459
+ * @param values - Values to interpolate
2460
+ * @param locale - Locale for plural rules
2461
+ * @returns Formatted string
2462
+ *
2463
+ * @example
2464
+ * parseMessage("Hello {name}!", { name: "World" })
2465
+ * // "Hello World!"
2466
+ *
2467
+ * parseMessage("{count, plural, =0 {No items} one {# item} other {# items}}", { count: 5 })
2468
+ * // "5 items"
2469
+ *
2470
+ * parseMessage("{active, select, true {Active} other {Inactive}}", { active: true })
2471
+ * // "Active"
2472
+ */
2473
+ declare function parseMessage(message: string, values?: MessageValues, locale?: string): string;
2474
+
2475
+ /**
2476
+ * English Messages (Default)
2477
+ *
2478
+ * Uses ICU-like message format for pluralization and selection.
2479
+ */
2480
+
2481
+ declare const enMessages: MessageCatalog;
2482
+
2483
+ /**
2484
+ * Vietnamese Messages
2485
+ *
2486
+ * Vietnamese doesn't have grammatical plural forms,
2487
+ * so ICU plural syntax always uses "other" category.
2488
+ */
2489
+
2490
+ declare const viMessages: MessageCatalog;
2491
+
2492
+ /**
2493
+ * Message Catalogs Index
2494
+ *
2495
+ * Default messages for supported locales.
2496
+ * Host App can override any message via config.
2497
+ */
2498
+
2499
+ /**
2500
+ * All supported locales
2501
+ */
2502
+ declare const SUPPORTED_LOCALES: readonly ["en", "vi"];
2503
+ type SupportedLocale = (typeof SUPPORTED_LOCALES)[number];
2504
+ /**
2505
+ * Default locale
2506
+ */
2507
+ declare const DEFAULT_LOCALE: SupportedLocale;
2508
+ /**
2509
+ * Message catalogs by locale
2510
+ */
2511
+ declare const messageCatalogs: Record<SupportedLocale, MessageCatalog>;
2512
+ /**
2513
+ * Get messages for a locale
2514
+ *
2515
+ * Falls back to English if locale not supported
2516
+ */
2517
+ declare function getMessages(locale: string): MessageCatalog;
2518
+ /**
2519
+ * Check if locale is supported
2520
+ */
2521
+ declare function isLocaleSupported(locale: string): locale is SupportedLocale;
2522
+
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 };