@xhub-short/sdk 0.1.0-beta.9 → 1.0.0-beta.19

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.
Files changed (3) hide show
  1. package/dist/index.d.ts +1402 -163
  2. package/dist/index.js +4071 -1409
  3. package/package.json +9 -8
package/dist/index.d.ts CHANGED
@@ -1,14 +1,14 @@
1
1
  import * as react from 'react';
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';
2
+ import react__default, { ComponentType, ReactNode, ReactElement, CSSProperties, SyntheticEvent } from 'react';
3
+ import { ActionBarHeadlessProps, ContentItem, VideoItem, UIInteractionState, AuthorInfoHeadlessProps, UIAuthorState, UIAuthorActions, Author, CommentConfig, ProgressBarHeadlessProps, Article, UIFeedState, UISwipeState, VideoInfoProps as VideoInfoProps$1, VideoSlotProps, MusicInfo, ContentStats, IDataSource, IPlaylistDataSource, IInteraction, ICommentAdapter, ISessionStorage, IAnalytics, ILogger, INetworkAdapter, IVideoLoader, IPosterLoader, LocalizationConfig, UICommentState, UICommentActions, ILocalization, MessageKey, MessageValues, MessageCatalog, CommentAuthor, VideoQuality, ReportReason, PlaylistData } from '@xhub-short/contracts';
4
+ export { ActionBarHeadlessProps, ActionBarProps, ActionButtonHeadlessProps, AnalyticsEvent, AnalyticsEventType, Article, ArticleSlotHeadlessProps, ArticleStats, Author, AuthorInfoHeadlessProps, AuthorInfoProps, CommentAuthor, CommentConfig, CommentItem, ErrorBoundaryProps, FeedResponse, IAnalytics, ICommentAdapter, IDataSource, IInteraction, ILocalization, ILogger, INetworkAdapter, IPosterLoader, ISessionStorage, IStorage, IVideoLoader, ImagePostSlotHeadlessProps, 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 } from '@xhub-short/contracts';
5
5
  import * as react_jsx_runtime from 'react/jsx-runtime';
6
- import { AuthorAvatar, AuthorName, AuthorDescription, FollowButtonProps, SheetHeaderProps, CommentListProps, CommentInputProps, VideoAuthorName, VideoCaption, VideoHashtags, VideoLocation, VideoMusic, VideoPlayerHeadlessExtendedProps, ErrorMode, ErrorBoundaryProps } from '@xhub-short/ui';
6
+ import { AuthorAvatar, AuthorName, AuthorDescription, FollowButtonProps, SheetHeaderProps, CommentListProps, CommentInputProps, VideoAuthorName, VideoCaption, VideoHashtags, VideoLocation, VideoMusic, VideoPlayerHeadlessExtendedProps, ArticleSlotHeadlessProps, ErrorMode, ErrorBoundaryProps } from '@xhub-short/ui';
7
7
  export { CommentInputProps, CommentListProps, SheetHeaderProps } from '@xhub-short/ui';
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';
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, PlaylistManager, PlaylistCollectionManager, 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';
11
- export { BrowserAdaptersConfig } from '@xhub-short/adapters';
11
+ export { BatchAnalyticsConfig, BatchAnalyticsContext, BatchAnalyticsEventData, BatchAnalyticsEventTransformer, BrowserAdaptersConfig } from '@xhub-short/adapters';
12
12
 
13
13
  /**
14
14
  * HOC Factory for creating wired components
@@ -143,10 +143,14 @@ interface ActionBarIconSet {
143
143
  */
