@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.
- package/dist/index.d.ts +1402 -163
- package/dist/index.js +4071 -1409
- 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,
|
|
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
|
|
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
|
-
*
|
|
147
|
-
* Required - ActionBar needs
|
|
146
|
+
* Content item (Video or Article) to get interaction state for
|
|
147
|
+
* Required - ActionBar needs data for likes/comments/shares
|
|
148
148
|
*/
|
|
149
|
-
|
|
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?: (
|
|
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,
|
|
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,
|
|
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
|
-
*
|
|
223
|
-
* Required - AuthorInfo needs
|
|
226
|
+
* Content item (Video or Article) to get author from
|
|
227
|
+
* Required - AuthorInfo needs data for author + follow state
|
|
224
228
|
*/
|
|
225
|
-
|
|
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,
|
|
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
|
|
785
|
+
* Wired Feed Component
|
|
704
786
|
*
|
|
705
787
|
* Pre-wired version of VideoFeedHeadless that auto-injects SDK hooks.
|
|
706
|
-
*
|
|
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
|
-
* -
|
|
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
|
|
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 {
|
|
806
|
+
* import { Feed, isVideoItem, isArticle } from '@xhub-short/sdk';
|
|
723
807
|
*
|
|
724
808
|
* function App() {
|
|
725
809
|
* return (
|
|
726
810
|
* <ShortVideoProvider>
|
|
727
|
-
* <
|
|
728
|
-
* renderSlot={(
|
|
729
|
-
*
|
|
730
|
-
*
|
|
731
|
-
* <
|
|
732
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
851
|
+
* feedState and swipeState are auto-injected by SDK hooks.
|
|
746
852
|
* You can still override them if needed.
|
|
747
853
|
*/
|
|
748
|
-
interface
|
|
749
|
-
/**
|
|
854
|
+
interface FeedProps {
|
|
855
|
+
/**
|
|
856
|
+
* Container height (default: 100vh via CSS)
|
|
857
|
+
*
|
|
858
|
+
* @default 100vh
|
|
859
|
+
*/
|
|
750
860
|
height?: number | string;
|
|
751
|
-
/**
|
|
861
|
+
/**
|
|
862
|
+
* Additional CSS classes
|
|
863
|
+
* @default ''
|
|
864
|
+
*/
|
|
752
865
|
className?: string;
|
|
753
|
-
/**
|
|
754
|
-
|
|
755
|
-
|
|
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
|
-
/**
|
|
904
|
+
/**
|
|
905
|
+
* Called when reaching near end of feed
|
|
906
|
+
* @returns The React node to render
|
|
907
|
+
*/
|
|
758
908
|
onEndReached?: () => void;
|
|
759
|
-
/**
|
|
909
|
+
/**
|
|
910
|
+
* Threshold for triggering onEndReached
|
|
911
|
+
* @default 2
|
|
912
|
+
*/
|
|
760
913
|
endReachedThreshold?: number;
|
|
761
|
-
/**
|
|
914
|
+
/**
|
|
915
|
+
* Number of slots to render before/after active
|
|
916
|
+
* @default 1
|
|
917
|
+
*/
|
|
762
918
|
bufferSize?: number;
|
|
763
|
-
/**
|
|
919
|
+
/**
|
|
920
|
+
* Loading text
|
|
921
|
+
* @default 'Loading...'
|
|
922
|
+
*/
|
|
764
923
|
loadingText?: string;
|
|
765
|
-
/**
|
|
924
|
+
/**
|
|
925
|
+
* Empty text
|
|
926
|
+
* @default 'No videos'
|
|
927
|
+
*/
|
|
766
928
|
emptyText?: string;
|
|
767
|
-
/**
|
|
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
|
|
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
|
|
855
|
-
declare namespace
|
|
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
|
-
*
|
|
1111
|
+
* VideoInfo wired component props
|
|
879
1112
|
*/
|
|
880
|
-
interface
|
|
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, }:
|
|
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
|
-
|
|
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
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
onLikeToggle?: (
|
|
1205
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1220
|
-
renderVideoInfo?: (props: VideoInfoWiredProps) => ReactNode;
|
|
1221
|
-
/** Custom ProgressBar renderer */
|
|
1686
|
+
renderVideoInfo?: (props: VideoInfoProps) => ReactNode;
|
|
1222
1687
|
renderProgressBar?: (props: ProgressBarProps) => ReactNode;
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
2568
|
+
declare function ShortVideoProvider({ children, config }: ShortVideoProviderProps): ReactElement;
|
|
1695
2569
|
|
|
1696
2570
|
/**
|
|
1697
2571
|
* Feed Hooks
|
|
1698
2572
|
*
|
|
1699
|
-
* React hooks for managing
|
|
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
|
|
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
|
|
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
|
|
2630
|
+
/** Load more items (paginate) */
|
|
1744
2631
|
loadMore: () => Promise<void>;
|
|
1745
2632
|
/** Revalidate current feed data */
|
|
1746
2633
|
revalidate: () => Promise<void>;
|
|
1747
|
-
/** Find
|
|
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
|
|
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
|
|
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
|
|
1767
|
-
* const {
|
|
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
|
-
* {
|
|
1777
|
-
* <
|
|
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
|
|
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
|
-
|
|
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 };
|