@xhub-short/ui 0.1.0-beta.0 → 0.1.0-beta.2
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/CommentSheet.css-DR3Wcn0F.d.ts +207 -0
- package/dist/{chunk-WKX2WBVO.js → chunk-3XPJHUYL.js} +1 -39
- package/dist/{chunk-YW23IBKF.js → chunk-5U3NZZGG.js} +45 -4
- package/dist/{chunk-UECU42WC.js → chunk-6LKRB7CM.js} +30 -15
- package/dist/{chunk-MMTAPG2C.js → chunk-ANCP53F3.js} +10 -4
- package/dist/chunk-DHQJBXQW.js +562 -0
- package/dist/chunk-EDWS2IPH.js +1 -0
- package/dist/chunk-GGQNSM6R.js +2016 -0
- package/dist/{chunk-OXY5JHVJ.js → chunk-JDNPQHFE.js} +28 -13
- package/dist/{chunk-ZZDQKP4R.js → chunk-KGMGUOLY.js} +93 -154
- package/dist/{chunk-4MN72OZH.js → chunk-N62QNEY5.js} +3 -3
- package/dist/chunk-NIFL42PC.js +740 -0
- package/dist/chunk-RE62D5GG.js +430 -0
- package/dist/{chunk-QKQUXR3H.js → chunk-WLJCY7W3.js} +258 -57
- package/dist/components/ActionBar/index.d.ts +1 -1
- package/dist/components/ActionBar/index.js +1 -1
- package/dist/components/AuthorInfo/index.d.ts +278 -0
- package/dist/components/AuthorInfo/index.js +1 -0
- package/dist/components/CommentSheet/index.d.ts +12 -0
- package/dist/components/CommentSheet/index.js +1 -0
- package/dist/components/ProgressBar/index.d.ts +30 -2
- package/dist/components/ProgressBar/index.js +1 -1
- package/dist/components/Skeleton/index.js +1 -1
- package/dist/components/VideoFeed/index.d.ts +11 -0
- package/dist/components/VideoFeed/index.js +1 -1
- package/dist/components/VideoInfo/index.d.ts +160 -0
- package/dist/components/VideoInfo/index.js +1 -0
- package/dist/components/VideoPlayer/index.d.ts +35 -41
- package/dist/components/VideoPlayer/index.js +1 -1
- package/dist/components/VideoSlot/index.d.ts +124 -64
- package/dist/components/VideoSlot/index.js +1 -1
- package/dist/components/VirtualSlider/index.d.ts +339 -0
- package/dist/components/VirtualSlider/index.js +1 -0
- package/dist/components/icons/index.d.ts +3 -1
- package/dist/components/icons/index.js +1 -1
- package/dist/index.d.ts +294 -98
- package/dist/index.js +437 -12
- package/package.json +51 -7
- package/dist/use-gesture-react.esm-3SV4QLEJ.js +0 -1893
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import react__default, { ReactElement, ReactNode } from 'react';
|
|
3
|
+
import { CommentItem, UICommentState, UICommentActions, CommentConfig } from '@xhub-short/contracts';
|
|
4
|
+
|
|
5
|
+
interface CommentInputProps {
|
|
6
|
+
/** Placeholder text */
|
|
7
|
+
placeholder?: string;
|
|
8
|
+
/** Quick emojis */
|
|
9
|
+
emojis?: string[];
|
|
10
|
+
/** Max input length */
|
|
11
|
+
maxLength?: number;
|
|
12
|
+
/** Custom class */
|
|
13
|
+
className?: string;
|
|
14
|
+
/** On submit callback */
|
|
15
|
+
onSubmitSuccess?: () => void;
|
|
16
|
+
/** On media button click */
|
|
17
|
+
onMediaClick?: () => void;
|
|
18
|
+
/** Reply to text (default: "Replying to") */
|
|
19
|
+
replyingToText?: string;
|
|
20
|
+
/** Reply placeholder template (default: "Reply to @{name}...") - {name} will be replaced */
|
|
21
|
+
replyPlaceholderTemplate?: string;
|
|
22
|
+
/** Cancel reply aria-label (default: "Cancel reply") */
|
|
23
|
+
cancelReplyAriaLabel?: string;
|
|
24
|
+
/** Add media aria-label (default: "Add media") */
|
|
25
|
+
addMediaAriaLabel?: string;
|
|
26
|
+
/** Submit comment aria-label (default: "Submit comment") */
|
|
27
|
+
submitAriaLabel?: string;
|
|
28
|
+
/** Open emoji aria-label (default: "Open emoji") */
|
|
29
|
+
emojiAriaLabel?: string;
|
|
30
|
+
/** Emoji button aria-label template (default: "Add {emoji}") */
|
|
31
|
+
addEmojiAriaLabel?: string;
|
|
32
|
+
}
|
|
33
|
+
declare const CommentInput: react.NamedExoticComponent<CommentInputProps>;
|
|
34
|
+
|
|
35
|
+
interface CommentItemProps {
|
|
36
|
+
comment: CommentItem;
|
|
37
|
+
className?: string;
|
|
38
|
+
}
|
|
39
|
+
declare const CommentItemComponent: react.NamedExoticComponent<CommentItemProps>;
|
|
40
|
+
|
|
41
|
+
interface CommentListProps {
|
|
42
|
+
/** Custom empty state */
|
|
43
|
+
emptyState?: ReactElement;
|
|
44
|
+
/** Custom loading state */
|
|
45
|
+
loadingState?: ReactElement;
|
|
46
|
+
/** Custom error state */
|
|
47
|
+
errorState?: (error: Error, retry: () => void) => ReactElement;
|
|
48
|
+
/** Custom class */
|
|
49
|
+
className?: string;
|
|
50
|
+
/** Error text (default: "Failed to load comments") */
|
|
51
|
+
errorText?: string;
|
|
52
|
+
/** Retry button text (default: "Try again") */
|
|
53
|
+
retryText?: string;
|
|
54
|
+
/** Empty state text (default: "No comments yet. Be the first!") */
|
|
55
|
+
emptyText?: string;
|
|
56
|
+
/** Load more button text (default: "Load more comments") */
|
|
57
|
+
loadMoreText?: string;
|
|
58
|
+
}
|
|
59
|
+
declare const CommentList: react.NamedExoticComponent<CommentListProps>;
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* i18n strings for CommentSheet internal components
|
|
63
|
+
*/
|
|
64
|
+
interface CommentSheetI18n {
|
|
65
|
+
/** Text for "See more" button (default: "See more") */
|
|
66
|
+
expandText?: string;
|
|
67
|
+
/** Text for "See less" button (default: "See less") */
|
|
68
|
+
collapseText?: string;
|
|
69
|
+
/** Text for view replies - use {count} placeholder (default: "View {count} more replies") */
|
|
70
|
+
viewRepliesText?: string;
|
|
71
|
+
/** Text for hide replies (default: "Hide replies") */
|
|
72
|
+
hideRepliesText?: string;
|
|
73
|
+
/** Text for load replies (default: "Load replies") */
|
|
74
|
+
loadRepliesText?: string;
|
|
75
|
+
/** Text for view more replies (default: "View more replies") */
|
|
76
|
+
viewMoreRepliesText?: string;
|
|
77
|
+
/** Function to format relative time */
|
|
78
|
+
formatRelativeTime?: (dateStr: string) => string;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* CommentSheet context value
|
|
82
|
+
*/
|
|
83
|
+
interface CommentSheetContextValue {
|
|
84
|
+
/** Comment state */
|
|
85
|
+
state: UICommentState;
|
|
86
|
+
/** Comment actions */
|
|
87
|
+
actions: UICommentActions;
|
|
88
|
+
/** Video ID */
|
|
89
|
+
videoId: string;
|
|
90
|
+
/** Config */
|
|
91
|
+
config: CommentConfig;
|
|
92
|
+
/** Whether sheet is open */
|
|
93
|
+
isOpen: boolean;
|
|
94
|
+
/** Close sheet */
|
|
95
|
+
onClose: () => void;
|
|
96
|
+
/** Reply target (when replying to a comment) */
|
|
97
|
+
replyTarget: ReplyTarget | null;
|
|
98
|
+
/** Set reply target */
|
|
99
|
+
setReplyTarget: (target: ReplyTarget | null) => void;
|
|
100
|
+
/** Initial count from video data (used before API loads) */
|
|
101
|
+
initialCount?: number;
|
|
102
|
+
/** i18n strings for internal components */
|
|
103
|
+
i18n: CommentSheetI18n;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Reply target info
|
|
107
|
+
*/
|
|
108
|
+
interface ReplyTarget {
|
|
109
|
+
/** Parent comment ID */
|
|
110
|
+
commentId: string;
|
|
111
|
+
/** Author name for @mention */
|
|
112
|
+
authorName: string;
|
|
113
|
+
/** Author ID */
|
|
114
|
+
authorId: string;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* CommentSheet context
|
|
118
|
+
*/
|
|
119
|
+
declare const CommentSheetContext: react.Context<CommentSheetContextValue | undefined>;
|
|
120
|
+
/**
|
|
121
|
+
* Hook to use CommentSheet context
|
|
122
|
+
* @throws if used outside of CommentSheetHeadless
|
|
123
|
+
*/
|
|
124
|
+
declare function useCommentSheetContext(): CommentSheetContextValue;
|
|
125
|
+
/**
|
|
126
|
+
* Hook to optionally use CommentSheet context
|
|
127
|
+
* @returns context or undefined if not within CommentSheetHeadless
|
|
128
|
+
*/
|
|
129
|
+
declare function useOptionalCommentSheetContext(): CommentSheetContextValue | undefined;
|
|
130
|
+
|
|
131
|
+
interface SheetHeaderProps {
|
|
132
|
+
/** Custom title label (default: "Comments") */
|
|
133
|
+
titleLabel?: string;
|
|
134
|
+
/** Show drag handle */
|
|
135
|
+
showHandle?: boolean;
|
|
136
|
+
/** Show sort button */
|
|
137
|
+
showSort?: boolean;
|
|
138
|
+
/** Sort click handler */
|
|
139
|
+
onSortClick?: () => void;
|
|
140
|
+
/** Custom close icon */
|
|
141
|
+
closeIcon?: ReactElement;
|
|
142
|
+
/** Custom class */
|
|
143
|
+
className?: string;
|
|
144
|
+
/** Sort button aria-label (default: "Sort comments") */
|
|
145
|
+
sortAriaLabel?: string;
|
|
146
|
+
/** Close button aria-label (default: "Close comments") */
|
|
147
|
+
closeAriaLabel?: string;
|
|
148
|
+
}
|
|
149
|
+
declare const SheetHeader: react__default.NamedExoticComponent<SheetHeaderProps>;
|
|
150
|
+
|
|
151
|
+
interface CommentSheetHeadlessProps {
|
|
152
|
+
/** Whether sheet is open */
|
|
153
|
+
isOpen: boolean;
|
|
154
|
+
/** Close callback */
|
|
155
|
+
onClose: () => void;
|
|
156
|
+
/** Video ID for comments */
|
|
157
|
+
videoId: string;
|
|
158
|
+
/** Comment state from SDK */
|
|
159
|
+
state: UICommentState;
|
|
160
|
+
/** Comment actions from SDK */
|
|
161
|
+
actions: UICommentActions;
|
|
162
|
+
/** Config */
|
|
163
|
+
config?: Partial<CommentConfig>;
|
|
164
|
+
/** Initial count from video data (displayed before API loads) */
|
|
165
|
+
initialCount?: number;
|
|
166
|
+
/** Custom children (compound pattern) */
|
|
167
|
+
children?: ReactNode;
|
|
168
|
+
/** Root class name */
|
|
169
|
+
className?: string;
|
|
170
|
+
/** Backdrop class name */
|
|
171
|
+
backdropClassName?: string;
|
|
172
|
+
/** Close on backdrop click */
|
|
173
|
+
closeOnBackdropClick?: boolean;
|
|
174
|
+
/** Close on escape key */
|
|
175
|
+
closeOnEscape?: boolean;
|
|
176
|
+
/** Enable drag-to-dismiss */
|
|
177
|
+
enableDragToDismiss?: boolean;
|
|
178
|
+
/** Drag threshold to close (px) */
|
|
179
|
+
dragCloseThreshold?: number;
|
|
180
|
+
/** i18n strings for internal components (CommentItem, etc.) */
|
|
181
|
+
i18n?: CommentSheetI18n;
|
|
182
|
+
}
|
|
183
|
+
declare const CommentSheetHeadless: react.NamedExoticComponent<CommentSheetHeadlessProps>;
|
|
184
|
+
declare const CommentSheet: react.NamedExoticComponent<CommentSheetHeadlessProps> & {
|
|
185
|
+
Header: react.NamedExoticComponent<SheetHeaderProps>;
|
|
186
|
+
List: react.NamedExoticComponent<CommentListProps>;
|
|
187
|
+
Input: react.NamedExoticComponent<CommentInputProps>;
|
|
188
|
+
Item: react.NamedExoticComponent<CommentItemProps>;
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* CommentSheet CSS
|
|
193
|
+
*
|
|
194
|
+
* Modern bottom sheet for comments (Light Theme)
|
|
195
|
+
* Based on Figma design: https://figma.com/design/Kd1lJUJ4B3Kuw3dV9UcUok
|
|
196
|
+
* Features:
|
|
197
|
+
* - Light theme with clean aesthetics
|
|
198
|
+
* - Slide-up animation
|
|
199
|
+
* - Backdrop with click-to-close
|
|
200
|
+
* - Keyboard-aware input positioning
|
|
201
|
+
* - Scrollable comment list
|
|
202
|
+
* - Pinned comment support
|
|
203
|
+
* - Vertical reply thread lines
|
|
204
|
+
*/
|
|
205
|
+
declare const COMMENT_SHEET_CSS = "\n/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n CSS VARIABLES (Light Theme)\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n:root {\n /* Primary colors */\n --sv-comment-primary: #164d8e;\n --sv-comment-primary-light: #1354ae;\n --sv-comment-primary-dark: #003477;\n \n /* Contrast colors */\n --sv-comment-bg: #ffffff;\n --sv-comment-text: #121212;\n --sv-comment-text-secondary: #6b7271;\n --sv-comment-border: rgba(18, 18, 18, 0.08);\n \n /* Accent colors */\n --sv-comment-like-color: #ff434e;\n --sv-comment-verified-color: #1ea031;\n --sv-comment-mention-color: #164d8e;\n \n /* Component specific */\n --sv-comment-avatar-bg: #e5e6e6;\n --sv-comment-input-border: #a3a3a3;\n --sv-comment-reply-line: #e5e6e6;\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n BACKDROP & CONTAINER\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.sv-comment-sheet-backdrop {\n position: fixed;\n inset: 0;\n background: var(--sv-comment-backdrop-bg, rgba(0, 0, 0, 0.5));\n z-index: var(--sv-comment-sheet-z-index, 1000);\n opacity: 0;\n visibility: hidden;\n pointer-events: none;\n transition: opacity var(--sv-comment-animation-duration, 400ms) ease,\n visibility 0s linear var(--sv-comment-animation-duration, 400ms);\n}\n\n.sv-comment-sheet-backdrop--open {\n opacity: 1;\n visibility: visible;\n pointer-events: auto;\n transition: opacity var(--sv-comment-animation-duration, 400ms) ease,\n visibility 0s linear 0s;\n}\n\n/* Keyframes for slide animations */\n@keyframes sv-sheet-slide-up {\n from { transform: translateY(100%); }\n to { transform: translateY(0); }\n}\n\n@keyframes sv-sheet-slide-down {\n from { transform: translateY(0); }\n to { transform: translateY(100%); }\n}\n\n.sv-comment-sheet {\n position: fixed;\n margin: 16px;\n left: 0;\n right: 0;\n bottom: 0;\n background: var(--sv-comment-bg, #ffffff);\n border-radius: var(--sv-comment-sheet-radius, 24px);\n z-index: var(--sv-comment-sheet-z-index, 1001);\n display: flex;\n flex-direction: column;\n max-height: var(--sv-comment-sheet-height, 55vh);\n transform: translateY(100%);\n overflow: hidden;\n touch-action: pan-y;\n isolation: isolate;\n pointer-events: none;\n will-change: transform;\n}\n\n.sv-comment-sheet--open {\n transform: translateY(0);\n pointer-events: auto;\n animation: sv-sheet-slide-up var(--sv-comment-animation-duration, 400ms) \n var(--sv-comment-animation-easing, cubic-bezier(0.32, 0.72, 0, 1)) forwards;\n}\n\n.sv-comment-sheet--open.sv-comment-sheet--closing {\n pointer-events: none;\n animation: sv-sheet-slide-down var(--sv-comment-animation-duration, 400ms) \n var(--sv-comment-animation-easing, cubic-bezier(0.32, 0.72, 0, 1)) forwards !important;\n}\n\n/* CRITICAL: Disable VirtualSlider/VideoFeed swipe when CommentSheet is open */\nbody.sv-comment-sheet-open .sv-slider,\nbody.sv-comment-sheet-open .sv-video-feed {\n pointer-events: none !important;\n touch-action: none !important;\n}\n\nbody.sv-comment-sheet-open .sv-comment-sheet,\nbody.sv-comment-sheet-open .sv-comment-sheet-backdrop {\n touch-action: auto !important;\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n HEADER\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.sv-comment-sheet__header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px;\n border-bottom: 1px solid var(--sv-comment-border);\n flex-shrink: 0;\n position: relative;\n cursor: grab;\n touch-action: none;\n}\n\n.sv-comment-sheet__header:active {\n cursor: grabbing;\n}\n\n.sv-comment-sheet__header-handle {\n position: absolute;\n top: 8px;\n left: 50%;\n transform: translateX(-50%);\n width: 36px;\n height: 4px;\n background: var(--sv-comment-text-secondary);\n border-radius: 2px;\n opacity: 0.3;\n}\n\n.sv-comment-sheet__header-left {\n display: flex;\n align-items: center;\n gap: 2px;\n}\n\n.sv-comment-sheet__title {\n font-family: 'SF Pro Display', -apple-system, BlinkMacSystemFont, sans-serif;\n font-size: 18px;\n font-weight: 600;\n line-height: 1.4;\n color: var(--sv-comment-text);\n opacity: 0.9;\n margin: 0;\n}\n\n.sv-comment-sheet__sort-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n background: none;\n border: none;\n padding: 0;\n cursor: pointer;\n color: var(--sv-comment-text);\n}\n\n.sv-comment-sheet__sort-btn svg {\n width: 20px;\n height: 20px;\n}\n\n.sv-comment-sheet__close-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 36px;\n height: 36px;\n border: none;\n border-radius: 100px;\n background: linear-gradient(180deg, var(--sv-comment-primary-light) 0%, var(--sv-comment-primary-dark) 100%);\n cursor: pointer;\n transition: opacity 0.15s ease;\n}\n\n.sv-comment-sheet__close-btn:hover {\n opacity: 0.9;\n}\n\n.sv-comment-sheet__close-btn svg {\n width: 20px;\n height: 20px;\n color: #ffffff;\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n COMMENT LIST\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.sv-comment-sheet__list {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n padding: 8px 16px 28px 16px;\n -webkit-overflow-scrolling: touch;\n overscroll-behavior: contain;\n touch-action: pan-y;\n}\n\n.sv-comment-sheet__list::-webkit-scrollbar {\n width: 0px;\n}\n\n.sv-comment-sheet__list::-webkit-scrollbar-thumb {\n background: rgba(0, 0, 0, 0.0);\n border-radius: 0px;\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n COMMENT ITEM\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.sv-comment-item {\n display: flex;\n gap: 6px;\n padding: 16px 0;\n position: relative;\n}\n\n.sv-comment-item--pending {\n opacity: 0.6;\n}\n\n.sv-comment-item--pinned {\n background: var(--sv-comment-bg);\n}\n\n.sv-comment-item__avatar {\n width: 40px;\n height: 40px;\n border-radius: 120px;\n flex-shrink: 0;\n object-fit: cover;\n background: var(--sv-comment-avatar-bg);\n}\n\n.sv-comment-item__content {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n\n.sv-comment-item__header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 4px;\n}\n\n.sv-comment-item__header-left {\n display: flex;\n align-items: center;\n gap: 4px;\n min-width: 0;\n}\n\n.sv-comment-item__pin-icon {\n width: 16px;\n height: 16px;\n flex-shrink: 0;\n color: var(--sv-comment-primary);\n}\n\n.sv-comment-item__author {\n font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;\n font-size: 14px;\n font-weight: 600;\n line-height: 1.4;\n color: var(--sv-comment-text);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.sv-comment-item__verified {\n width: 12px;\n height: 12px;\n flex-shrink: 0;\n color: var(--sv-comment-verified-color);\n}\n\n.sv-comment-item__badge {\n font-size: 10px;\n padding: 2px 6px;\n background: var(--sv-comment-primary);\n color: #ffffff;\n border-radius: 4px;\n flex-shrink: 0;\n}\n\n.sv-comment-item__menu-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n background: none;\n border: none;\n padding: 0;\n cursor: pointer;\n color: var(--sv-comment-text-secondary);\n}\n\n.sv-comment-item__menu-btn svg {\n width: 20px;\n height: 20px;\n}\n\n.sv-comment-item__text {\n font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;\n font-size: 12px;\n font-weight: 400;\n line-height: 1.4;\n color: var(--sv-comment-text);\n word-break: break-word;\n margin: 0;\n padding-right: 16px;\n}\n\n/* Text collapse */\n.sv-comment-item__text--collapsed {\n display: -webkit-box;\n -webkit-line-clamp: var(--sv-comment-max-lines, 3);\n -webkit-box-orient: vertical;\n overflow: hidden;\n}\n\n.sv-comment-item__expand-btn {\n background: none;\n border: none;\n padding: 0;\n font-size: 12px;\n color: var(--sv-comment-text-secondary);\n cursor: pointer;\n margin-top: 4px;\n}\n\n.sv-comment-item__expand-btn:hover {\n color: var(--sv-comment-text);\n}\n\n/* Actions row */\n.sv-comment-item__actions {\n display: flex;\n align-items: center;\n gap: 16px;\n}\n\n.sv-comment-item__time {\n font-family: 'SF Pro Display', -apple-system, BlinkMacSystemFont, sans-serif;\n font-size: 12px;\n font-weight: 500;\n line-height: 1.2;\n color: var(--sv-comment-text-secondary);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.sv-comment-item__action-btn {\n display: flex;\n align-items: center;\n gap: 4px;\n background: none;\n border: none;\n padding: 0;\n font-family: 'SF Pro Display', -apple-system, BlinkMacSystemFont, sans-serif;\n font-size: 12px;\n font-weight: 500;\n line-height: 1.2;\n color: var(--sv-comment-text-secondary);\n cursor: pointer;\n transition: color 0.15s ease;\n}\n\n.sv-comment-item__action-btn:hover {\n color: var(--sv-comment-text);\n}\n\n.sv-comment-item__action-btn--active {\n color: var(--sv-comment-like-color);\n}\n\n.sv-comment-item__action-btn--active:hover {\n color: var(--sv-comment-like-color);\n}\n\n.sv-comment-item__action-icon {\n width: 20px;\n height: 20px;\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n REPLIES\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.sv-comment-replies {\n margin-top: 12px;\n position: relative;\n}\n\n/* Vertical connecting line */\n.sv-comment-item--has-replies::before {\n content: '';\n position: absolute;\n left: 20px;\n top: 56px;\n bottom: 0;\n width: 1px;\n background: var(--sv-comment-reply-line);\n}\n\n.sv-comment-replies__toggle {\n display: flex;\n align-items: center;\n gap: 0;\n background: none;\n border: none;\n padding: 4px 0;\n cursor: pointer;\n}\n\n.sv-comment-replies__toggle-line {\n width: 24px;\n height: 1px;\n background: #a3a3a3;\n margin-right: 0;\n}\n\n.sv-comment-replies__toggle-text {\n font-family: 'SF Pro Display', -apple-system, BlinkMacSystemFont, sans-serif;\n font-size: 13px;\n font-weight: 600;\n line-height: 1.4;\n color: var(--sv-comment-text-secondary);\n white-space: nowrap;\n}\n\n.sv-comment-replies__toggle-icon {\n width: 20px;\n height: 20px;\n color: var(--sv-comment-text-secondary);\n}\n\n.sv-comment-replies__list {\n margin-top: 12px;\n}\n\n.sv-comment-reply {\n display: flex;\n gap: 6px;\n padding: 0 0 12px 0;\n position: relative;\n}\n\n.sv-comment-reply__avatar {\n width: 24px;\n height: 24px;\n border-radius: 100px;\n flex-shrink: 0;\n object-fit: cover;\n background: var(--sv-comment-avatar-bg);\n}\n\n.sv-comment-reply__mention {\n color: var(--sv-comment-mention-color);\n font-weight: 500;\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n INPUT AREA\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.sv-comment-sheet__input-area {\n padding: 0 16px 36px 16px;\n flex-shrink: 0;\n}\n\n.sv-comment-sheet__reply-to {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 4px 0;\n margin-bottom: 8px;\n font-size: 12px;\n color: var(--sv-comment-text-secondary);\n}\n\n.sv-comment-sheet__reply-to-author-name {\n font-size: 12px;\n color: var(--sv-comment-text);\n font-weight: 500;\n}\n\n.sv-comment-sheet__reply-to-clear {\n background: none;\n border: none;\n padding: 4px;\n color: var(--sv-comment-text-secondary);\n cursor: pointer;\n font-size: 12px;\n}\n\n.sv-comment-sheet__input-wrapper {\n display: flex;\n align-items: center;\n gap: 8px;\n height: 44px;\n padding: 16px;\n background: var(--sv-comment-bg);\n border: 1px solid var(--sv-comment-input-border);\n border-radius: 12px;\n backdrop-filter: blur(50px);\n}\n\n.sv-comment-sheet__input-left {\n display: flex;\n align-items: center;\n gap: 8px;\n flex: 1;\n min-width: 0;\n}\n\n.sv-comment-sheet__media-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n background: none;\n border: none;\n padding: 0;\n cursor: pointer;\n flex-shrink: 0;\n}\n\n.sv-comment-sheet__media-btn svg {\n width: 20px;\n height: 20px;\n}\n\n.sv-comment-sheet__input {\n flex: 1;\n background: none;\n border: none;\n outline: none;\n resize: none;\n font-family: 'SF Pro Display', -apple-system, BlinkMacSystemFont, sans-serif;\n font-size: 12px;\n font-style: italic;\n font-weight: 400;\n line-height: 1.4;\n color: var(--sv-comment-text);\n padding: 0;\n min-width: 0;\n}\n\n.sv-comment-sheet__input::placeholder {\n color: var(--sv-comment-text-secondary);\n}\n\n.sv-comment-sheet__input:not(:placeholder-shown) {\n font-style: normal;\n}\n\n.sv-comment-sheet__emoji-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n background: none;\n border: none;\n padding: 0;\n cursor: pointer;\n flex-shrink: 0;\n}\n\n.sv-comment-sheet__emoji-btn svg {\n width: 20px;\n height: 20px;\n color: var(--sv-comment-primary);\n}\n\n/* Hidden emoji bar (can be toggled) */\n.sv-comment-sheet__emoji-bar {\n display: none;\n gap: 8px;\n padding: 8px 0;\n overflow-x: auto;\n -webkit-overflow-scrolling: touch;\n}\n\n.sv-comment-sheet__emoji-bar--visible {\n display: flex;\n}\n\n.sv-comment-sheet__emoji-bar::-webkit-scrollbar {\n display: none;\n}\n\n.sv-comment-sheet__emoji-bar-btn {\n background: none;\n border: none;\n padding: 4px;\n font-size: 20px;\n cursor: pointer;\n border-radius: 4px;\n transition: background 0.15s ease;\n}\n\n.sv-comment-sheet__emoji-bar-btn:hover {\n background: rgba(0, 0, 0, 0.05);\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n STATES\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.sv-comment-sheet__loading {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 32px;\n color: var(--sv-comment-text-secondary);\n}\n\n.sv-comment-sheet__loading-spinner {\n width: 24px;\n height: 24px;\n border: 2px solid rgba(0, 0, 0, 0.1);\n border-top-color: var(--sv-comment-primary);\n border-radius: 50%;\n animation: sv-comment-spin 0.8s linear infinite;\n}\n\n@keyframes sv-comment-spin {\n to { transform: rotate(360deg); }\n}\n\n.sv-comment-sheet__empty {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 32px;\n text-align: center;\n}\n\n.sv-comment-sheet__empty-icon {\n font-size: 48px;\n margin-bottom: 12px;\n}\n\n.sv-comment-sheet__empty-text {\n color: var(--sv-comment-text-secondary);\n font-size: 14px;\n}\n\n.sv-comment-sheet__error {\n display: flex;\n flex-direction: column;\n align-items: center;\n padding: 32px;\n text-align: center;\n color: var(--sv-comment-like-color);\n}\n\n.sv-comment-sheet__error-btn {\n margin-top: 12px;\n padding: 8px 16px;\n background: rgba(0, 0, 0, 0.05);\n border: none;\n border-radius: 8px;\n color: var(--sv-comment-text);\n cursor: pointer;\n}\n\n/* Load more */\n.sv-comment-sheet__load-more {\n display: flex;\n justify-content: center;\n padding: 12px;\n}\n\n.sv-comment-sheet__load-more-btn {\n background: none;\n border: none;\n padding: 8px 16px;\n color: var(--sv-comment-text-secondary);\n cursor: pointer;\n font-size: 13px;\n}\n\n.sv-comment-sheet__load-more-btn:hover {\n color: var(--sv-comment-text);\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n DELETE CONFIRMATION\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.sv-comment-delete-confirm {\n position: fixed;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n background: rgba(0, 0, 0, 0.5);\n z-index: var(--sv-comment-modal-z-index, 1100);\n}\n\n.sv-comment-delete-confirm__dialog {\n background: var(--sv-comment-bg);\n border-radius: 12px;\n padding: 16px;\n max-width: 280px;\n text-align: center;\n}\n\n.sv-comment-delete-confirm__title {\n font-size: 16px;\n font-weight: 600;\n color: var(--sv-comment-text);\n margin-bottom: 8px;\n}\n\n.sv-comment-delete-confirm__text {\n font-size: 14px;\n color: var(--sv-comment-text-secondary);\n margin-bottom: 16px;\n}\n\n.sv-comment-delete-confirm__actions {\n display: flex;\n gap: 8px;\n}\n\n.sv-comment-delete-confirm__btn {\n flex: 1;\n padding: 8px 12px;\n border: none;\n border-radius: 8px;\n font-size: 14px;\n font-weight: 600;\n cursor: pointer;\n}\n\n.sv-comment-delete-confirm__btn--cancel {\n background: rgba(0, 0, 0, 0.05);\n color: var(--sv-comment-text);\n}\n\n.sv-comment-delete-confirm__btn--delete {\n background: var(--sv-comment-like-color);\n color: #ffffff;\n}\n\n/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n SKELETON LOADING\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n@keyframes sv-skeleton-shimmer {\n 0% { background-position: -200% 0; }\n 100% { background-position: 200% 0; }\n}\n\n.sv-comment-skeleton-list {\n display: flex;\n flex-direction: column;\n}\n\n.sv-comment-skeleton {\n animation: sv-skeleton-fade-in 0.3s ease;\n}\n\n@keyframes sv-skeleton-fade-in {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n.sv-comment-skeleton__avatar {\n width: 40px;\n height: 40px;\n border-radius: 50%;\n background: linear-gradient(\n 90deg,\n rgba(0, 0, 0, 0.04) 25%,\n rgba(0, 0, 0, 0.08) 50%,\n rgba(0, 0, 0, 0.04) 75%\n );\n background-size: 200% 100%;\n animation: sv-skeleton-shimmer 1.5s ease-in-out infinite;\n}\n\n.sv-comment-skeleton__content {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.sv-comment-skeleton__header {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.sv-comment-skeleton__author {\n width: 80px;\n height: 14px;\n border-radius: 4px;\n background: linear-gradient(\n 90deg,\n rgba(0, 0, 0, 0.04) 25%,\n rgba(0, 0, 0, 0.08) 50%,\n rgba(0, 0, 0, 0.04) 75%\n );\n background-size: 200% 100%;\n animation: sv-skeleton-shimmer 1.5s ease-in-out infinite;\n animation-delay: 0.1s;\n}\n\n.sv-comment-skeleton__time {\n width: 40px;\n height: 12px;\n border-radius: 4px;\n background: linear-gradient(\n 90deg,\n rgba(0, 0, 0, 0.04) 25%,\n rgba(0, 0, 0, 0.08) 50%,\n rgba(0, 0, 0, 0.04) 75%\n );\n background-size: 200% 100%;\n animation: sv-skeleton-shimmer 1.5s ease-in-out infinite;\n animation-delay: 0.15s;\n}\n\n.sv-comment-skeleton__text {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.sv-comment-skeleton__line {\n height: 14px;\n border-radius: 4px;\n background: linear-gradient(\n 90deg,\n rgba(0, 0, 0, 0.04) 25%,\n rgba(0, 0, 0, 0.08) 50%,\n rgba(0, 0, 0, 0.04) 75%\n );\n background-size: 200% 100%;\n animation: sv-skeleton-shimmer 1.5s ease-in-out infinite;\n}\n\n.sv-comment-skeleton__line--full {\n width: 100%;\n animation-delay: 0.2s;\n}\n\n.sv-comment-skeleton__line--medium {\n width: 65%;\n animation-delay: 0.25s;\n}\n\n.sv-comment-skeleton__actions {\n display: flex;\n align-items: center;\n gap: 16px;\n margin-top: 4px;\n}\n\n.sv-comment-skeleton__action {\n width: 50px;\n height: 12px;\n border-radius: 4px;\n background: linear-gradient(\n 90deg,\n rgba(0, 0, 0, 0.04) 25%,\n rgba(0, 0, 0, 0.08) 50%,\n rgba(0, 0, 0, 0.04) 75%\n );\n background-size: 200% 100%;\n animation: sv-skeleton-shimmer 1.5s ease-in-out infinite;\n animation-delay: 0.3s;\n}\n";
|
|
206
|
+
|
|
207
|
+
export { CommentSheet as C, type ReplyTarget as R, SheetHeader as S, CommentSheetHeadless as a, type CommentSheetHeadlessProps as b, type SheetHeaderProps as c, CommentList as d, type CommentListProps as e, CommentInput as f, type CommentInputProps as g, CommentItemComponent as h, type CommentItemProps as i, CommentSheetContext as j, useOptionalCommentSheetContext as k, type CommentSheetContextValue as l, type CommentSheetI18n as m, COMMENT_SHEET_CSS as n, useCommentSheetContext as u };
|
|
@@ -1,30 +1,3 @@
|
|
|
1
|
-
// src/utils/lazyGesture.ts
|
|
2
|
-
var gestureModule = null;
|
|
3
|
-
var loadPromise = null;
|
|
4
|
-
async function loadGesture() {
|
|
5
|
-
if (gestureModule) {
|
|
6
|
-
return gestureModule;
|
|
7
|
-
}
|
|
8
|
-
if (loadPromise) {
|
|
9
|
-
return loadPromise;
|
|
10
|
-
}
|
|
11
|
-
loadPromise = import('./use-gesture-react.esm-3SV4QLEJ.js').then((mod) => {
|
|
12
|
-
gestureModule = mod;
|
|
13
|
-
return mod;
|
|
14
|
-
}).catch((error) => {
|
|
15
|
-
loadPromise = null;
|
|
16
|
-
throw error;
|
|
17
|
-
});
|
|
18
|
-
return loadPromise;
|
|
19
|
-
}
|
|
20
|
-
function isGestureLoaded() {
|
|
21
|
-
return gestureModule !== null;
|
|
22
|
-
}
|
|
23
|
-
function preloadGesture() {
|
|
24
|
-
loadGesture().catch(() => {
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
|
-
|
|
28
1
|
// src/utils/formatCount.ts
|
|
29
2
|
var DEFAULT_SUFFIXES = {
|
|
30
3
|
thousand: "K",
|
|
@@ -83,16 +56,5 @@ function parseFormattedCount(formatted) {
|
|
|
83
56
|
return num;
|
|
84
57
|
}
|
|
85
58
|
}
|
|
86
|
-
function cn(...inputs) {
|
|
87
|
-
return inputs.filter(Boolean).map((input) => {
|
|
88
|
-
if (typeof input === "string") {
|
|
89
|
-
return input;
|
|
90
|
-
}
|
|
91
|
-
if (typeof input === "object" && input !== null) {
|
|
92
|
-
return Object.entries(input).filter(([, value]) => value).map(([key]) => key).join(" ");
|
|
93
|
-
}
|
|
94
|
-
return "";
|
|
95
|
-
}).join(" ").trim();
|
|
96
|
-
}
|
|
97
59
|
|
|
98
|
-
export {
|
|
60
|
+
export { formatCount, formatCountWithSeparators, parseFormattedCount };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { clsx2 } from './chunk-EDWS2IPH.js';
|
|
2
2
|
import { injectComponentCSS } from './chunk-UXMA4KJZ.js';
|
|
3
|
-
import { useInsertionEffect, useMemo, useEffect, useCallback, useRef, useState } from 'react';
|
|
3
|
+
import { memo, useInsertionEffect, useMemo, useEffect, useCallback, useRef, useState } from 'react';
|
|
4
4
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
5
5
|
|
|
6
6
|
// src/components/ProgressBar/ProgressBar.css.ts
|
|
@@ -244,6 +244,40 @@ var PROGRESS_BAR_CSS = `
|
|
|
244
244
|
display: none;
|
|
245
245
|
}
|
|
246
246
|
|
|
247
|
+
/* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
248
|
+
* Auto-hide Variant
|
|
249
|
+
* Shows progress bar only when video is paused or user is seeking/hovering
|
|
250
|
+
* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
|
|
251
|
+
|
|
252
|
+
.sv-progress-bar--auto-hide {
|
|
253
|
+
/* Smooth transition for show/hide */
|
|
254
|
+
transition: opacity 0.3s ease, visibility 0.3s ease, transform 0.3s ease;
|
|
255
|
+
opacity: 1;
|
|
256
|
+
visibility: visible;
|
|
257
|
+
transform: translateY(0);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
.sv-progress-bar--auto-hide.sv-progress-bar--hidden {
|
|
261
|
+
opacity: 0;
|
|
262
|
+
visibility: hidden;
|
|
263
|
+
transform: translateY(8px);
|
|
264
|
+
pointer-events: none;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/* Show on hover even when auto-hide is enabled */
|
|
268
|
+
.sv-progress-bar--auto-hide:hover {
|
|
269
|
+
opacity: 1;
|
|
270
|
+
visibility: visible;
|
|
271
|
+
transform: translateY(0);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/* Always show when seeking */
|
|
275
|
+
.sv-progress-bar--auto-hide.sv-progress-bar--seeking {
|
|
276
|
+
opacity: 1;
|
|
277
|
+
visibility: visible;
|
|
278
|
+
transform: translateY(0);
|
|
279
|
+
}
|
|
280
|
+
|
|
247
281
|
/* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
248
282
|
* Reduced Motion (Accessibility)
|
|
249
283
|
* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
|
|
@@ -379,7 +413,7 @@ function useSeekHandlers({
|
|
|
379
413
|
handlePointerLeave
|
|
380
414
|
};
|
|
381
415
|
}
|
|
382
|
-
function
|
|
416
|
+
function ProgressBarHeadlessBase({
|
|
383
417
|
currentTime,
|
|
384
418
|
duration,
|
|
385
419
|
buffered = 0,
|
|
@@ -391,6 +425,8 @@ function ProgressBarHeadless({
|
|
|
391
425
|
showTime = false,
|
|
392
426
|
showTooltip,
|
|
393
427
|
minimal = false,
|
|
428
|
+
autoHide = true,
|
|
429
|
+
visible,
|
|
394
430
|
fillRef: externalFillRef,
|
|
395
431
|
bufferedRef: externalBufferedRef,
|
|
396
432
|
handleRef: externalHandleRef,
|
|
@@ -440,14 +476,17 @@ function ProgressBarHeadless({
|
|
|
440
476
|
const stopBubble = useCallback((e) => {
|
|
441
477
|
e.stopPropagation();
|
|
442
478
|
}, []);
|
|
479
|
+
const isHidden = visible !== void 0 ? !visible : autoHide && !isSeeking && hoverTime === null;
|
|
443
480
|
return /* @__PURE__ */ jsxs(
|
|
444
481
|
"div",
|
|
445
482
|
{
|
|
446
|
-
className:
|
|
483
|
+
className: clsx2(
|
|
447
484
|
CSS_PREFIX,
|
|
448
485
|
!isSeekable && `${CSS_PREFIX}--disabled`,
|
|
449
486
|
isSeeking && `${CSS_PREFIX}--seeking`,
|
|
450
487
|
minimal && `${CSS_PREFIX}--minimal`,
|
|
488
|
+
autoHide && `${CSS_PREFIX}--auto-hide`,
|
|
489
|
+
isHidden && `${CSS_PREFIX}--hidden`,
|
|
451
490
|
className
|
|
452
491
|
),
|
|
453
492
|
onClick: stopBubble,
|
|
@@ -526,5 +565,7 @@ function ProgressBarHeadless({
|
|
|
526
565
|
}
|
|
527
566
|
);
|
|
528
567
|
}
|
|
568
|
+
var ProgressBarHeadless = memo(ProgressBarHeadlessBase);
|
|
569
|
+
ProgressBarHeadless.displayName = "ProgressBarHeadless";
|
|
529
570
|
|
|
530
571
|
export { PROGRESS_BAR_CSS, ProgressBarHeadless, calculateProgress, formatTime };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { clsx2 } from './chunk-EDWS2IPH.js';
|
|
2
2
|
import { injectComponentCSS } from './chunk-UXMA4KJZ.js';
|
|
3
|
-
import {
|
|
3
|
+
import { memo, useInsertionEffect, useCallback, useMemo, useRef, useState, useEffect } from 'react';
|
|
4
4
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
5
5
|
|
|
6
6
|
// src/components/VideoPlayer/VideoPlayer.css.ts
|
|
@@ -35,6 +35,7 @@ var VIDEO_PLAYER_CSS = (
|
|
|
35
35
|
align-items: center;
|
|
36
36
|
justify-content: center;
|
|
37
37
|
z-index: var(--sv-player-video-z);
|
|
38
|
+
background: var(--sv-bg-primary, #0ff);
|
|
38
39
|
}
|
|
39
40
|
|
|
40
41
|
/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550
|
|
@@ -601,17 +602,21 @@ function supportsNativeHLS() {
|
|
|
601
602
|
function isHlsErrorData(d) {
|
|
602
603
|
return typeof d === "object" && d !== null && "fatal" in d;
|
|
603
604
|
}
|
|
604
|
-
async function setupHlsSource(video, src, hlsRef, onHlsError) {
|
|
605
|
+
async function setupHlsSource(video, src, hlsRef, onHlsError, startTime) {
|
|
605
606
|
if (supportsNativeHLS()) {
|
|
606
|
-
video.src = src;
|
|
607
|
+
video.src = startTime && startTime > 0 ? `${src}#t=${startTime}` : src;
|
|
607
608
|
return;
|
|
608
609
|
}
|
|
609
610
|
const Hls = await loadHls();
|
|
610
611
|
if (!Hls?.isSupported?.()) {
|
|
611
|
-
video.src = src;
|
|
612
|
+
video.src = startTime && startTime > 0 ? `${src}#t=${startTime}` : src;
|
|
612
613
|
return;
|
|
613
614
|
}
|
|
614
|
-
const
|
|
615
|
+
const hlsConfig = {};
|
|
616
|
+
if (startTime && startTime > 0) {
|
|
617
|
+
hlsConfig.startPosition = startTime;
|
|
618
|
+
}
|
|
619
|
+
const hls = new Hls.default(hlsConfig);
|
|
615
620
|
hlsRef.current = hls;
|
|
616
621
|
hls.loadSource(src);
|
|
617
622
|
hls.attachMedia(video);
|
|
@@ -633,6 +638,7 @@ function useVideoElement(config) {
|
|
|
633
638
|
loop = true,
|
|
634
639
|
muted = true,
|
|
635
640
|
volume = 1,
|
|
641
|
+
startTime,
|
|
636
642
|
onCanPlay,
|
|
637
643
|
onPlay,
|
|
638
644
|
onPlaying,
|
|
@@ -678,13 +684,19 @@ function useVideoElement(config) {
|
|
|
678
684
|
const setupSource = async () => {
|
|
679
685
|
try {
|
|
680
686
|
if (type === "hls") {
|
|
681
|
-
await setupHlsSource(
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
687
|
+
await setupHlsSource(
|
|
688
|
+
video,
|
|
689
|
+
src,
|
|
690
|
+
hlsRef,
|
|
691
|
+
(hlsError) => {
|
|
692
|
+
setError(hlsError);
|
|
693
|
+
setIsLoading(false);
|
|
694
|
+
onError?.(hlsError);
|
|
695
|
+
},
|
|
696
|
+
startTime
|
|
697
|
+
);
|
|
686
698
|
} else {
|
|
687
|
-
video.src = src;
|
|
699
|
+
video.src = startTime && startTime > 0 ? `${src}#t=${startTime}` : src;
|
|
688
700
|
}
|
|
689
701
|
video.loop = loop;
|
|
690
702
|
video.muted = muted;
|
|
@@ -708,7 +720,7 @@ function useVideoElement(config) {
|
|
|
708
720
|
hlsRef.current = null;
|
|
709
721
|
}
|
|
710
722
|
};
|
|
711
|
-
}, [src, type, loop, muted, volume, onError, retryTrigger]);
|
|
723
|
+
}, [src, type, loop, muted, volume, startTime, onError, retryTrigger]);
|
|
712
724
|
useEffect(() => {
|
|
713
725
|
const video = videoRef.current;
|
|
714
726
|
if (!video) return;
|
|
@@ -909,7 +921,7 @@ function getMediaErrorMessage(code) {
|
|
|
909
921
|
return "Unknown video error";
|
|
910
922
|
}
|
|
911
923
|
}
|
|
912
|
-
function
|
|
924
|
+
function VideoPlayerHeadlessBase({
|
|
913
925
|
src,
|
|
914
926
|
type,
|
|
915
927
|
poster,
|
|
@@ -917,6 +929,7 @@ function VideoPlayerHeadless({
|
|
|
917
929
|
loop = true,
|
|
918
930
|
muted = true,
|
|
919
931
|
volume = 1,
|
|
932
|
+
startTime,
|
|
920
933
|
className,
|
|
921
934
|
videoRef: externalVideoRef,
|
|
922
935
|
videoId,
|
|
@@ -947,6 +960,7 @@ function VideoPlayerHeadless({
|
|
|
947
960
|
loop,
|
|
948
961
|
muted,
|
|
949
962
|
volume,
|
|
963
|
+
startTime,
|
|
950
964
|
onCanPlay,
|
|
951
965
|
onPlay,
|
|
952
966
|
onPlaying,
|
|
@@ -1008,7 +1022,7 @@ function VideoPlayerHeadless({
|
|
|
1008
1022
|
return /* @__PURE__ */ jsxs(
|
|
1009
1023
|
"div",
|
|
1010
1024
|
{
|
|
1011
|
-
className:
|
|
1025
|
+
className: clsx2(PLAYER_CLASS, stateClasses, className),
|
|
1012
1026
|
...{ [VIDEO_TYPE_ATTR]: type },
|
|
1013
1027
|
...{ [PLAYBACK_STATE_ATTR]: playbackState },
|
|
1014
1028
|
style: {
|
|
@@ -1105,6 +1119,7 @@ function getUserFriendlyErrorMessage(message) {
|
|
|
1105
1119
|
}
|
|
1106
1120
|
return "Failed to load video. Please try again.";
|
|
1107
1121
|
}
|
|
1122
|
+
var VideoPlayerHeadless = memo(VideoPlayerHeadlessBase);
|
|
1108
1123
|
VideoPlayerHeadless.displayName = "VideoPlayerHeadless";
|
|
1109
1124
|
|
|
1110
1125
|
export { BUFFERING_STATE_CLASS, DEFAULT_OBJECT_FIT, DEFAULT_PRELOAD, ENDED_CLASS, ERROR_CLASS, ERROR_STATE_CLASS, FIRST_FRAME_MAX_WIDTH, FIRST_FRAME_QUALITY, LOADING_CLASS, LOADING_STATE_ATTR, LOADING_STATE_CLASS, PAUSED_CLASS, PLAYBACK_STATE_ATTR, PLAYER_CLASS, PLAYING_CLASS, POSTER_CLASS, READY_CLASS, VIDEO_CLASS, VIDEO_PLAYER_CSS, VIDEO_TYPE_ATTR, VIDEO_WRAPPER_CLASS, VideoElementError, VideoPlayerHeadless, Z_INDEX, Z_INDEX_CSS_VARS, createFirstFrameCache, firstFrameCache, useAutoFirstFrameCapture, useFirstFrameCapture, useVideoElement };
|
|
@@ -110,10 +110,10 @@ function BookmarkFilledIcon(props) {
|
|
|
110
110
|
) });
|
|
111
111
|
}
|
|
112
112
|
function PlayIcon(props) {
|
|
113
|
-
return /* @__PURE__ */ jsx("svg", {
|
|
113
|
+
return /* @__PURE__ */ jsx("svg", { "aria-hidden": "true", xmlns: "http://www.w3.org/2000/svg", fill: "none", ...getIconProps(props), children: /* @__PURE__ */ jsx(
|
|
114
114
|
"path",
|
|
115
115
|
{
|
|
116
|
-
d: "
|
|
116
|
+
d: "M9.92196 2.01322C7.19974 0.436195 3.79175 2.40044 3.79175 5.54647V22.4486C3.79175 25.5946 7.19974 27.5588 9.92195 25.9818L24.5099 17.5308C27.2252 15.9578 27.2252 12.0373 24.5099 10.4643L9.92196 2.01322Z",
|
|
117
117
|
fill: "currentColor"
|
|
118
118
|
}
|
|
119
119
|
) });
|
|
@@ -122,7 +122,7 @@ function PauseIcon(props) {
|
|
|
122
122
|
return /* @__PURE__ */ jsx("svg", { ...getIconProps(props), "aria-hidden": "true", children: /* @__PURE__ */ jsx(
|
|
123
123
|
"path",
|
|
124
124
|
{
|
|
125
|
-
d: "
|
|
125
|
+
d: "M24.2096 4.20016V23.8002C24.2096 24.5422 24.2096 24.9902 23.9879 25.4265C23.7907 25.8138 23.4816 26.123 23.0954 26.319C22.6591 26.5407 22.2111 26.5407 21.4679 26.5407H19.3679C18.6259 26.5407 18.1767 26.5407 17.7404 26.319C17.3542 26.123 17.0451 25.8138 16.8479 25.4265C16.6251 24.989 16.6251 24.541 16.6251 23.799V4.20016C16.6251 3.45816 16.6251 3.01016 16.8467 2.57383C17.0439 2.1865 17.3531 1.87733 17.7393 1.68133C18.1756 1.4585 18.6236 1.4585 19.3667 1.4585H21.4667C22.2099 1.4585 22.6579 1.4585 23.0954 1.68133C23.4804 1.87733 23.7896 2.1865 23.9867 2.57266C24.2096 3.01016 24.2096 3.45816 24.2096 4.20016ZM10.2621 1.68133C9.82458 1.4585 9.37658 1.4585 8.63342 1.4585H6.53341C5.79025 1.4585 5.34225 1.4585 4.90591 1.68133C4.51858 1.8785 4.20941 2.18766 4.01341 2.57383C3.79175 3.01016 3.79175 3.45816 3.79175 4.20016V23.8002C3.79175 24.5422 3.79175 24.9902 4.01341 25.4253C4.21058 25.8127 4.51975 26.1218 4.90708 26.319C5.34341 26.5407 5.79141 26.5407 6.53458 26.5407H8.63458C9.37658 26.5407 9.82575 26.5407 10.2621 26.319C10.6482 26.123 10.9574 25.8138 11.1546 25.4265C11.3762 24.9902 11.3762 24.5422 11.3762 23.8002V4.20016C11.3762 3.45816 11.3762 3.01016 11.1534 2.57266C10.9562 2.18533 10.6471 1.87733 10.2621 1.68133Z",
|
|
126
126
|
fill: "currentColor"
|
|
127
127
|
}
|
|
128
128
|
) });
|
|
@@ -197,5 +197,11 @@ function VerifiedIcon(props) {
|
|
|
197
197
|
)
|
|
198
198
|
] });
|
|
199
199
|
}
|
|
200
|
+
function PlusIcon(props) {
|
|
201
|
+
return /* @__PURE__ */ jsxs("svg", { ...getIconProps({ ...props, fill: "none", stroke: "currentColor" }), "aria-hidden": "true", children: [
|
|
202
|
+
/* @__PURE__ */ jsx("line", { x1: "12", y1: "5", x2: "12", y2: "19", strokeWidth: "2.5", strokeLinecap: "round" }),
|
|
203
|
+
/* @__PURE__ */ jsx("line", { x1: "5", y1: "12", x2: "19", y2: "12", strokeWidth: "2.5", strokeLinecap: "round" })
|
|
204
|
+
] });
|
|
205
|
+
}
|
|
200
206
|
|
|
201
|
-
export { BookmarkFilledIcon, BookmarkIcon, CloseIcon, CommentIcon, HeartFilledIcon, HeartIcon, MoreIcon, MusicIcon, PauseIcon, PlayIcon, ShareIcon, UserCheckIcon, UserPlusIcon, VerifiedIcon, VolumeIcon, VolumeMutedIcon };
|
|
207
|
+
export { BookmarkFilledIcon, BookmarkIcon, CloseIcon, CommentIcon, HeartFilledIcon, HeartIcon, MoreIcon, MusicIcon, PauseIcon, PlayIcon, PlusIcon, ShareIcon, UserCheckIcon, UserPlusIcon, VerifiedIcon, VolumeIcon, VolumeMutedIcon };
|