144
144
  interface ActionBarProps extends Omit<ActionBarHeadlessProps, 'interactionState' | 'interactionActions'> {
145
145
  /**
146
- * Video item to get interaction state for
147
- * Required - ActionBar needs video data for likes/comments/shares
146
+ * Content item (Video or Article) to get interaction state for
147
+ * Required - ActionBar needs data for likes/comments/shares
148
148
  */
149
- video: VideoItem;
149
+ content: ContentItem;
150
+ /**
151
+ * @deprecated Use 'content' instead. Will be removed in v3.0
152
+ */
153
+ video?: VideoItem;
150
154
  /**
151
155
  * Icon set for buttons
152
156
  * Host app provides these to customize appearance
@@ -166,11 +170,11 @@ interface ActionBarProps extends Omit<ActionBarHeadlessProps, 'interactionState'
166
170
  * Custom callback when sharing
167
171
  * Default: no-op (host app should implement share sheet)
168
172
  */
169
- onShare?: (video: VideoItem) => void | Promise<void>;
173
+ onShare?: (content: ContentItem) => void | Promise<void>;
170
174
  /**
171
175
  * Custom callback when like is toggled (in addition to SDK action)
172
176
  */
173
- onLikeToggle?: (isLiked: boolean, videoId: string) => void;
177
+ onLikeToggle?: (isLiked: boolean, contentId: string) => void;
174
178
  /**
175
179
  * Whether to show bookmark button (not auto-wired, host manages state)
176
180
  * @default false
@@ -183,7 +187,7 @@ interface ActionBarProps extends Omit<ActionBarHeadlessProps, 'interactionState'
183
187
  /**
184
188
  * Callback when bookmark is toggled
185
189
  */
186
- onBookmarkToggle?: (isBookmarked: boolean, videoId: string) => void;
190
+ onBookmarkToggle?: (isBookmarked: boolean, contentId: string) => void;
187
191
  /**
188
192
  * Layout direction
189
193
  * @default 'vertical'
@@ -209,7 +213,7 @@ interface ActionBarProps extends Omit<ActionBarHeadlessProps, 'interactionState'
209
213
  * Auto-connects Like, Comment, Share buttons to SDK hooks.
210
214
  * Uses optimistic UI for Like with automatic rollback on failure.
211
215
  */
212
- declare function ActionBar({ video, icons, interactionState: overrideState, onOpenComments, onShare, onLikeToggle, showBookmark, isBookmarked, onBookmarkToggle, direction, buttonVariant, className, children, testId, }: ActionBarProps): React.ReactElement;
216
+ declare function ActionBar({ content: contentProp, video: videoLegacy, icons, interactionState: overrideState, onOpenComments, onShare, onLikeToggle, showBookmark, isBookmarked, onBookmarkToggle, direction, buttonVariant, className, children, testId, }: ActionBarProps): React.ReactElement;
213
217
  declare namespace ActionBar {
214
218
  var displayName: string;
215
219
  }
@@ -219,10 +223,14 @@ declare namespace ActionBar {
219
223
  */
220
224
  interface AuthorInfoProps extends Omit<AuthorInfoHeadlessProps, 'authorState' | 'authorActions'> {
221
225
  /**
222
- * Video item to get author from
223
- * Required - AuthorInfo needs video data for author + follow state
226
+ * Content item (Video or Article) to get author from
227
+ * Required - AuthorInfo needs data for author + follow state
224
228
  */
225
- video: VideoItem;
229
+ content: ContentItem;
230
+ /**
231
+ * @deprecated Use 'content' instead. Will be removed in v3.0
232
+ */
233
+ video?: VideoItem;
226
234
  /**
227
235
  * Override author state (for custom scenarios)
228
236
  * If provided, replaces auto-derived state from video
@@ -277,7 +285,7 @@ interface AuthorInfoProps extends Omit<AuthorInfoHeadlessProps, 'authorState' |
277
285
  * Auto-connects Follow button to SDK hooks.
278
286
  * Uses optimistic UI for Follow with automatic rollback on failure.
279
287
  */
280
- declare function AuthorInfoRoot({ video, authorState: overrideState, authorActions: overrideActions, onOpenProfile, onFollowToggle, showFollowButton, variant, overlay, className, children, testId, }: AuthorInfoProps): React.ReactElement;
288
+ declare function AuthorInfoRoot({ content: contentProp, video: videoLegacy, authorState: overrideState, authorActions: overrideActions, onOpenProfile, onFollowToggle, showFollowButton, variant, overlay, className, children, testId, }: AuthorInfoProps): React.ReactElement;
281
289
  declare namespace AuthorInfoRoot {
282
290
  var displayName: string;
283
291
  }
@@ -349,8 +357,6 @@ interface CommentSheetProps {
349
357
  isOpen: boolean;
350
358
  /** Close callback */
351
359
  onClose: () => void;
352
- /** Current user info (required for optimistic UI when posting) */
353
- currentUser?: CommentAuthor;
354
360
  /** Config overrides */
355
361
  config?: Partial<CommentConfig>;
356
362
  /** Initial count from video data (displayed before API loads) */
@@ -368,7 +374,7 @@ interface CommentSheetProps {
368
374
  /** Close on escape key (default: true) */
369
375
  closeOnEscape?: boolean;
370
376
  }
371
- declare function CommentSheetInner({ videoId, isOpen, onClose, currentUser, config, initialCount, autoLoad, children, className, backdropClassName, closeOnBackdropClick, closeOnEscape, }: CommentSheetProps): ReactElement;
377
+ declare function CommentSheetInner({ videoId, isOpen, onClose, config, initialCount, autoLoad, children, className, backdropClassName, closeOnBackdropClick, closeOnEscape, }: CommentSheetProps): ReactElement;
372
378
  /**
373
379
  * Translated SheetHeader - auto-injects i18n strings
374
380
  */
@@ -486,6 +492,54 @@ declare namespace ProgressBar {
486
492
  var displayName: string;
487
493
  }
488
494
 
495
+ /**
496
+ * Lightweight Touch Drag Hook
497
+ *
498
+ * Custom replacement for @use-gesture/react's useDrag.
499
+ * ~1KB instead of ~20KB gzipped.
500
+ *
501
+ * Features:
502
+ * - Touch and mouse support
503
+ * - Axis locking (vertical/horizontal)
504
+ * - Velocity calculation
505
+ * - Direction detection
506
+ * - First/Last event detection
507
+ *
508
+ * @internal This is an internal implementation detail.
509
+ * Use useSwipeGesture for the public API.
510
+ */
511
+ type DragAxis = 'x' | 'y' | 'both';
512
+ interface DragState {
513
+ /** Movement from start [x, y] in pixels */
514
+ movement: [number, number];
515
+ /** Velocity [vx, vy] in px/ms */
516
+ velocity: [number, number];
517
+ /** Direction [-1, 0, 1] for each axis */
518
+ direction: [number, number];
519
+ /** True on first event of gesture */
520
+ first: boolean;
521
+ /** True on last event (release) */
522
+ last: boolean;
523
+ /** True while gesture is active */
524
+ active: boolean;
525
+ /** Cancel function to abort gesture */
526
+ cancel: () => void;
527
+ /** Original event */
528
+ event: TouchEvent | MouseEvent | PointerEvent;
529
+ }
530
+ interface DragConfig {
531
+ /** Axis to track: 'x', 'y', or 'both' */
532
+ axis?: DragAxis;
533
+ /** Filter out taps (short movements) */
534
+ filterTaps?: boolean;
535
+ /** Tap threshold in pixels */
536
+ tapThreshold?: number;
537
+ /** Enable touch events */
538
+ touch?: boolean;
539
+ /** Enable mouse/pointer events */
540
+ mouse?: boolean;
541
+ }
542
+ type DragHandler = (state: DragState) => void;
489
543
  interface DragBind {
490
544
  onPointerDown?: (e: React.PointerEvent) => void;
491
545
  onTouchStart?: (e: React.TouchEvent) => void;
@@ -493,6 +547,25 @@ interface DragBind {
493
547
  touchAction: string;
494
548
  };
495
549
  }
550
+ /**
551
+ * Lightweight drag hook - replacement for @use-gesture/react useDrag
552
+ *
553
+ * @param handler - Callback for drag events
554
+ * @param config - Configuration options
555
+ * @returns Bind function to spread on target element
556
+ *
557
+ * @example
558
+ * ```tsx
559
+ * const bind = useTouchDrag((state) => {
560
+ * if (state.first) console.log('Started dragging');
561
+ * if (state.last) console.log('Released', state.velocity);
562
+ * console.log('Movement:', state.movement);
563
+ * }, { axis: 'y' });
564
+ *
565
+ * return <div {...bind()}>Drag me</div>;
566
+ * ```
567
+ */
568
+ declare function useTouchDrag(handler: DragHandler, config?: DragConfig): () => DragBind;
496
569
 
497
570
  /**
498
571
  * Swipe Gesture Hook
@@ -506,10 +579,6 @@ interface DragBind {
506
579
  * - Velocity-based snap decisions
507
580
  * - Integration with ResourceGovernor
508
581
  *
509
- * PERFORMANCE CRITICAL (ADR 005):
510
- * - KHÔNG sử dụng useState cho dragOffset trong scroll loop
511
- * - Dùng useRef + direct DOM manipulation
512
- * - Chỉ sync state khi Touch End (Snap)
513
582
  *
514
583
  * AXIS SUPPORT:
515
584
  * - `vertical`: Full support - index navigation + gesture
@@ -549,6 +618,19 @@ interface SwipeConfig {
549
618
  * @default true
550
619
  */
551
620
  enableMouse?: boolean;
621
+ /**
622
+ * Temporarily disable swipe gestures.
623
+ * Use this to block swipe during other gestures (e.g., zoom).
624
+ *
625
+ * @default false
626
+ * @example
627
+ * ```tsx
628
+ * // Block swipe during zoom
629
+ * const { isSwipeLocked } = useZoomGesture();
630
+ * const swipe = useSwipeGesture({ disabled: isSwipeLocked });
631
+ * ```
632
+ */
633
+ disabled?: boolean;
552
634
  /**
553
635
  * Called when swipe completes and snaps
554
636
  */
@@ -700,37 +782,40 @@ interface UseSwipeGestureReturn {
700
782
  declare function useSwipeGesture(config?: SwipeConfig): UseSwipeGestureReturn;
701
783
 
702
784
  /**
703
- * Wired VideoFeed Component
785
+ * Wired Feed Component
704
786
  *
705
787
  * Pre-wired version of VideoFeedHeadless that auto-injects SDK hooks.
706
- * This is the recommended way to use VideoFeed in host applications.
788
+ * Supports mixed content (VideoItem | Article) in a single feed.
789
+ * This is the recommended way to use Feed in host applications.
707
790
  *
708
791
  * Features:
709
792
  * - Auto-connects to FeedManager via useFeed()
710
793
  * - Auto-handles swipe gestures via useSwipeGesture()
711
794
  * - Direct DOM manipulation for 60fps swipe (ADR 005)
712
- * - All props from VideoFeedHeadless are still available for customization
795
+ * - Mixed content support (videos + articles)
796
+ * - All props from FeedHeadless are still available for customization
713
797
  *
714
798
  * ## Gesture Scope
715
799
  *
716
- * Gestures are attached to the outer container div (not VideoFeedHeadless).
800
+ * Gestures are attached to the outer container div (not FeedHeadless).
717
801
  * If you wrap this component with additional DOM, gestures will still work
718
802
  * correctly as they're attached to the inner container.
719
803
  *
720
804
  * @example
721
805
  * ```tsx
722
- * import { VideoFeed } from '@xhub-short/sdk';
806
+ * import { Feed, isVideoItem, isArticle } from '@xhub-short/sdk';
723
807
  *
724
808
  * function App() {
725
809
  * return (
726
810
  * <ShortVideoProvider>
727
- * <VideoFeed
728
- * renderSlot={(video, index) => (
729
- * <div>
730
- * <img src={video.poster} alt={video.title} />
731
- * <span>{video.title}</span>
732
- * </div>
733
- * )}
811
+ * <Feed
812
+ * renderSlot={(item, index) => {
813
+ * // Type guard for mixed content
814
+ * if (isArticle(item)) {
815
+ * return <DefaultArticleSlot article={item} index={index} />;
816
+ * }
817
+ * return <DefaultVideoSlot video={item} index={index} />;
818
+ * }}
734
819
  * onIndexChange={(index) => console.log('Active:', index)}
735
820
  * />
736
821
  * </ShortVideoProvider>
@@ -740,31 +825,111 @@ declare function useSwipeGesture(config?: SwipeConfig): UseSwipeGestureReturn;
740
825
  */
741
826
 
742
827
  /**
743
- * Props for wired VideoFeed component
828
+ * Custom renderers for each content type.
829
+ * Allows host apps to override rendering per type without using explicit type guards.
830
+ */
831
+ interface SlotRenderers {
832
+ /** Custom renderer for video items */
833
+ video?: (props: {
834
+ video: VideoItem;
835
+ index: number;
836
+ isActive: boolean;
837
+ }) => ReactNode;
838
+ /** Custom renderer for article items */
839
+ article?: (props: {
840
+ article: Article;
841
+ index: number;
842
+ isActive: boolean;
843
+ }) => ReactNode;
844
+ }
845
+ /**
846
+ * Props for wired Feed component
847
+ *
848
+ * Supports mixed content (VideoItem | Article).
849
+ * Use type guards (isVideoItem, isArticle) in renderSlot to handle different content types.
744
850
  *
745
- * Extends VideoFeedHeadlessProps but feedState and swipeState are auto-injected.
851
+ * feedState and swipeState are auto-injected by SDK hooks.
746
852
  * You can still override them if needed.
747
853
  */
748
- interface VideoFeedProps {
749
- /** Container height (default: 100vh via CSS) */
854
+ interface FeedProps {
855
+ /**
856
+ * Container height (default: 100vh via CSS)
857
+ *
858
+ * @default 100vh
859
+ */
750
860
  height?: number | string;
751
- /** Additional CSS classes */
861
+ /**
862
+ * Additional CSS classes
863
+ * @default ''
864
+ */
752
865
  className?: string;
753
- /** Render function for each video slot */
754
- renderSlot: (video: VideoItem, index: number) => ReactNode;
755
- /** Called when active index changes */
866
+ /**
867
+ * Render function for each content slot (video or article)
868
+ *
869
+ * @deprecated Use `renderers` prop for a cleaner, type-safe mapping pattern.
870
+ * If not provided, RendererFactory will automatically select DefaultVideoSlot
871
+ * for videos and DefaultArticleSlot for articles.
872
+ *
873
+ * @param item - The content item (VideoItem | Article)
874
+ * @param index - The index of the slot
875
+ * @param isActive - Whether this slot is currently active/visible
876
+ * @returns The React node to render
877
+ */
878
+ renderSlot?: (item: ContentItem, index: number, isActive: boolean) => ReactNode;
879
+ /**
880
+ * Custom renderers for each content type.
881
+ * Recommended for advanced customization without explicit type guards.
882
+ *
883
+ * @example
884
+ * ```tsx
885
+ * <Feed
886
+ * renderers={{
887
+ * video: (props) => <MyCustomVideo {...props} showBookmark={false} />,
888
+ * article: (props) => <MyCustomArticle {...props} />
889
+ * }}
890
+ * />
891
+ * ```
892
+ */
893
+ renderers?: SlotRenderers;
894
+ /**
895
+ * Common props to pass to both default slots (if no renderers or renderSlot provided)
896
+ * or to use as a base for custom renderers.
897
+ */
898
+ slotProps?: Record<string, unknown>;
899
+ /**
900
+ * Called when active index changes
901
+ * @param index - The new active index
902
+ */
756
903
  onIndexChange?: (index: number) => void;
757
- /** Called when reaching near end of feed */
904
+ /**
905
+ * Called when reaching near end of feed
906
+ * @returns The React node to render
907
+ */
758
908
  onEndReached?: () => void;
759
- /** Threshold for triggering onEndReached (default: 2) */
909
+ /**
910
+ * Threshold for triggering onEndReached
911
+ * @default 2
912
+ */
760
913
  endReachedThreshold?: number;
761
- /** Number of slots to render before/after active (default: 1) */
914
+ /**
915
+ * Number of slots to render before/after active
916
+ * @default 1
917
+ */
762
918
  bufferSize?: number;
763
- /** Loading text */
919
+ /**
920
+ * Loading text
921
+ * @default 'Loading...'
922
+ */
764
923
  loadingText?: string;
765
- /** Empty text */
924
+ /**
925
+ * Empty text
926
+ * @default 'No videos'
927
+ */
766
928
  emptyText?: string;
767
- /** End of feed text */
929
+ /**
930
+ * End of feed text
931
+ * @default 'End of feed'
932
+ */
768
933
  endText?: string;
769
934
  /**
770
935
  * Whether to auto-load initial feed on mount
@@ -838,11 +1003,59 @@ interface VideoFeedProps {
838
1003
  * @default { touchAction: 'none' }
839
1004
  */
840
1005
  containerStyle?: CSSProperties;
1006
+ /**
1007
+ * Playlist ID to load.
1008
+ * If provided, feed will switch to Playlist mode.
1009
+ * If undefined/null, feed will switch to Recommendation mode.
1010
+ */
1011
+ playlistId?: string;
1012
+ /**
1013
+ * Externally disable swipe gestures.
1014
+ * Use this to block swipe during other gestures (e.g., zoom).
1015
+ *
1016
+ * @default false
1017
+ * @example
1018
+ * ```tsx
1019
+ * // With useZoomGesture hook
1020
+ * function MyFeed() {
1021
+ * const zoom = useZoomGesture();
1022
+ *
1023
+ * return (
1024
+ * <VideoFeed
1025
+ * swipeDisabled={zoom.isSwipeLocked}
1026
+ * renderSlot={(video, index) => (
1027
+ * <div {...zoom.handlers} style={{ transform: zoom.transform }}>
1028
+ * <video src={video.url} />
1029
+ * {!zoom.isZooming && <ActionBar />}
1030
+ * </div>
1031
+ * )}
1032
+ * />
1033
+ * );
1034
+ * }
1035
+ * ```
1036
+ */
1037
+ swipeDisabled?: boolean;
1038
+ /**
1039
+ * Custom empty state component.
1040
+ * Receives `text` prop (localized empty text).
1041
+ */
1042
+ renderEmpty?: (text: string) => ReactNode;
1043
+ /**
1044
+ * Custom loading state component.
1045
+ * Receives `text` prop (localized loading text).
1046
+ */
1047
+ renderLoading?: (text: string) => ReactNode;
1048
+ /**
1049
+ * Custom end of feed component.
1050
+ * Receives `text` prop (localized end text).
1051
+ */
1052
+ renderEnd?: (text: string) => ReactNode;
841
1053
  }
842
1054
  /**
843
- * Wired VideoFeed Component
1055
+ * Wired Feed Component
844
1056
  *
845
1057
  * Automatically connects to SDK's FeedManager and SwipeGesture.
1058
+ * Supports mixed content (VideoItem | Article) in a single feed.
846
1059
  * Provides smooth 60fps swipe navigation using ref-based DOM manipulation.
847
1060
  *
848
1061
  * ## Performance Notes
@@ -850,11 +1063,31 @@ interface VideoFeedProps {
850
1063
  * This component uses direct DOM manipulation during swipe to avoid
851
1064
  * React re-renders. The `dragOffset` in swipeState is always 0 because
852
1065
  * real-time offset is stored in a ref and applied directly to DOM elements.
1066
+ *
1067
+ * ## Mixed Content Support
1068
+ *
1069
+ * Use type guards in renderSlot to handle different content types:
1070
+ * ```tsx
1071
+ * <Feed
1072
+ * renderSlot={(item, index) => {
1073
+ * if (isArticle(item)) return <ArticleSlot article={item} />;
1074
+ * return <VideoSlot video={item} />;
1075
+ * }}
1076
+ * />
1077
+ * ```
853
1078
  */
854
- 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;
855
- declare namespace VideoFeed {
1079
+ declare function Feed({ height, className, renderSlot, renderers, slotProps, onIndexChange, onEndReached, endReachedThreshold, bufferSize, loadingText: loadingTextProp, emptyText: emptyTextProp, endText: endTextProp, autoLoad, autoLoadMore, swipeThreshold, velocityThreshold, snapDuration, onSwipe, feedState: feedStateProp, swipeState: swipeStateProp, containerStyle, swipeDisabled, playlistId, renderEmpty, renderLoading, renderEnd, }: FeedProps): React.ReactElement;
1080
+ declare namespace Feed {
856
1081
  var displayName: string;
857
1082
  }
1083
+ /**
1084
+ * @deprecated Use `Feed` instead. `VideoFeed` is an alias for backward compatibility.
1085
+ */
1086
+ declare const VideoFeed: typeof Feed;
1087
+ /**
1088
+ * @deprecated Use `FeedProps` instead. `VideoFeedProps` is an alias for backward compatibility.
1089
+ */
1090
+ type VideoFeedProps = FeedProps;
858
1091
 
859
1092
  /**
860
1093
  * VideoInfo - Wired SDK Component
@@ -875,9 +1108,9 @@ declare namespace VideoFeed {
875
1108
  */
876
1109
 
877
1110
  /**
878
- * Extended props for wired VideoInfo component
1111
+ * VideoInfo wired component props
879
1112
  */
880
- interface VideoInfoWiredProps extends VideoInfoProps {
1113
+ interface VideoInfoProps extends VideoInfoProps$1 {
881
1114
  /** Called when author name is clicked */
882
1115
  onOpenProfile?: (author: Author) => void;
883
1116
  /** Called when hashtag is clicked */
@@ -891,10 +1124,12 @@ interface VideoInfoWiredProps extends VideoInfoProps {
891
1124
  /** Test ID for testing */
892
1125
  testId?: string;
893
1126
  }
1127
+ /** @deprecated Use VideoInfoProps instead. Will be removed in v3.0 */
1128
+ type VideoInfoWiredProps = VideoInfoProps;
894
1129
  /**
895
1130
  * VideoInfo - Wired SDK component
896
1131
  */
897
- declare function VideoInfoRoot({ video, videoInfoState: overrideState, videoInfoActions: overrideActions, onOpenProfile, onHashtagClick, onMusicClick, onLocationClick, overlay, className, children, testId, }: VideoInfoWiredProps): ReactElement;
1132
+ declare function VideoInfoRoot({ content: contentProp, video: videoLegacy, videoInfoState: overrideState, videoInfoActions: overrideActions, onOpenProfile, onHashtagClick, onMusicClick, onLocationClick, overlay, className, children, testId, }: VideoInfoProps): ReactElement;
898
1133
  /**
899
1134
  * Compound component with sub-components attached
900
1135
  */
@@ -1107,10 +1342,29 @@ interface VideoSlotWiredProps extends VideoSlotProps {
1107
1342
  * Must be provided by host app if needed
1108
1343
  */
1109
1344
  onDoubleTap?: () => void;
1345
+ /**
1346
+ * Handle long press (hold > 500ms)
1347
+ * Typically used to open context menu (AdvanceMenu)
1348
+ */
1349
+ onLongPress?: () => void;
1350
+ /**
1351
+ * Disable tap gesture handling.
1352
+ * When true, single tap won't trigger play/pause toggle or PlayIndicator.
1353
+ * Useful during zoom gesture to prevent phantom taps from touchend events.
1354
+ */
1355
+ disableTap?: boolean;
1110
1356
  /** Custom error UI (receives wrapped error with metadata) */
1111
1357
  renderError?: (error: Error, retry: () => void) => ReactNode;
1112
1358
  /** Custom loading UI */
1113
1359
  renderLoading?: () => ReactNode;
1360
+ /** Title for reported overlay */
1361
+ reportedTitle?: string;
1362
+ /** Message for reported overlay */
1363
+ reportedMessage?: string;
1364
+ /** Button text for reported overlay */
1365
+ reportedButtonText?: string;
1366
+ /** Custom styles */
1367
+ style?: React.CSSProperties;
1114
1368
  }
1115
1369
  /**
1116
1370
  * SDK Player Error - Preserves error metadata from PlayerEngine
@@ -1160,88 +1414,623 @@ declare class SDKPlayerError extends Error {
1160
1414
  * Host app must trigger these manually or wait for future IntersectionObserver
1161
1415
  * implementation in VideoSlotHeadless.
1162
1416
  */
1163
- declare function VideoSlot({ video, index, resourceState: resourceStateOverride, playerState: playerStateOverride, playerControls: playerControlsOverride, className, children, onVisible, onHidden, onTap, onDoubleTap, renderError, renderLoading, }: VideoSlotWiredProps): React.ReactElement;
1417
+ declare function VideoSlot({ video, index, resourceState: resourceStateOverride, playerState: playerStateOverride, playerControls: playerControlsOverride, className, children, onVisible, onHidden, onTap, onDoubleTap, onLongPress, disableTap, renderError, renderLoading, reportedTitle, reportedMessage, reportedButtonText, style, }: VideoSlotWiredProps): React.ReactElement;
1164
1418
  declare namespace VideoSlot {
1165
1419
  var displayName: string;
1166
1420
  }
1167
1421
 
1168
- interface DefaultSlotProps {
1422
+ /**
1423
+ * Wired ArticleSlot Component
1424
+ *
1425
+ * Pre-wired version of ArticleSlotHeadless that auto-injects SDK hooks.
1426
+ * This is the recommended way to use ArticleSlot in host applications.
1427
+ *
1428
+ * Features:
1429
+ * - Auto-connects to useArticle hook for state management
1430
+ * - Auto-connects to SDK context for interactions
1431
+ * - Handles like animation and double-tap
1432
+ * - Integrates with DetailView for "Read More" functionality
1433
+ * - Music playback support
1434
+ */
1435
+
1436
+ interface ArticleSlotWiredProps extends Omit<ArticleSlotHeadlessProps, 'currentImageIndex' | 'onImageIndexChange' | 'isMusicPlaying' | 'onToggleMusic' | 'onDoubleTap' | 'onReadMoreClick'> {
1437
+ /** Slot index in the feed */
1438
+ index: number;
1439
+ /** Music info for this post */
1440
+ music?: MusicInfo;
1441
+ /** Whether this post is active (visible) */
1442
+ isActive?: boolean;
1443
+ /** Whether to show detail view on "Read More" click */
1444
+ enableDetailView?: boolean;
1445
+ /** Custom double tap handler (default: toggle like) */
1446
+ onDoubleTap?: () => void;
1447
+ /** Custom "Read More" handler (default: open detail view) */
1448
+ onReadMoreClick?: () => void;
1449
+ /** Custom long press handler */
1450
+ onLongPress?: () => void;
1451
+ /** Custom single tap handler (default: toggle music if tapToToggleMusic=true) */
1452
+ onTap?: () => void;
1453
+ /** Enable tap-to-toggle music (default: true if music exists) */
1454
+ tapToToggleMusic?: boolean;
1455
+ /**
1456
+ * Callback when image index changes in carousel.
1457
+ * Useful for syncing with Detail View.
1458
+ */
1459
+ onImageIndexChange?: (index: number) => void;
1460
+ /** Children (overlay content) */
1461
+ children?: ReactNode;
1462
+ /** Custom detail view content */
1463
+ renderDetailView?: (props: {
1464
+ article: Article;
1465
+ onClose: () => void;
1466
+ isOpen: boolean;
1467
+ }) => ReactNode;
1468
+ /** Detail view header title */
1469
+ detailViewTitle?: string;
1470
+ /** Whether to show follow button in detail view */
1471
+ showFollowButton?: boolean;
1472
+ /** Current user follows this author */
1473
+ isFollowing?: boolean;
1474
+ /** Follow button click handler */
1475
+ onFollowClick?: () => void;
1476
+ /** Custom styles */
1477
+ style?: React.CSSProperties;
1478
+ }
1479
+ declare function ArticleSlot({ article, index, music, isActive, enableDetailView, onDoubleTap: customDoubleTap, onReadMoreClick: customReadMore, onLongPress, onTap: customTap, tapToToggleMusic, onImageIndexChange: onIndexChangeProp, children, renderDetailView, detailViewTitle, showFollowButton, isFollowing, onFollowClick, ...restProps }: ArticleSlotWiredProps): ReactElement;
1480
+ declare namespace ArticleSlot {
1481
+ var displayName: string;
1482
+ }
1483
+ /** @deprecated Use ArticleSlot instead */
1484
+ declare const ImagePostSlot: typeof ArticleSlot;
1485
+ /** @deprecated Use ArticleSlotWiredProps instead */
1486
+ type ImagePostSlotWiredProps = ArticleSlotWiredProps;
1487
+
1488
+ interface DefaultArticleSlotProps {
1489
+ /** Article data */
1490
+ article: Article;
1491
+ /** Index in the feed */
1492
+ index: number;
1493
+ /** Whether this post is currently active/visible (for music autoplay) */
1494
+ isActive?: boolean;
1495
+ showLikeAnimation?: boolean;
1496
+ showBookmark?: boolean;
1497
+ showShare?: boolean;
1498
+ showComment?: boolean;
1499
+ showMusic?: boolean;
1500
+ showPlayIndicator?: boolean;
1501
+ showAuthorFollow?: boolean;
1502
+ enableDetailView?: boolean;
1503
+ enableZoom?: boolean;
1504
+ showCounter?: boolean;
1505
+ showAdvanceMenu?: boolean;
1506
+ showCleanModeOverlay?: boolean;
1507
+ showReportSheet?: boolean;
1508
+ detailViewTitle?: string;
1509
+ onShare?: (article: Article) => void;
1510
+ onOpenComments?: (postId: string) => void;
1511
+ onAuthorTap?: (article: Article) => void;
1512
+ onFollow?: (article: Article) => void;
1513
+ onHashtagTap?: (hashtag: string, article: Article) => void;
1514
+ onContentHidden?: (contentId: string) => void;
1515
+ onLikeToggle?: (isLiked: boolean) => void;
1516
+ onBookmarkToggle?: (isBookmarked: boolean) => void;
1517
+ renderActionBar?: (props: ActionBarProps) => ReactNode;
1518
+ renderAuthorInfo?: (props: AuthorInfoProps) => ReactNode;
1519
+ children?: ReactNode;
1520
+ /** Additional className */
1521
+ className?: string;
1522
+ }
1523
+ declare const DefaultArticleSlot: react.NamedExoticComponent<DefaultArticleSlotProps>;
1524
+ /** @deprecated Use DefaultArticleSlot instead */
1525
+ declare const DefaultImagePostSlot: react.NamedExoticComponent<DefaultArticleSlotProps>;
1526
+ /** @deprecated Use DefaultArticleSlotProps instead */
1527
+ type DefaultImagePostSlotProps = DefaultArticleSlotProps;
1528
+
1529
+ interface AdvanceMenuProps {
1530
+ /** Content item (Video or Article) */
1531
+ content: ContentItem;
1532
+ /** @deprecated Use content instead. Will be removed in v3.0 */
1533
+ video?: VideoItem;
1534
+ /** Whether menu is open */
1535
+ isOpen: boolean;
1536
+ /** Close handler */
1537
+ onClose: () => void;
1538
+ /** Callback when report is clicked (opens report sheet) */
1539
+ onOpenReport?: () => void;
1540
+ /** Show quality picker (default: true) */
1541
+ showQuality?: boolean;
1542
+ /** Show auto-scroll toggle (default: true) */
1543
+ showAutoScroll?: boolean;
1544
+ /** Show clean mode option (default: true) */
1545
+ showCleanMode?: boolean;
1546
+ /** Show not interested option (default: true) */
1547
+ showNotInterested?: boolean;
1548
+ /** Show report option (default: true) */
1549
+ showReport?: boolean;
1550
+ /** Custom class name */
1551
+ className?: string;
1552
+ /** Speed label */
1553
+ speedLabel?: string;
1554
+ /** Quality label */
1555
+ qualityLabel?: string;
1556
+ /** Auto-scroll label */
1557
+ autoScrollLabel?: string;
1558
+ /** Clean mode label */
1559
+ cleanModeLabel?: string;
1560
+ /** Not interested label */
1561
+ notInterestedLabel?: string;
1562
+ /** Report label */
1563
+ reportLabel?: string;
1564
+ /** Custom speed icon */
1565
+ speedIcon?: ReactNode;
1566
+ /** Custom quality icon */
1567
+ qualityIcon?: ReactNode;
1568
+ /** Custom auto-scroll icon */
1569
+ autoScrollIcon?: ReactNode;
1570
+ /** Custom clean mode icon */
1571
+ cleanModeIcon?: ReactNode;
1572
+ /** Custom not interested icon */
1573
+ notInterestedIcon?: ReactNode;
1574
+ /** Custom report icon */
1575
+ reportIcon?: ReactNode;
1576
+ }
1577
+ declare function AdvanceMenuComponent({ content: contentProp, video: videoLegacy, isOpen, onClose, onOpenReport, showQuality, showAutoScroll, showCleanMode, showNotInterested, showReport, className, speedLabel, qualityLabel, autoScrollLabel, cleanModeLabel, notInterestedLabel, reportLabel, speedIcon, qualityIcon, autoScrollIcon, cleanModeIcon, notInterestedIcon, reportIcon, }: AdvanceMenuProps): ReactElement;
1578
+ declare const AdvanceMenu: react.MemoExoticComponent<typeof AdvanceMenuComponent>;
1579
+ /** @deprecated Use AdvanceMenu instead */
1580
+ declare const AdvanceMenuWired: react.MemoExoticComponent<typeof AdvanceMenuComponent>;
1581
+ /** @deprecated Use AdvanceMenuProps instead */
1582
+ type AdvanceMenuWiredProps = AdvanceMenuProps;
1583
+
1584
+ interface ReportSheetProps {
1585
+ /** Content ID to report */
1586
+ contentId: string;
1587
+ /** Current video index in feed (required for goToNextOnSuccess) */
1588
+ currentIndex?: number;
1589
+ /** Whether sheet is open */
1590
+ isOpen: boolean;
1591
+ /** Close handler */
1592
+ onClose: () => void;
1593
+ /** Callback when report succeeds */
1594
+ onSuccess?: () => void;
1595
+ /** Callback when report fails */
1596
+ onError?: (error: Error) => void;
1597
+ /**
1598
+ * Auto navigate to next video when Done is clicked after successful report
1599
+ * @default true
1600
+ */
1601
+ goToNextOnSuccess?: boolean;
1602
+ /** Custom class name */
1603
+ className?: string;
1604
+ /** Sheet title for step 1 - reason selection */
1605
+ selectTitle?: string;
1606
+ /** Sheet title for step 2 - report detail */
1607
+ title?: string;
1608
+ /** Text input placeholder */
1609
+ inputPlaceholder?: string;
1610
+ /** Submit button text */
1611
+ submitText?: string;
1612
+ /** Loading text */
1613
+ loadingText?: string;
1614
+ /** Success title */
1615
+ successTitle?: string;
1616
+ /** Success message */
1617
+ successMessage?: string;
1618
+ /** Done button text (on success screen) */
1619
+ doneText?: string;
1620
+ /** Error message */
1621
+ errorMessage?: string;
1622
+ /** Error description (retry hint) */
1623
+ errorDescription?: string;
1624
+ /**
1625
+ * Custom button element to trigger the report sheet
1626
+ */
1627
+ buttonElement?: ReactElement;
1628
+ }
1629
+ declare function ReportSheetComponent({ contentId, currentIndex, isOpen, onClose, onSuccess, onError, goToNextOnSuccess, className, selectTitle, title, inputPlaceholder, submitText, loadingText, successTitle, successMessage, doneText, errorMessage, errorDescription, buttonElement, }: ReportSheetProps): ReactElement;
1630
+ declare const ReportSheet: react.MemoExoticComponent<typeof ReportSheetComponent>;
1631
+ /** @deprecated Use ReportSheet instead */
1632
+ declare const ReportSheetWired: react.MemoExoticComponent<typeof ReportSheetComponent>;
1633
+ /** @deprecated Use ReportSheetProps instead */
1634
+ type ReportSheetWiredProps = ReportSheetProps;
1635
+
1636
+ interface CleanModeOverlayProps {
1637
+ /** Auto-hide delay in ms (default: 3000) */
1638
+ hideDelay?: number;
1639
+ /** Custom exit icon */
1640
+ exitIcon?: ReactNode;
1641
+ /** Custom play icon */
1642
+ playIcon?: ReactNode;
1643
+ /** Custom pause icon */
1644
+ pauseIcon?: ReactNode;
1645
+ /** Custom class name */
1646
+ className?: string;
1647
+ }
1648
+ declare function CleanModeOverlayComponent({ hideDelay, exitIcon, playIcon, pauseIcon, className, }: CleanModeOverlayProps): ReactElement | null;
1649
+ declare const CleanModeOverlay: react.MemoExoticComponent<typeof CleanModeOverlayComponent>;
1650
+
1651
+ interface DefaultVideoSlotProps {
1169
1652
  /** Video item data */
1170
1653
  video: VideoItem;
1171
1654
  /** Index in the feed */
1172
1655
  index: number;
1173
- /** Show poster before video plays (default: true) */
1174
1656
  showPoster?: boolean;
1175
- /** Show play/pause indicator on tap (default: true) */
1176
1657
  showPlayIndicator?: boolean;
1177
- /** Keep play icon visible while video is paused - YouTube style (default: true) */
1178
1658
  persistPlayIndicatorWhenPaused?: boolean;
1179
- /** Show like animation on double-tap (default: true) */
1180
1659
  showLikeAnimation?: boolean;
1181
- /** Show author info - avatar + follow badge (default: true) */
1182
1660
  showAuthorInfo?: boolean;
1183
- /** Show action bar - like, comment, share (default: true) */
1184
1661
  showActionBar?: boolean;
1185
- /** Show video info - author name, caption, hashtags (default: true) */
1186
1662
  showVideoInfo?: boolean;
1187
- /** Show progress bar (default: true) */
1188
1663
  showProgressBar?: boolean;
1189
- /** Show time display in progress bar (default: true) */
1190
1664
  showTime?: boolean;
1191
- /** Show tooltip when seeking (default: true) */
1192
1665
  showTooltip?: boolean;
1193
- /** Show bookmark button (default: false) */
1194
1666
  showBookmark?: boolean;
1195
- /** Show comment sheet when comment button is clicked (default: true) */
1196
1667
  showCommentSheet?: boolean;
1197
- /** Show debug info (default: false) */
1198
1668
  showDebug?: boolean;
1199
- /** Called when comments button is clicked */
1200
- onOpenComments?: (videoId: string) => void;
1201
- /** Called when share button is clicked */
1202
- onShare?: (video: VideoItem) => void;
1203
- /** Called when like is toggled */
1204
- onLikeToggle?: (isNowLiked: boolean, videoId: string) => void;
1205
- /** Called when bookmark is toggled */
1206
- onBookmarkToggle?: (isNowBookmarked: boolean, videoId: string) => void;
1207
- /** Called when author profile is clicked */
1669
+ showCleanModeOverlay?: boolean;
1670
+ showAdvanceMenu?: boolean;
1671
+ showReportSheet?: boolean;
1672
+ onOpenComments?: () => void;
1673
+ onShare?: (content: VideoItem) => void;
1674
+ onLikeToggle?: (isLiked: boolean) => void;
1675
+ onBookmarkToggle?: (isBookmarked: boolean) => void;
1208
1676
  onOpenProfile?: (author: VideoItem['author']) => void;
1209
- /** Called when follow is toggled */
1210
- onFollowToggle?: (isNowFollowing: boolean, authorId: string) => void;
1211
- /** Called when a hashtag is clicked */
1677
+ onFollowToggle?: (isFollowing: boolean, authorId: string) => void;
1212
1678
  onHashtagClick?: (hashtag: string) => void;
1213
- /** Custom VideoPlayer renderer */
1679
+ onContentHidden?: (contentId: string) => void;
1680
+ onReportSuccess?: (contentId: string) => void;
1681
+ onReportError?: (error: Error) => void;
1682
+ onZoomStateChange?: (isZooming: boolean) => void;
1214
1683
  renderPlayer?: (props: VideoPlayerProps) => ReactNode;
1215
- /** Custom ActionBar renderer */
1216
1684
  renderActionBar?: (props: ActionBarProps) => ReactNode;
1217
- /** Custom AuthorInfo renderer */
1218
1685
  renderAuthorInfo?: (props: AuthorInfoProps) => ReactNode;
1219
- /** Custom VideoInfo renderer */
1220
- renderVideoInfo?: (props: VideoInfoWiredProps) => ReactNode;
1221
- /** Custom ProgressBar renderer */
1686
+ renderVideoInfo?: (props: VideoInfoProps) => ReactNode;
1222
1687
  renderProgressBar?: (props: ProgressBarProps) => ReactNode;
1223
- /** Custom CommentSheet renderer */
1224
- renderCommentSheet?: (props: CommentSheetProps) => ReactNode;
1225
- /** Custom Error renderer */
1688
+ renderCommentSheet?: (props: {
1689
+ videoId: string;
1690
+ isOpen: boolean;
1691
+ onClose: () => void;
1692
+ config?: Partial<CommentConfig>;
1693
+ }) => ReactNode;
1694
+ renderAdvanceMenu?: (props: {
1695
+ content: VideoItem;
1696
+ isOpen: boolean;
1697
+ onClose: () => void;
1698
+ onOpenReport?: () => void;
1699
+ }) => ReactNode;
1700
+ renderReportSheet?: (props: {
1701
+ contentId: string;
1702
+ isOpen: boolean;
1703
+ onClose: () => void;
1704
+ onSuccess?: () => void;
1705
+ onError?: (error: Error) => void;
1706
+ }) => ReactNode;
1226
1707
  renderError?: (error: Error, retry: () => void) => ReactNode;
1227
- /** Current user info for optimistic UI when posting comments */
1228
- currentUser?: CommentAuthor;
1229
- /** Comment configuration (pageSize, maxLength, etc.) */
1230
1708
  commentConfig?: Partial<CommentConfig>;
1231
- /** Like animation style (default: 'float') */
1232
1709
  likeAnimationStyle?: 'float' | 'burst' | 'scale' | 'bounce';
1233
- /** Like animation duration in ms (default: 1200) */
1234
1710
  likeAnimationDuration?: number;
1235
- /** Max hearts in animation (default: 15) */
1236
1711
  likeAnimationMaxHearts?: number;
1237
- /** Heart size in px (default: 70) */
1238
1712
  likeAnimationSize?: number;
1239
- /** Heart color (default: '#fe2c55') */
1240
1713
  likeAnimationColor?: string;
1241
- /** Additional class name */
1714
+ enableZoom?: boolean;
1715
+ zoomMaxScale?: number;
1716
+ zoomSnapBackAnimation?: 'none' | 'ease' | 'spring';
1717
+ className?: string;
1718
+ }
1719
+ declare const DefaultVideoSlot: react.NamedExoticComponent<DefaultVideoSlotProps>;
1720
+
1721
+ /**
1722
+ * Snap-back animation type
1723
+ * - 'none': Instant snap (no animation)
1724
+ * - 'ease': Smooth ease-out transition
1725
+ * - 'spring': Spring-like bounce effect
1726
+ */
1727
+ type SnapBackAnimation = 'none' | 'ease' | 'spring';
1728
+ /**
1729
+ * Configuration for useZoomGesture
1730
+ */
1731
+ interface UseZoomGestureConfig {
1732
+ /** Minimum scale factor (default: 1) */
1733
+ minScale?: number;
1734
+ /** Maximum scale factor (default: 5) */
1735
+ maxScale?: number;
1736
+ /** Whether to lock vertical swipe during zoom (default: true) */
1737
+ lockVerticalSwipe?: boolean;
1738
+ /**
1739
+ * Snap-back animation type (default: 'ease')
1740
+ * - 'none': Instant snap, onZoomEnd called immediately
1741
+ * - 'ease': Smooth ease-out, onZoomEnd called after duration
1742
+ * - 'spring': Spring bounce effect, onZoomEnd called after duration
1743
+ */
1744
+ snapBackAnimation?: SnapBackAnimation;
1745
+ /** Snap-back animation duration in ms (default: 200) */
1746
+ snapBackDuration?: number;
1747
+ /** Callback when zoom starts (scale > 1) */
1748
+ onZoomStart?: () => void;
1749
+ /** Callback when zoom ends (after snap-back animation completes) */
1750
+ onZoomEnd?: (finalScale: number) => void;
1751
+ /** Callback on scale change during gesture */
1752
+ onZoomChange?: (scale: number) => void;
1753
+ /** Whether zoom is enabled (default: true) */
1754
+ enabled?: boolean;
1755
+ }
1756
+ /**
1757
+ * Touch event handlers
1758
+ */
1759
+ interface ZoomGestureHandlers {
1760
+ onTouchStart: (e: react__default.TouchEvent) => void;
1761
+ onTouchMove: (e: react__default.TouchEvent) => void;
1762
+ onTouchEnd: (e: react__default.TouchEvent) => void;
1763
+ }
1764
+ /**
1765
+ * Return type for useZoomGesture
1766
+ */
1767
+ interface UseZoomGestureReturn {
1768
+ /** Current scale factor (1 = normal) */
1769
+ scale: number;
1770
+ /** Current X translation in pixels */
1771
+ translateX: number;
1772
+ /** Current Y translation in pixels */
1773
+ translateY: number;
1774
+ /** Whether actively zooming (2+ fingers) */
1775
+ isZooming: boolean;
1776
+ /** Whether currently panning while zoomed */
1777
+ isPanning: boolean;
1778
+ /** Whether snap-back animation is playing */
1779
+ isAnimating: boolean;
1780
+ /** Whether vertical swipe is locked */
1781
+ isSwipeLocked: boolean;
1782
+ /** Touch event handlers to spread on container */
1783
+ handlers: ZoomGestureHandlers;
1784
+ /** Manually reset to default state */
1785
+ reset: () => void;
1786
+ /** CSS transform string for convenience */
1787
+ transform: string;
1788
+ /** CSS transform-origin string */
1789
+ transformOrigin: string;
1790
+ /**
1791
+ * CSS styles for container element.
1792
+ * Includes `touchAction: 'none'` for proper gesture handling on mobile.
1793
+ * Always spread this on your container for best compatibility.
1794
+ */
1795
+ containerStyle: react__default.CSSProperties;
1796
+ /**
1797
+ * CSS transition string for snap-back animation.
1798
+ * Apply this to the transform property for smooth animations.
1799
+ */
1800
+ transitionStyle: react__default.CSSProperties;
1801
+ }
1802
+ /**
1803
+ * useZoomGesture - Pinch-to-zoom gesture handler
1804
+ *
1805
+ * Handles pinch gestures for video zoom with pan support.
1806
+ * Always snaps back to scale=1 on release (Instagram Reels behavior).
1807
+ *
1808
+ * @example
1809
+ * ```tsx
1810
+ * function VideoPlayer({ video }: { video: VideoItem }) {
1811
+ * const {
1812
+ * transform,
1813
+ * transformOrigin,
1814
+ * containerStyle,
1815
+ * handlers,
1816
+ * isZooming,
1817
+ * } = useZoomGesture({
1818
+ * onZoomStart: () => enterCleanMode('zoom'),
1819
+ * onZoomEnd: () => exitCleanMode(),
1820
+ * snapBackAnimation: 'ease', // smooth snap-back
1821
+ * });
1822
+ *
1823
+ * return (
1824
+ * <div
1825
+ * style={{
1826
+ * ...containerStyle, // includes touchAction: 'none' for proper gesture handling
1827
+ * transform,
1828
+ * transformOrigin,
1829
+ * }}
1830
+ * {...handlers}
1831
+ * >
1832
+ * <video src={video.url} />
1833
+ * </div>
1834
+ * );
1835
+ * }
1836
+ * ```
1837
+ *
1838
+ * @remarks
1839
+ * **Important:** Always spread `containerStyle` on your container element.
1840
+ * This sets `touchAction: 'none'` which is required for `preventDefault()` to work
1841
+ * on mobile browsers (Chrome 56+, Safari) where touch events are passive by default.
1842
+ */
1843
+ declare function useZoomGesture(config?: UseZoomGestureConfig): UseZoomGestureReturn;
1844
+
1845
+ /**
1846
+ * Minimum requirements for content used in SlotComposer
1847
+ */
1848
+ interface SlotContent {
1849
+ /** Unique content ID */
1850
+ id: string;
1851
+ /** Author information */
1852
+ author: Author;
1853
+ /** Content statistics */
1854
+ stats: ContentStats;
1855
+ /** Content type discriminator */
1856
+ type: 'video' | 'article';
1857
+ }
1858
+ /**
1859
+ * State provided by SlotComposer to its children
1860
+ */
1861
+ interface ComposerState {
1862
+ /** Whether clean mode is active */
1863
+ cleanMode: boolean;
1864
+ /** Whether pinch-to-zoom is currently active */
1865
+ isZoomActive: boolean;
1866
+ /** Whether content is liked (reactive) */
1867
+ isLiked: boolean;
1868
+ /** Whether content is bookmarked (local state) */
1869
+ isBookmarked: boolean;
1870
+ /** Whether comment sheet is open */
1871
+ isCommentSheetOpen: boolean;
1872
+ /** Whether advance menu is open */
1873
+ isMenuOpen: boolean;
1874
+ /** Whether report sheet is open */
1875
+ isReportSheetOpen: boolean;
1876
+ /** Zoom transform property */
1877
+ zoomTransform: string;
1878
+ /** Zoom transform origin */
1879
+ zoomTransformOrigin: string;
1880
+ /** Zoom container style (includes touchAction: 'none') */
1881
+ zoomContainerStyle: React.CSSProperties;
1882
+ /** Zoom snap-back transition style */
1883
+ zoomTransitionStyle: React.CSSProperties;
1884
+ }
1885
+ /**
1886
+ * Handlers provided by SlotComposer
1887
+ */
1888
+ interface ComposerHandlers {
1889
+ /** Toggle like status */
1890
+ handleLike: () => void;
1891
+ /** Trigger share action */
1892
+ handleShare: () => void;
1893
+ /** Trigger comment action */
1894
+ handleComment: () => void;
1895
+ /** Toggle bookmark status */
1896
+ handleBookmark: () => void;
1897
+ /** Handle double-tap like (like only) */
1898
+ handleDoubleTap: () => void;
1899
+ /** Handle open report sheet */
1900
+ handleOpenReport: () => void;
1901
+ /** Close all transient UI */
1902
+ handleCloseAll: () => void;
1903
+ /** Set visibility states */
1904
+ setCommentSheetOpen: (open: boolean) => void;
1905
+ setMenuOpen: (open: boolean) => void;
1906
+ setReportSheetOpen: (open: boolean) => void;
1907
+ /** Pinch-to-zoom touch event handlers */
1908
+ zoomHandlers: ReturnType<typeof useZoomGesture>['handlers'];
1909
+ }
1910
+ /**
1911
+ * Pre-configured wired components
1912
+ */
1913
+ interface ComposerComponents {
1914
+ /** Pre-wired ActionBar */
1915
+ ActionBarComponent: (props: {
1916
+ icons: ActionBarIconSet;
1917
+ onOpenComments?: () => void;
1918
+ onShare?: (content: ContentItem) => void;
1919
+ }) => ReactNode;
1920
+ /** Pre-wired CommentSheet */
1921
+ CommentSheetComponent: (props: {
1922
+ isOpen: boolean;
1923
+ onClose: () => void;
1924
+ initialCount?: number;
1925
+ }) => ReactNode;
1926
+ /** Pre-wired AdvanceMenu */
1927
+ AdvanceMenuComponent: (props: {
1928
+ isOpen: boolean;
1929
+ onClose: () => void;
1930
+ onOpenReport?: () => void;
1931
+ }) => ReactNode;
1932
+ /** Pre-wired ReportSheet */
1933
+ ReportSheetComponent: (props: {
1934
+ isOpen: boolean;
1935
+ onClose: () => void;
1936
+ }) => ReactNode;
1937
+ }
1938
+ /**
1939
+ * Context provided to the children render function
1940
+ */
1941
+ interface ComposerContext<TContent extends SlotContent> {
1942
+ /** Passed content data */
1943
+ content: TContent;
1944
+ /** Aggregate state from SDK hooks */
1945
+ state: ComposerState;
1946
+ /** Aggregate handlers from SDK hooks */
1947
+ handlers: ComposerHandlers;
1948
+ /** Pre-configured wired components */
1949
+ components: ComposerComponents;
1950
+ }
1951
+ interface SlotComposerProps<TContent extends SlotContent> {
1952
+ /** Content data (VideoItem or Article) */
1953
+ content: TContent;
1954
+ /** Render prop function */
1955
+ children: (context: ComposerContext<TContent>) => ReactNode;
1956
+ /** Callback when like is toggled */
1957
+ onLikeToggle?: (isLiked: boolean) => void;
1958
+ /** Callback when bookmark is toggled */
1959
+ onBookmarkToggle?: (isBookmarked: boolean) => void;
1960
+ /** Callback when comments are opened */
1961
+ onOpenComments?: () => void;
1962
+ /** Callback when share is triggered */
1963
+ onShare?: (content: ContentItem) => void;
1964
+ /** Callback when zoom state changes */
1965
+ onZoomStateChange?: (isZooming: boolean) => void;
1966
+ /** Whether to show ActionBar (default: true) */
1967
+ showActionBar?: boolean;
1968
+ /** Whether to show CommentSheet (default: true) */
1969
+ showCommentSheet?: boolean;
1970
+ /** Whether to show AdvanceMenu (default: true) */
1971
+ showAdvanceMenu?: boolean;
1972
+ /** Zoom max scale (default: 5) */
1973
+ zoomMaxScale?: number;
1974
+ /** Snap-back animation style (default: 'ease') */
1975
+ zoomSnapBackAnimation?: 'none' | 'ease' | 'spring';
1976
+ }
1977
+ /**
1978
+ * SlotComposer - Logic-only component for wiring slots
1979
+ *
1980
+ * extraction of shared behavior between DefaultVideoSlot and DefaultArticleSlot.
1981
+ */
1982
+ declare function SlotComposer<TContent extends SlotContent>({ content: initialContent, children, onLikeToggle, onBookmarkToggle, onOpenComments, onShare, onZoomStateChange, showActionBar, showCommentSheet, showAdvanceMenu, zoomMaxScale, zoomSnapBackAnimation, }: SlotComposerProps<TContent>): react_jsx_runtime.JSX.Element;
1983
+ declare namespace SlotComposer {
1984
+ var displayName: string;
1985
+ }
1986
+
1987
+ interface PlaylistBarProps {
1988
+ /** Custom playlist icon */
1989
+ icon?: React.ReactNode;
1990
+ /** Custom arrow icon */
1991
+ arrowIcon?: React.ReactNode;
1992
+ /** Optional label text */
1993
+ label?: string;
1994
+ }
1995
+ /**
1996
+ * Wired PlaylistBar component
1997
+ * Automatically connects to PlaylistContext to display current playlist info.
1998
+ */
1999
+ declare function PlaylistBar({ icon, arrowIcon, label }: PlaylistBarProps): react_jsx_runtime.JSX.Element | null;
2000
+
2001
+ interface PlaylistCollectionProps {
2002
+ /** View type: grid or list */
2003
+ viewType?: 'grid' | 'list';
2004
+ /** Optional callback for navigation when a playlist is selected */
2005
+ onNavigate?: (id: string) => void;
2006
+ /** Custom class name */
1242
2007
  className?: string;
1243
2008
  }
1244
- declare const DefaultSlot: react.NamedExoticComponent<DefaultSlotProps>;
2009
+ /**
2010
+ * Wired PlaylistCollection component
2011
+ *
2012
+ * Connects to usePlaylistCollection hook and renders PlaylistCollectionHeadless.
2013
+ * Automatically handles data fetching and i18n.
2014
+ */
2015
+ declare function PlaylistCollection({ viewType, onNavigate, className, }: PlaylistCollectionProps): react_jsx_runtime.JSX.Element;
2016
+
2017
+ interface PlaylistSheetProps {
2018
+ /** Optional custom header accessory */
2019
+ headerAccessory?: ReactNode;
2020
+ /** Optional custom translations */
2021
+ translations?: {
2022
+ title?: string;
2023
+ emptyState?: string;
2024
+ nowPlaying?: string;
2025
+ };
2026
+ }
2027
+ /**
2028
+ * Wired Playlist Sheet Component
2029
+ *
2030
+ * Connects the headless playlist sheet to the SDK store and context.
2031
+ * Automatically handles item selection and visibility state via Global UI Store.
2032
+ */
2033
+ declare function PlaylistSheet({ headerAccessory, translations }: PlaylistSheetProps): react_jsx_runtime.JSX.Element;
1245
2034
 
1246
2035
  /**
1247
2036
  * SDK Configuration Types
@@ -1256,6 +2045,8 @@ declare const DefaultSlot: react.NamedExoticComponent<DefaultSlotProps>;
1256
2045
  interface AdaptersConfig {
1257
2046
  /** Data source adapter for fetching video feed */
1258
2047
  dataSource?: IDataSource;
2048
+ /** Playlist data source adapter for fetching playlists */
2049
+ playlist?: IPlaylistDataSource;
1259
2050
  /** Interaction adapter for like/follow/comment actions */
1260
2051
  interaction?: IInteraction;
1261
2052
  /** Comment adapter for comment operations (read/write/like) */
@@ -1273,6 +2064,64 @@ interface AdaptersConfig {
1273
2064
  /** Poster loader adapter for preloading thumbnails */
1274
2065
  posterLoader?: IPosterLoader;
1275
2066
  }
2067
+ /**
2068
+ * User information for SDK features
2069
+ *
2070
+ * Used by:
2071
+ * - Analytics: Set user context for events
2072
+ * - Comments: Author info for posted comments
2073
+ * - Any feature requiring user identification
2074
+ */
2075
+ interface SDKUser {
2076
+ /** User ID (required) */
2077
+ id: string;
2078
+ /** Display name */
2079
+ name?: string;
2080
+ /** Avatar URL */
2081
+ avatar?: string;
2082
+ /** Additional user properties (for analytics) */
2083
+ properties?: Record<string, unknown>;
2084
+ }
2085
+ /**
2086
+ * User configuration
2087
+ */
2088
+ interface UserConfig {
2089
+ /**
2090
+ * Current user info
2091
+ *
2092
+ * If provided, SDK will:
2093
+ * - Set analytics user context automatically
2094
+ * - Use as default author for comments
2095
+ *
2096
+ * @example
2097
+ * ```tsx
2098
+ * <ShortVideoProvider config={{
2099
+ * user: {
2100
+ * current: {
2101
+ * id: 'user-123',
2102
+ * name: 'John Doe',
2103
+ * avatar: 'https://example.com/avatar.jpg',
2104
+ * },
2105
+ * },
2106
+ * }}>
2107
+ * ```
2108
+ */
2109
+ current?: SDKUser | null;
2110
+ /**
2111
+ * Callback to get user dynamically
2112
+ * Called when user info is needed but `current` is not set
2113
+ *
2114
+ * @example
2115
+ * ```tsx
2116
+ * <ShortVideoProvider config={{
2117
+ * user: {
2118
+ * getUser: () => authStore.getCurrentUser(),
2119
+ * },
2120
+ * }}>
2121
+ * ```
2122
+ */
2123
+ getUser?: () => SDKUser | null | Promise<SDKUser | null>;
2124
+ }
1276
2125
  /**
1277
2126
  * Actions that require authentication
1278
2127
  *
@@ -1287,7 +2136,7 @@ type GuestAction = 'like' | 'unlike' | 'comment' | 'reply' | 'follow' | 'unfollo
1287
2136
  */
1288
2137
  interface GuestActionContext {
1289
2138
  /** Type of resource */
1290
- resourceType: 'video' | 'comment' | 'author';
2139
+ resourceType: 'video' | 'article' | 'comment' | 'author';
1291
2140
  /** Resource ID */
1292
2141
  resourceId: string;
1293
2142
  /** Additional metadata (e.g., videoId for comment, authorId for follow) */
@@ -1451,7 +2300,9 @@ interface SDKConfig {
1451
2300
  prefetchCache?: {
1452
2301
  /** Enable instant loading from cache (default: true) */
1453
2302
  enabled?: boolean;
1454
- /** Number of videos to cache (default: 10) */
2303
+ /** Number of items to cache (default: 10) */
2304
+ maxItems?: number;
2305
+ /** @deprecated Use maxItems instead. Will be removed in v3.0 */
1455
2306
  maxVideos?: number;
1456
2307
  /**
1457
2308
  * Enable dynamic cache eviction (default: true)
@@ -1485,6 +2336,29 @@ interface SDKConfig {
1485
2336
  * ```
1486
2337
  */
1487
2338
  localization?: LocalizationConfig;
2339
+ /**
2340
+ * User configuration
2341
+ *
2342
+ * Provides user info for all SDK features:
2343
+ * - Analytics: User context for events
2344
+ * - Comments: Author info for posted comments
2345
+ *
2346
+ * @example
2347
+ * ```tsx
2348
+ * <ShortVideoProvider config={{
2349
+ * user: {
2350
+ * current: {
2351
+ * id: 'user-123',
2352
+ * name: 'John Doe',
2353
+ * avatar: 'https://example.com/avatar.jpg',
2354
+ * },
2355
+ * },
2356
+ * }}>
2357
+ * <App />
2358
+ * </ShortVideoProvider>
2359
+ * ```
2360
+ */
2361
+ user?: UserConfig;
1488
2362
  /**
1489
2363
  * Enable debug mode
1490
2364
  * When true, enables verbose logging
@@ -1691,15 +2565,26 @@ declare namespace ShortVideoRoot {
1691
2565
  var displayName: string;
1692
2566
  }
1693
2567
 
1694
- declare function ShortVideoProvider({ children, config, fallback, }: ShortVideoProviderProps): ReactElement;
2568
+ declare function ShortVideoProvider({ children, config }: ShortVideoProviderProps): ReactElement;
1695
2569
 
1696
2570
  /**
1697
2571
  * Feed Hooks
1698
2572
  *
1699
- * React hooks for managing video feed state and actions.
2573
+ * React hooks for managing content feed state and actions.
1700
2574
  * Provides SSR-safe subscriptions to FeedManager via useSyncExternalStore.
1701
2575
  */
1702
2576
 
2577
+ /**
2578
+ * Options for useFeed hook
2579
+ */
2580
+ interface UseFeedOptions {
2581
+ /**
2582
+ * Playlist ID to load.
2583
+ * If provided, feed will switch to Playlist mode.
2584
+ * If undefined/null, feed will switch to Recommendation mode.
2585
+ */
2586
+ playlistId?: string;
2587
+ }
1703
2588
  /**
1704
2589
  * Selector-based hook for FeedManager state
1705
2590
  *
@@ -1726,7 +2611,9 @@ declare function useFeedSelector<TSelected>(selector: (state: FeedState) => TSel
1726
2611
  * Return type for useFeed hook
1727
2612
  */
1728
2613
  interface UseFeedReturn {
1729
- /** Array of videos in display order */
2614
+ /** Array of items in display order */
2615
+ items: ContentItem[];
2616
+ /** @deprecated Use items instead. Will be removed in v3.0 */
1730
2617
  videos: VideoItem[];
1731
2618
  /** Whether initial load is in progress */
1732
2619
  loading: boolean;
@@ -1734,19 +2621,23 @@ interface UseFeedReturn {
1734
2621
  loadingMore: boolean;
1735
2622
  /** Current error, if any */
1736
2623
  error: FeedError | null;
1737
- /** Whether more videos can be loaded */
2624
+ /** Whether more items can be loaded */
1738
2625
  hasMore: boolean;
1739
2626
  /** Current pagination cursor */
1740
2627
  cursor: string | null;
1741
2628
  /** Load initial feed data */
1742
2629
  loadInitial: () => Promise<void>;
1743
- /** Load more videos (paginate) */
2630
+ /** Load more items (paginate) */
1744
2631
  loadMore: () => Promise<void>;
1745
2632
  /** Revalidate current feed data */
1746
2633
  revalidate: () => Promise<void>;
1747
- /** Find video by ID */
2634
+ /** Find item by ID */
2635
+ findItem: (id: string) => ContentItem | undefined;
2636
+ /** @deprecated Use findItem instead */
1748
2637
  findVideo: (id: string) => VideoItem | undefined;
1749
- /** Update a single video (for optimistic updates) */
2638
+ /** Update a single item (for optimistic updates) */
2639
+ updateItem: (id: string, updates: Partial<ContentItem>) => void;
2640
+ /** @deprecated Use updateItem instead */
1750
2641
  updateVideo: (id: string, updates: Partial<VideoItem>) => void;
1751
2642
  /** Check if feed data is stale */
1752
2643
  isStale: () => boolean;
@@ -1756,15 +2647,15 @@ interface UseFeedReturn {
1756
2647
  /**
1757
2648
  * Full-featured hook for Feed management
1758
2649
  *
1759
- * Returns state and methods for controlling the video feed.
2650
+ * Returns state and methods for controlling the content feed.
1760
2651
  * Includes request spam prevention for loadMore.
1761
2652
  *
1762
2653
  * @returns Feed state and actions
1763
2654
  *
1764
2655
  * @example
1765
2656
  * ```tsx
1766
- * function VideoFeed() {
1767
- * const { videos, loading, loadMore, hasMore } = useFeed();
2657
+ * function Feed({ playlistId }: { playlistId?: string }) {
2658
+ * const { items, loading, loadMore, hasMore } = useFeed({ playlistId });
1768
2659
  *
1769
2660
  * useEffect(() => {
1770
2661
  * loadInitial();
@@ -1773,8 +2664,8 @@ interface UseFeedReturn {
1773
2664
  * return (
1774
2665
  * <div>
1775
2666
  * {loading && <Spinner />}
1776
- * {videos.map(video => (
1777
- * <VideoCard key={video.id} video={video} />
2667
+ * {items.map(item => (
2668
+ * <ContentCard key={item.id} item={item} />
1778
2669
  * ))}
1779
2670
  * {hasMore && (
1780
2671
  * <button onClick={loadMore}>Load More</button>
@@ -1784,7 +2675,7 @@ interface UseFeedReturn {
1784
2675
  * }
1785
2676
  * ```
1786
2677
  */
1787
- declare function useFeed(): UseFeedReturn;
2678
+ declare function useFeed(options?: UseFeedOptions): UseFeedReturn;
1788
2679
 
1789
2680
  /**
1790
2681
  * Player Hooks
@@ -2247,11 +3138,62 @@ declare function useOptimistic(): {
2247
3138
  };
2248
3139
  type UseOptimisticReturn = ReturnType<typeof useOptimistic>;
2249
3140
 
3141
+ /**
3142
+ * UI State Store
3143
+ *
3144
+ * Simple vanilla store for shared UI state that needs to be synced
3145
+ * across multiple components (e.g., cleanMode, menuState).
3146
+ *
3147
+ * This is separate from Core managers because it's purely UI state
3148
+ * that doesn't affect playback/feed logic.
3149
+ *
3150
+ * Uses the same pattern as Zustand's createStore for compatibility
3151
+ * with React's useSyncExternalStore.
3152
+ */
3153
+ /** What triggered clean mode */
3154
+ type CleanModeTrigger = 'menu' | 'zoom' | 'gesture' | 'api' | null;
3155
+ interface UIState {
3156
+ cleanMode: boolean;
3157
+ cleanModeTrigger: CleanModeTrigger;
3158
+ isMenuOpen: boolean;
3159
+ menuVideoId: string | null;
3160
+ reportedVideoIds: Set<string>;
3161
+ dismissedReportOverlays: Set<string>;
3162
+ isPlaylistSheetOpen: boolean;
3163
+ isGestureLocked: boolean;
3164
+ overlaysVisible: boolean;
3165
+ enableAutoHide: boolean;
3166
+ autoScrollEnabled: boolean;
3167
+ }
3168
+ interface UIActions {
3169
+ enterCleanMode: (trigger: CleanModeTrigger) => void;
3170
+ exitCleanMode: () => void;
3171
+ toggleCleanMode: () => void;
3172
+ openMenu: (videoId: string) => void;
3173
+ closeMenu: () => void;
3174
+ markVideoReported: (videoId: string) => void;
3175
+ isVideoReported: (videoId: string) => boolean;
3176
+ dismissReportOverlay: (videoId: string) => void;
3177
+ isReportOverlayDismissed: (videoId: string) => boolean;
3178
+ openPlaylistSheet: () => void;
3179
+ closePlaylistSheet: () => void;
3180
+ togglePlaylistSheet: () => void;
3181
+ setGestureLock: (isLocked: boolean) => void;
3182
+ setEnableAutoHide: (enabled: boolean) => void;
3183
+ triggerInteraction: () => void;
3184
+ setAutoScrollEnabled: (enabled: boolean) => void;
3185
+ }
3186
+ type UIStore = UIState & UIActions;
3187
+ interface UIStoreApi {
3188
+ getState: () => UIStore;
3189
+ subscribe: (listener: () => void) => () => void;
3190
+ }
3191
+
2250
3192
  /**
2251
3193
  * SDK instance containing all managers
2252
3194
  */
2253
3195
  interface SDKInstance {
2254
- /** Feed manager for video list management */
3196
+ /** Feed manager for item list management */
2255
3197
  feedManager: FeedManager;
2256
3198
  /** Player engine for playback control */
2257
3199
  playerEngine: PlayerEngine;
@@ -2261,6 +3203,12 @@ interface SDKInstance {
2261
3203
  lifecycleManager: LifecycleManager;
2262
3204
  /** Optimistic manager for UI updates */
2263
3205
  optimisticManager: OptimisticManager;
3206
+ /** UI state store (clean mode, menu state, etc.) */
3207
+ uiStore: UIStoreApi;
3208
+ /** Playlist manager */
3209
+ playlistManager: PlaylistManager;
3210
+ /** Playlist collection manager */
3211
+ playlistCollectionManager: PlaylistCollectionManager;
2264
3212
  /** Adapters used by the SDK */
2265
3213
  adapters: {
2266
3214
  dataSource: IDataSource;
@@ -2271,6 +3219,8 @@ interface SDKInstance {
2271
3219
  network: INetworkAdapter;
2272
3220
  videoLoader: IVideoLoader;
2273
3221
  posterLoader: IPosterLoader;
3222
+ /** Playlist adapter (optional) */
3223
+ playlist?: IPlaylistDataSource;
2274
3224
  /** Comment adapter (optional - only if comment feature is enabled) */
2275
3225
  comment?: ICommentAdapter;
2276
3226
  };
@@ -2281,54 +3231,21 @@ interface SDKInstance {
2281
3231
  /** Guest mode config from SDKConfig */
2282
3232
  config?: GuestModeConfig;
2283
3233
  };
3234
+ /** User management */
3235
+ user: {
3236
+ /** Get current user */
3237
+ getUser: () => SDKUser | null;
3238
+ /** Set current user (updates analytics and other features) */
3239
+ setUser: (user: SDKUser | null) => void;
3240
+ /** User config from SDKConfig */
3241
+ config?: UserConfig;
3242
+ };
2284
3243
  /** Destroy all managers and cleanup resources */
2285
3244
  destroy: () => void;
2286
3245
  }
2287
3246
  declare function createSDK(config?: SDKConfig): SDKInstance;
2288
- /**
2289
- * Get or create singleton SDK instance
2290
- *
2291
- * @deprecated Use `createSDK()` with `ShortVideoProvider` instead.
2292
- * Singleton pattern causes issues with:
2293
- * - **SSR**: Instance shared between requests
2294
- * - **Testing**: State persists between tests
2295
- * - **Multiple instances**: Not supported
2296
- *
2297
- * @param config - SDK configuration (only used on first call)
2298
- * @returns Singleton SDK instance
2299
- *
2300
- * @example
2301
- * ```tsx
2302
- * // ❌ DEPRECATED - Don't use this
2303
- * const sdk = getSDK({ feed: { pageSize: 20 } });
2304
- *
2305
- * // ✅ RECOMMENDED - Use createSDK with Provider
2306
- * <ShortVideoProvider config={{ feed: { pageSize: 20 } }}>
2307
- * <App />
2308
- * </ShortVideoProvider>
2309
- * ```
2310
- */
2311
3247
  declare function getSDK(config?: SDKConfig): SDKInstance;
2312
- /**
2313
- * Destroy singleton SDK instance
2314
- *
2315
- * Call this before creating a new instance with different config,
2316
- * or when cleaning up (e.g., in tests).
2317
- */
2318
3248
  declare function destroySDK(): void;
2319
- /**
2320
- * Prefetch feed data (Standalone functionality)
2321
- *
2322
- * Allows host app to fetch data before mounting the SDK components.
2323
- * Data is stored in static in-memory cache and automatically consumed
2324
- * when SDK initializes with the same configuration.
2325
- *
2326
- * @example
2327
- * ```ts
2328
- * // In routing logic or hover handler
2329
- * await prefetchFeed(config);
2330
- * ```
2331
- */
2332
3249
  declare function prefetchFeed(config: SDKConfig, options?: {
2333
3250
  ttl?: number;
2334
3251
  }): Promise<void>;
@@ -2462,8 +3379,6 @@ interface UseCommentOptions {
2462
3379
  videoId: string;
2463
3380
  /** Auto load comments when hook mounts (default: false) */
2464
3381
  autoLoad?: boolean;
2465
- /** Current user info (required for posting) */
2466
- currentUser?: CommentAuthor;
2467
3382
  /** Config overrides */
2468
3383
  config?: Partial<CommentConfig>;
2469
3384
  }
@@ -2762,4 +3677,328 @@ interface UseGuestModeReturn {
2762
3677
  */
2763
3678
  declare function useGuestMode(guestConfigOverride?: GuestModeConfig): UseGuestModeReturn;
2764
3679
 
2765
- 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 };
3680
+ /**
3681
+ * useUser - Hook for managing current user
3682
+ *
3683
+ * Provides access to current user and ability to update user info.
3684
+ * Changes are automatically propagated to Analytics, Comments, etc.
3685
+ *
3686
+ * @example
3687
+ * ```tsx
3688
+ * function UserProfile() {
3689
+ * const { user, setUser, isLoggedIn } = useUser();
3690
+ *
3691
+ * const handleLogin = (userData) => {
3692
+ * setUser({
3693
+ * id: userData.id,
3694
+ * name: userData.name,
3695
+ * avatar: userData.avatar,
3696
+ * });
3697
+ * };
3698
+ *
3699
+ * const handleLogout = () => {
3700
+ * setUser(null);
3701
+ * };
3702
+ *
3703
+ * return (
3704
+ * <div>
3705
+ * {isLoggedIn ? (
3706
+ * <span>Welcome, {user.name}!</span>
3707
+ * ) : (
3708
+ * <span>Guest</span>
3709
+ * )}
3710
+ * </div>
3711
+ * );
3712
+ * }
3713
+ * ```
3714
+ */
3715
+
3716
+ interface UseUserReturn {
3717
+ /** Current user info (null if not logged in) */
3718
+ user: SDKUser | null;
3719
+ /** Whether user is logged in */
3720
+ isLoggedIn: boolean;
3721
+ /**
3722
+ * Set current user
3723
+ * Pass null to logout/clear user
3724
+ *
3725
+ * This will:
3726
+ * - Update analytics user context
3727
+ * - Update default author for comments
3728
+ */
3729
+ setUser: (user: SDKUser | null) => void;
3730
+ /**
3731
+ * Get user as CommentAuthor format
3732
+ * Returns anonymous user if not logged in
3733
+ */
3734
+ getCommentAuthor: () => CommentAuthor;
3735
+ }
3736
+ /**
3737
+ * Hook for managing current user
3738
+ */
3739
+ declare function useUser(): UseUserReturn;
3740
+
3741
+ /**
3742
+ * useAdvancedControls - Umbrella hook for advanced video controls
3743
+ *
3744
+ * Consolidates speed, quality, clean mode, auto-scroll, report, and menu state
3745
+ * into a single hook for simplified SDK API surface.
3746
+ *
3747
+ * @example
3748
+ * ```tsx
3749
+ * function VideoControls({ videoId }: { videoId: string }) {
3750
+ * const {
3751
+ * speed, setSpeed,
3752
+ * cleanMode, enterCleanMode, exitCleanMode,
3753
+ * isMenuOpen, openMenu, closeMenu,
3754
+ * report, notInterested,
3755
+ * } = useAdvancedControls();
3756
+ *
3757
+ * return (
3758
+ * <div>
3759
+ * <button onClick={() => setSpeed(2)}>2x</button>
3760
+ * <button onClick={openMenu}>Menu</button>
3761
+ * </div>
3762
+ * );
3763
+ * }
3764
+ * ```
3765
+ */
3766
+
3767
+ /**
3768
+ * Speed preset options
3769
+ */
3770
+ declare const SPEED_PRESETS: readonly [0.5, 0.75, 1, 1.25, 1.5, 2];
3771
+ type SpeedPreset = (typeof SPEED_PRESETS)[number];
3772
+ /**
3773
+ * Return type for useAdvancedControls hook
3774
+ */
3775
+ interface UseAdvancedControlsReturn {
3776
+ /** Current playback speed (from PlayerEngine) */
3777
+ speed: number;
3778
+ /** Set playback speed */
3779
+ setSpeed: (speed: number) => void;
3780
+ /** Available speed presets */
3781
+ speedPresets: readonly number[];
3782
+ /** Whether clean mode is active */
3783
+ cleanMode: boolean;
3784
+ /** What triggered clean mode */
3785
+ cleanModeTrigger: CleanModeTrigger;
3786
+ /** Enter clean mode */
3787
+ enterCleanMode: (trigger: CleanModeTrigger) => void;
3788
+ /** Exit clean mode */
3789
+ exitCleanMode: () => void;
3790
+ /** Toggle clean mode */
3791
+ toggleCleanMode: () => void;
3792
+ /** Whether auto-scroll is enabled */
3793
+ autoScroll: boolean;
3794
+ /** Toggle auto-scroll on/off */
3795
+ toggleAutoScroll: () => void;
3796
+ /** Set auto-scroll state */
3797
+ setAutoScroll: (enabled: boolean) => void;
3798
+ /** Current quality level (-1 = auto) */
3799
+ quality: number;
3800
+ /** Set quality level (-1 for auto) */
3801
+ setQuality: (level: number) => void;
3802
+ /** Available quality levels (from HLS.js) */
3803
+ qualityLevels: VideoQuality[];
3804
+ /** Whether quality is in auto mode */
3805
+ isAutoQuality: boolean;
3806
+ /**
3807
+ * Report content
3808
+ * @param contentId - ID of content to report
3809
+ * @param reason - Report reason code
3810
+ * @param description - Optional additional description
3811
+ */
3812
+ report: (contentId: string, reason: string, description?: string) => Promise<void>;
3813
+ /**
3814
+ * Get available report reasons
3815
+ */
3816
+ getReportReasons: () => Promise<ReportReason[]>;
3817
+ /**
3818
+ * Mark content as "not interested"
3819
+ * @param contentId - ID of content
3820
+ */
3821
+ notInterested: (contentId: string) => Promise<void>;
3822
+ /**
3823
+ * Download content (delegated to host app via callback)
3824
+ * @param content - Content item to download
3825
+ */
3826
+ download: (content: ContentItem) => Promise<void>;
3827
+ /** Whether advanced menu is open */
3828
+ isMenuOpen: boolean;
3829
+ /** Open advanced menu */
3830
+ openMenu: () => void;
3831
+ /** Close advanced menu */
3832
+ closeMenu: () => void;
3833
+ /** Toggle menu open/close */
3834
+ toggleMenu: () => void;
3835
+ /** Whether report is in progress */
3836
+ isReporting: boolean;
3837
+ /** Whether not-interested action is in progress */
3838
+ isMarkingNotInterested: boolean;
3839
+ }
3840
+ /**
3841
+ * Configuration for useAdvancedControls
3842
+ */
3843
+ interface UseAdvancedControlsConfig {
3844
+ /** Callback when download is requested (handled by host app) */
3845
+ onDownload?: (content: ContentItem) => Promise<void>;
3846
+ /** Callback when content is hidden via "not interested" */
3847
+ onContentHidden?: (contentId: string) => void;
3848
+ }
3849
+ /**
3850
+ * Advanced controls hook
3851
+ *
3852
+ * Combines multiple control features into a single hook:
3853
+ * - Speed control (uses PlayerEngine)
3854
+ * - Clean mode (local state)
3855
+ * - Auto-scroll (persisted to storage)
3856
+ * - Quality control (placeholder for HLS.js integration)
3857
+ * - Report/Not interested actions (uses IInteraction adapter)
3858
+ * - Menu state (local state)
3859
+ */
3860
+ declare function useAdvancedControls(config?: UseAdvancedControlsConfig): UseAdvancedControlsReturn;
3861
+
3862
+ /**
3863
+ * useReportedVideo - Hook to check/manage reported video state
3864
+ *
3865
+ * Provides methods to check if a video has been reported and
3866
+ * whether the overlay has been dismissed by the user.
3867
+ */
3868
+ interface UseReportedVideoReturn {
3869
+ /** Whether this video has been reported by user */
3870
+ isReported: boolean;
3871
+ /** Whether user dismissed the overlay (wants to watch anyway) */
3872
+ isOverlayDismissed: boolean;
3873
+ /** Should show the reported overlay (reported AND not dismissed) */
3874
+ shouldShowOverlay: boolean;
3875
+ /** Mark video as reported */
3876
+ markReported: () => void;
3877
+ /** Dismiss the overlay (user wants to watch) */
3878
+ dismissOverlay: () => void;
3879
+ }
3880
+ /**
3881
+ * Hook to manage reported video state for a specific video
3882
+ *
3883
+ * @param videoId - The video ID to check
3884
+ * @returns Object with reported state and actions
3885
+ */
3886
+ declare function useReportedVideo(videoId: string): UseReportedVideoReturn;
3887
+
3888
+ /**
3889
+ * useArticle - Hook for managing Article state and interactions
3890
+ *
3891
+ * Features:
3892
+ * - Article carousel navigation
3893
+ * - Music playback control
3894
+ * - Detail view state
3895
+ * - Like/unlike
3896
+ * - Share
3897
+ */
3898
+
3899
+ interface UseArticleConfig {
3900
+ /** The article data */
3901
+ article: Article;
3902
+ /** Initial image index (default: 0) */
3903
+ initialIndex?: number;
3904
+ /** Music info for this article (optional) */
3905
+ music?: MusicInfo;
3906
+ /** Whether this article is currently active (visible) */
3907
+ isActive?: boolean;
3908
+ }
3909
+ interface UseArticleReturn {
3910
+ /** Current image index in carousel */
3911
+ currentIndex: number;
3912
+ /** Set current image index */
3913
+ setCurrentIndex: (index: number) => void;
3914
+ /** Go to next image */
3915
+ next: () => void;
3916
+ /** Go to previous image */
3917
+ prev: () => void;
3918
+ /** Total number of images */
3919
+ totalImages: number;
3920
+ /** Whether can go to next image */
3921
+ hasNext: boolean;
3922
+ /** Whether can go to previous image */
3923
+ hasPrev: boolean;
3924
+ /** Whether music is playing */
3925
+ isMusicPlaying: boolean;
3926
+ /** Toggle music playback */
3927
+ toggleMusic: () => void;
3928
+ /** Play music */
3929
+ playMusic: () => void;
3930
+ /** Pause music */
3931
+ pauseMusic: () => void;
3932
+ /** Timestamp of last user music toggle (for PlayIndicator) */
3933
+ lastMusicToggleTime: number;
3934
+ /** Whether detail view is open */
3935
+ isDetailOpen: boolean;
3936
+ /** Open detail view */
3937
+ openDetail: () => void;
3938
+ /** Close detail view */
3939
+ closeDetail: () => void;
3940
+ /** Whether article is liked by current user */
3941
+ isLiked: boolean;
3942
+ /** Like the article */
3943
+ handleLike: () => Promise<void>;
3944
+ /** Unlike the article */
3945
+ handleUnlike: () => Promise<void>;
3946
+ /** Toggle like state */
3947
+ toggleLike: () => Promise<void>;
3948
+ /** Share the article */
3949
+ handleShare: () => Promise<void>;
3950
+ }
3951
+ declare function useArticle({ article, initialIndex, music, isActive, }: UseArticleConfig): UseArticleReturn;
3952
+ /** @deprecated Use useArticle instead */
3953
+ declare const useImagePost: typeof useArticle;
3954
+ /** @deprecated Use UseArticleConfig instead */
3955
+ type UseImagePostConfig = UseArticleConfig;
3956
+ /** @deprecated Use UseArticleReturn instead */
3957
+ type UseImagePostReturn = UseArticleReturn;
3958
+
3959
+ /**
3960
+ * Playlist Context Value
3961
+ */
3962
+ interface PlaylistContextValue {
3963
+ /** Current active playlist ID */
3964
+ playlistId: string | null;
3965
+ /** List of items in the playlist */
3966
+ items: ContentItem[];
3967
+ /** Current active item index */
3968
+ currentIndex: number;
3969
+ /** Loading status */
3970
+ status: 'idle' | 'loading' | 'error';
3971
+ /** Error information */
3972
+ error: Error | null;
3973
+ /** Playlist metadata */
3974
+ metadata: {
3975
+ title: string;
3976
+ description?: string;
3977
+ cover?: string;
3978
+ totalItems: number;
3979
+ } | null;
3980
+ /** Load a playlist by ID */
3981
+ loadPlaylist: (id: string) => Promise<void>;
3982
+ /** Set playlist data directly */
3983
+ setPlaylist: (playlist: PlaylistData) => void;
3984
+ /** Go to next item */
3985
+ next: () => void;
3986
+ /** Go to previous item */
3987
+ prev: () => void;
3988
+ /** Jump to a specific index */
3989
+ jumpTo: (index: number) => void;
3990
+ /** Reset store state */
3991
+ reset: () => void;
3992
+ }
3993
+ /**
3994
+ * PlaylistProvider - Connects PlaylistManager to React Context
3995
+ */
3996
+ declare function PlaylistProvider({ children }: {
3997
+ children: ReactNode;
3998
+ }): react_jsx_runtime.JSX.Element;
3999
+ /**
4000
+ * Hook to access Playlist state and actions
4001
+ */
4002
+ declare function usePlaylist(): PlaylistContextValue;
4003
+
4004
+ export { ActionBar, type ActionBarIconSet, type ActionBarProps as ActionBarWiredProps, type AdaptersConfig, AdvanceMenu, type AdvanceMenuProps, AdvanceMenuWired, type AdvanceMenuWiredProps, ArticleSlot, type ArticleSlotWiredProps, AuthorInfo, type AuthorInfoProps as AuthorInfoWiredProps, CleanModeOverlay as CleanModeOverlayWired, type CleanModeOverlayProps as CleanModeOverlayWiredProps, type CleanModeTrigger, CommentSheet, type CommentSheetProps, type ComposerContext, DEFAULT_LOCALE, DefaultArticleSlot, type DefaultArticleSlotProps, DefaultImagePostSlot, type DefaultImagePostSlotProps, DefaultVideoSlot as DefaultSlot, type DefaultVideoSlotProps as DefaultSlotProps, type DragAxis, type DragBind, type DragConfig, type DragHandler, type DragState, Feed, type FeedProps, type GuestAction, type GuestActionContext, type GuestModeConfig, type HookReturn, ImagePostSlot, type ImagePostSlotWiredProps, LocalizationAdapter, LocalizationContext, LocalizationProvider, type LocalizationProviderProps, PlaylistBar, PlaylistCollection, type PlaylistCollectionProps, type PlaylistContextValue, PlaylistProvider, PlaylistSheet, ProgressBar, type ProgressBarProps, ReportSheet, type ReportSheetProps, ReportSheetWired, type ReportSheetWiredProps, type SDKConfig, type SDKInstance, SDKPlayerError, type SDKUser, SPEED_PRESETS, SUPPORTED_LOCALES, ShortVideoProvider, type ShortVideoProviderProps, ShortVideoRoot, type ShortVideoRootProps, SlotComposer, type SlotComposerProps, type SpeedPreset, type SupportedLocale, type SwipeConfig, type SwipeDirection, type SwipeState, type TranslateFn, type UseAdvancedControlsConfig, type UseAdvancedControlsReturn, type UseArticleConfig, type UseArticleReturn, type UseCommentOptions, type UseCommentReturn, type UseFeedReturn, type UseGuestModeReturn, type UseImagePostConfig, type UseImagePostReturn, type UseLifecycleOptions, type UseLifecycleReturn, type UseOptimisticReturn, type UsePlayerCoreReturn, type UsePlayerForVideoReturn, type UsePlayerReturn, type UseReportedVideoReturn, type UseResourceAllocationReturn, type UseResourceReturn, type UseSwipeGestureReturn, type UseTranslationReturn, type UseUserReturn, type UseZoomGestureConfig, type UseZoomGestureReturn, type UserConfig, type VideoElementHandlers, VideoFeed, type VideoFeedProps, VideoInfo, type VideoInfoWiredProps, VideoPlayer, type VideoPlayerProps, VideoSlot, type VideoSlotWiredProps, type WireConfig, type ZoomGestureHandlers, createSDK, createSimpleWireConfig, createWiredComponent, destroySDK, enMessages, getMessages, getSDK, isLocaleSupported, messageCatalogs, parseMessage, prefetchFeed, resetCommentManager, useAdvancedControls, useArticle, useComment, useFeed, useFeedSelector, useGuestMode, useImagePost, useLifecycle, useLifecycleSelector, useLocalization, useOptimistic, useOptimisticSelector, useOptionalLocalization, useOptionalTranslation, usePlayer, usePlayerForVideo, usePlayerSelector, usePlaylist, useReportedVideo, useResource, useResourceAllocation, useResourceSelector, useSDK, useSwipeGesture, useTouchDrag, useTranslation, useUser, useZoomGesture, viMessages };