@xhub-short/ui 0.1.0-beta.1 → 0.1.0-beta.11
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-DyEc3Sro.d.ts +217 -0
- package/dist/VideoSlotPlayIndicator-DPs8Xt5C.d.ts +51 -0
- package/dist/chunk-3OB3OVYR.js +349 -0
- package/dist/{chunk-WKX2WBVO.js → chunk-3XPJHUYL.js} +1 -39
- package/dist/chunk-4RIMQOBR.js +58 -0
- package/dist/chunk-4TUBNA2X.js +180 -0
- package/dist/{chunk-4YDIRPIN.js → chunk-ANCP53F3.js} +3 -3
- package/dist/{chunk-UXMA4KJZ.js → chunk-CAWE42LH.js} +5 -3
- package/dist/{chunk-ANGBSV7L.js → chunk-CIIZ3IHV.js} +10 -5
- package/dist/chunk-DR7KR7OT.js +103 -0
- package/dist/chunk-DXLCQ4FH.js +102 -0
- package/dist/chunk-EDWS2IPH.js +1 -0
- package/dist/chunk-FR7UQSZP.js +570 -0
- package/dist/chunk-IWSBYOSS.js +91 -0
- package/dist/chunk-JEY6R4KJ.js +334 -0
- package/dist/chunk-KMJ3PQ7M.js +1262 -0
- package/dist/chunk-MFJS65C5.js +368 -0
- package/dist/{chunk-HW4LXTFT.js → chunk-OM4L7RE5.js} +18 -6
- package/dist/chunk-PBIH2F2Q.js +344 -0
- package/dist/chunk-PJ4NMVMY.js +326 -0
- package/dist/chunk-Q6MG7AVG.js +531 -0
- package/dist/chunk-QCKVF2DR.js +713 -0
- package/dist/chunk-QCRRF76W.js +75 -0
- package/dist/chunk-QUEJHA24.js +508 -0
- package/dist/chunk-VXW7AOGM.js +285 -0
- package/dist/chunk-YB7AXTX7.js +430 -0
- package/dist/chunk-ZGWSJ6Z5.js +601 -0
- package/dist/components/ActionBar/index.js +1 -1
- package/dist/components/AdvanceMenu/index.d.ts +78 -0
- package/dist/components/AdvanceMenu/index.js +1 -0
- package/dist/components/AuthorInfo/index.d.ts +5 -1
- package/dist/components/AuthorInfo/index.js +1 -1
- package/dist/components/BottomSheet/index.d.ts +82 -0
- package/dist/components/BottomSheet/index.js +1 -0
- package/dist/components/CleanModeOverlay/index.d.ts +60 -0
- package/dist/components/CleanModeOverlay/index.js +1 -0
- package/dist/components/CommentSheet/index.d.ts +164 -0
- package/dist/components/CommentSheet/index.js +1 -0
- package/dist/components/DetailView/index.d.ts +311 -0
- package/dist/components/DetailView/index.js +1 -0
- package/dist/components/ErrorBoundary/index.js +1 -1
- package/dist/components/ImageCarousel/index.d.ts +50 -0
- package/dist/components/ImageCarousel/index.js +1 -0
- package/dist/components/ImagePostSlot/index.d.ts +207 -0
- package/dist/components/ImagePostSlot/index.js +1 -0
- package/dist/components/ProgressBar/index.d.ts +30 -2
- package/dist/components/ProgressBar/index.js +1 -1
- package/dist/components/QualityPicker/index.d.ts +35 -0
- package/dist/components/QualityPicker/index.js +1 -0
- package/dist/components/ReportSheet/index.d.ts +68 -0
- package/dist/components/ReportSheet/index.js +1 -0
- package/dist/components/Skeleton/index.js +1 -1
- package/dist/components/SpeedPicker/index.d.ts +32 -0
- package/dist/components/SpeedPicker/index.js +1 -0
- package/dist/components/VideoFeed/index.d.ts +12 -1
- package/dist/components/VideoFeed/index.js +1 -1
- package/dist/components/VideoInfo/index.d.ts +4 -2
- package/dist/components/VideoInfo/index.js +1 -1
- package/dist/components/VideoPlayer/index.d.ts +14 -41
- package/dist/components/VideoPlayer/index.js +1 -1
- package/dist/components/VideoSlot/index.d.ts +84 -65
- package/dist/components/VideoSlot/index.js +2 -1
- package/dist/components/VirtualSlider/index.d.ts +339 -0
- package/dist/components/VirtualSlider/index.js +1 -0
- package/dist/components/icons/index.js +1 -1
- package/dist/index.d.ts +107 -95
- package/dist/index.js +84 -27
- package/package.json +51 -7
- package/dist/chunk-2PTMP65P.js +0 -738
- package/dist/chunk-4MN72OZH.js +0 -148
- package/dist/chunk-DHQJBXQW.js +0 -562
- package/dist/chunk-SSJDO24Q.js +0 -204
- package/dist/chunk-XAOEHLOX.js +0 -1326
- package/dist/chunk-YW23IBKF.js +0 -530
- package/dist/chunk-ZZDQKP4R.js +0 -418
- package/dist/use-gesture-react.esm-3SV4QLEJ.js +0 -1893
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ReactNode, ReactElement } from 'react';
|
|
3
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
4
|
+
import { ImagePost, MusicInfo } from '@xhub-short/contracts';
|
|
5
|
+
|
|
6
|
+
interface DetailViewContextValue {
|
|
7
|
+
/** The image post data */
|
|
8
|
+
imagePost: ImagePost;
|
|
9
|
+
/** Current image index */
|
|
10
|
+
currentImageIndex: number;
|
|
11
|
+
/** Set current image index */
|
|
12
|
+
setCurrentImageIndex: (index: number) => void;
|
|
13
|
+
/** Close detail view */
|
|
14
|
+
close: () => void;
|
|
15
|
+
/** Whether view is animating */
|
|
16
|
+
isAnimating: boolean;
|
|
17
|
+
/** Actions */
|
|
18
|
+
actions: {
|
|
19
|
+
onLike?: () => void;
|
|
20
|
+
onComment?: () => void;
|
|
21
|
+
onShare?: () => void;
|
|
22
|
+
onBookmark?: () => void;
|
|
23
|
+
onFollow?: () => void;
|
|
24
|
+
};
|
|
25
|
+
/** States */
|
|
26
|
+
states: {
|
|
27
|
+
isLiked: boolean;
|
|
28
|
+
isBookmarked: boolean;
|
|
29
|
+
isFollowing: boolean;
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Hook to access DetailView context
|
|
34
|
+
* @throws if used outside DetailViewHeadless
|
|
35
|
+
*/
|
|
36
|
+
declare function useDetailViewContext(): DetailViewContextValue;
|
|
37
|
+
declare function BackIcon(): react_jsx_runtime.JSX.Element;
|
|
38
|
+
declare function HeartIcon({ filled }: {
|
|
39
|
+
filled?: boolean;
|
|
40
|
+
}): react_jsx_runtime.JSX.Element;
|
|
41
|
+
declare function CommentIcon(): react_jsx_runtime.JSX.Element;
|
|
42
|
+
declare function BookmarkIcon({ filled }: {
|
|
43
|
+
filled?: boolean;
|
|
44
|
+
}): react_jsx_runtime.JSX.Element;
|
|
45
|
+
declare function ShareIcon(): react_jsx_runtime.JSX.Element;
|
|
46
|
+
interface DetailViewHeadlessProps {
|
|
47
|
+
/** Whether the detail view is open */
|
|
48
|
+
isOpen: boolean;
|
|
49
|
+
/** Close handler */
|
|
50
|
+
onClose: () => void;
|
|
51
|
+
/** The image post to display */
|
|
52
|
+
imagePost: ImagePost;
|
|
53
|
+
/** Initial image index */
|
|
54
|
+
initialImageIndex?: number;
|
|
55
|
+
/** Animation duration in ms */
|
|
56
|
+
animationDuration?: number;
|
|
57
|
+
/** Enable swipe down to close */
|
|
58
|
+
enableSwipeToClose?: boolean;
|
|
59
|
+
/** Swipe threshold (percentage) to trigger close */
|
|
60
|
+
swipeCloseThreshold?: number;
|
|
61
|
+
/** Custom header title (fallback if no author) */
|
|
62
|
+
headerTitle?: string;
|
|
63
|
+
/** Show drag indicator */
|
|
64
|
+
showDragIndicator?: boolean;
|
|
65
|
+
/** Whether post is liked */
|
|
66
|
+
isLiked?: boolean;
|
|
67
|
+
/** Whether post is bookmarked */
|
|
68
|
+
isBookmarked?: boolean;
|
|
69
|
+
/** Whether following author */
|
|
70
|
+
isFollowing?: boolean;
|
|
71
|
+
/** Like button handler */
|
|
72
|
+
onLike?: () => void;
|
|
73
|
+
/** Comment button handler */
|
|
74
|
+
onComment?: () => void;
|
|
75
|
+
/** Share button handler */
|
|
76
|
+
onShare?: () => void;
|
|
77
|
+
/** Bookmark button handler */
|
|
78
|
+
onBookmark?: () => void;
|
|
79
|
+
/** Follow button handler */
|
|
80
|
+
onFollow?: () => void;
|
|
81
|
+
/**
|
|
82
|
+
* Custom bottom bar renderer.
|
|
83
|
+
* When provided, replaces the entire default bottom bar.
|
|
84
|
+
* Use compound components (DetailViewBottomBar, DetailViewActionButton, etc.)
|
|
85
|
+
* to build custom layouts.
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* ```tsx
|
|
89
|
+
* <DetailViewHeadless
|
|
90
|
+
* renderBottomBar={() => (
|
|
91
|
+
* <DetailViewBottomBar>
|
|
92
|
+
* <DetailViewActionButton type="like" />
|
|
93
|
+
* <DetailViewActionButton type="share" />
|
|
94
|
+
* </DetailViewBottomBar>
|
|
95
|
+
* )}
|
|
96
|
+
* />
|
|
97
|
+
* ```
|
|
98
|
+
*/
|
|
99
|
+
renderBottomBar?: () => ReactNode;
|
|
100
|
+
/**
|
|
101
|
+
* Hide the default bottom bar completely.
|
|
102
|
+
* Use when you want to render your own bottom bar via children.
|
|
103
|
+
*/
|
|
104
|
+
hideBottomBar?: boolean;
|
|
105
|
+
/** Additional class name */
|
|
106
|
+
className?: string;
|
|
107
|
+
/** Children */
|
|
108
|
+
children?: ReactNode;
|
|
109
|
+
}
|
|
110
|
+
declare function formatCount(count: number): string;
|
|
111
|
+
declare function DetailViewHeadlessBase({ isOpen, onClose, imagePost, initialImageIndex, animationDuration, enableSwipeToClose, swipeCloseThreshold, headerTitle, showDragIndicator, isLiked, isBookmarked, isFollowing, onLike, onComment, onShare, onBookmark, onFollow, renderBottomBar, hideBottomBar, className, children, }: DetailViewHeadlessProps): ReactElement | null;
|
|
112
|
+
declare const DetailViewHeadless: react.MemoExoticComponent<typeof DetailViewHeadlessBase>;
|
|
113
|
+
/**
|
|
114
|
+
* Image Gallery for detail view
|
|
115
|
+
*/
|
|
116
|
+
interface DetailViewGalleryProps {
|
|
117
|
+
/** Enable zoom on images */
|
|
118
|
+
enableZoom?: boolean;
|
|
119
|
+
/** Class name */
|
|
120
|
+
className?: string;
|
|
121
|
+
}
|
|
122
|
+
declare function DetailViewGallery({ enableZoom, className, }: DetailViewGalleryProps): ReactElement;
|
|
123
|
+
/**
|
|
124
|
+
* Author section for detail view
|
|
125
|
+
*/
|
|
126
|
+
interface DetailViewAuthorProps {
|
|
127
|
+
/** Whether user is following this author */
|
|
128
|
+
isFollowing?: boolean;
|
|
129
|
+
/** Follow button click handler */
|
|
130
|
+
onFollowClick?: () => void;
|
|
131
|
+
/** Show follow button */
|
|
132
|
+
showFollowButton?: boolean;
|
|
133
|
+
/** Format date function */
|
|
134
|
+
formatDate?: (date: Date | string) => string;
|
|
135
|
+
/** Follow button label */
|
|
136
|
+
followLabel?: string;
|
|
137
|
+
/** Following button label */
|
|
138
|
+
followingLabel?: string;
|
|
139
|
+
/** Class name */
|
|
140
|
+
className?: string;
|
|
141
|
+
}
|
|
142
|
+
declare function DetailViewAuthor({ isFollowing, onFollowClick, showFollowButton, formatDate, followLabel, followingLabel, className, }: DetailViewAuthorProps): ReactElement | null;
|
|
143
|
+
/**
|
|
144
|
+
* Caption display for detail view
|
|
145
|
+
*/
|
|
146
|
+
interface DetailViewCaptionProps {
|
|
147
|
+
/** Render hashtags as links */
|
|
148
|
+
renderHashtag?: (hashtag: string) => ReactNode;
|
|
149
|
+
/** Class name */
|
|
150
|
+
className?: string;
|
|
151
|
+
}
|
|
152
|
+
declare function DetailViewCaption({ renderHashtag, className, }: DetailViewCaptionProps): ReactElement | null;
|
|
153
|
+
/**
|
|
154
|
+
* Stats display for detail view
|
|
155
|
+
*/
|
|
156
|
+
interface DetailViewStatsProps {
|
|
157
|
+
/** Format number function */
|
|
158
|
+
formatNumber?: (num: number) => string;
|
|
159
|
+
/** Labels */
|
|
160
|
+
labels?: {
|
|
161
|
+
likes?: string;
|
|
162
|
+
comments?: string;
|
|
163
|
+
shares?: string;
|
|
164
|
+
views?: string;
|
|
165
|
+
};
|
|
166
|
+
/** Class name */
|
|
167
|
+
className?: string;
|
|
168
|
+
}
|
|
169
|
+
declare function DetailViewStats({ formatNumber, labels, className, }: DetailViewStatsProps): ReactElement;
|
|
170
|
+
/**
|
|
171
|
+
* Music bar for detail view
|
|
172
|
+
*/
|
|
173
|
+
interface DetailViewMusicProps {
|
|
174
|
+
/** Music info */
|
|
175
|
+
music?: MusicInfo;
|
|
176
|
+
/** Whether music is playing */
|
|
177
|
+
isPlaying?: boolean;
|
|
178
|
+
/** Click handler */
|
|
179
|
+
onClick?: () => void;
|
|
180
|
+
/** Class name */
|
|
181
|
+
className?: string;
|
|
182
|
+
}
|
|
183
|
+
declare function DetailViewMusic({ music, isPlaying, onClick, className, }: DetailViewMusicProps): ReactElement | null;
|
|
184
|
+
/**
|
|
185
|
+
* Bottom bar container
|
|
186
|
+
*
|
|
187
|
+
* Use this to wrap custom bottom bar content.
|
|
188
|
+
* Handles event propagation and styling.
|
|
189
|
+
*
|
|
190
|
+
* @example
|
|
191
|
+
* ```tsx
|
|
192
|
+
* <DetailViewHeadless
|
|
193
|
+
* renderBottomBar={() => (
|
|
194
|
+
* <DetailViewBottomBar>
|
|
195
|
+
* <DetailViewCommentInput />
|
|
196
|
+
* <DetailViewActions>
|
|
197
|
+
* <DetailViewActionButton type="like" />
|
|
198
|
+
* <DetailViewActionButton type="share" />
|
|
199
|
+
* </DetailViewActions>
|
|
200
|
+
* </DetailViewBottomBar>
|
|
201
|
+
* )}
|
|
202
|
+
* />
|
|
203
|
+
* ```
|
|
204
|
+
*/
|
|
205
|
+
interface DetailViewBottomBarProps {
|
|
206
|
+
/** Children */
|
|
207
|
+
children?: ReactNode;
|
|
208
|
+
/** Class name */
|
|
209
|
+
className?: string;
|
|
210
|
+
}
|
|
211
|
+
declare function DetailViewBottomBar({ children, className, }: DetailViewBottomBarProps): ReactElement;
|
|
212
|
+
/**
|
|
213
|
+
* Comment input for bottom bar
|
|
214
|
+
*
|
|
215
|
+
* @example
|
|
216
|
+
* ```tsx
|
|
217
|
+
* <DetailViewCommentInput
|
|
218
|
+
* placeholder="Write a comment..."
|
|
219
|
+
* onSubmit={(value) => submitComment(value)}
|
|
220
|
+
* />
|
|
221
|
+
* ```
|
|
222
|
+
*/
|
|
223
|
+
interface DetailViewCommentInputProps {
|
|
224
|
+
/** Placeholder text */
|
|
225
|
+
placeholder?: string;
|
|
226
|
+
/** Called when user submits comment (presses Enter) */
|
|
227
|
+
onSubmit?: (value: string) => void;
|
|
228
|
+
/** Class name */
|
|
229
|
+
className?: string;
|
|
230
|
+
}
|
|
231
|
+
declare function DetailViewCommentInput({ placeholder, onSubmit, className, }: DetailViewCommentInputProps): ReactElement;
|
|
232
|
+
/**
|
|
233
|
+
* Actions container for bottom bar
|
|
234
|
+
*
|
|
235
|
+
* @example
|
|
236
|
+
* ```tsx
|
|
237
|
+
* <DetailViewActions>
|
|
238
|
+
* <DetailViewActionButton type="like" />
|
|
239
|
+
* <DetailViewActionButton type="comment" />
|
|
240
|
+
* </DetailViewActions>
|
|
241
|
+
* ```
|
|
242
|
+
*/
|
|
243
|
+
interface DetailViewActionsProps {
|
|
244
|
+
/** Children (action buttons) */
|
|
245
|
+
children?: ReactNode;
|
|
246
|
+
/** Class name */
|
|
247
|
+
className?: string;
|
|
248
|
+
}
|
|
249
|
+
declare function DetailViewActions({ children, className }: DetailViewActionsProps): ReactElement;
|
|
250
|
+
/**
|
|
251
|
+
* Action button types
|
|
252
|
+
*/
|
|
253
|
+
type DetailViewActionType = 'like' | 'comment' | 'bookmark' | 'share';
|
|
254
|
+
/**
|
|
255
|
+
* Single action button for bottom bar
|
|
256
|
+
*
|
|
257
|
+
* Can be used with predefined types (like, comment, bookmark, share)
|
|
258
|
+
* or with custom icon/content.
|
|
259
|
+
*
|
|
260
|
+
* @example
|
|
261
|
+
* ```tsx
|
|
262
|
+
* // Using predefined type
|
|
263
|
+
* <DetailViewActionButton type="like" isActive={isLiked} count={123} onClick={handleLike} />
|
|
264
|
+
*
|
|
265
|
+
* // Using custom icon
|
|
266
|
+
* <DetailViewActionButton icon={<MyCustomIcon />} onClick={handleCustomAction} />
|
|
267
|
+
* ```
|
|
268
|
+
*/
|
|
269
|
+
interface DetailViewActionButtonProps {
|
|
270
|
+
/** Predefined action type */
|
|
271
|
+
type?: DetailViewActionType;
|
|
272
|
+
/** Custom icon (overrides type) */
|
|
273
|
+
icon?: ReactNode;
|
|
274
|
+
/** Whether button is active (e.g., liked, bookmarked) */
|
|
275
|
+
isActive?: boolean;
|
|
276
|
+
/** Count to display */
|
|
277
|
+
count?: number;
|
|
278
|
+
/** Click handler */
|
|
279
|
+
onClick?: () => void;
|
|
280
|
+
/** Aria label */
|
|
281
|
+
ariaLabel?: string;
|
|
282
|
+
/** Class name */
|
|
283
|
+
className?: string;
|
|
284
|
+
/** Children (additional content) */
|
|
285
|
+
children?: ReactNode;
|
|
286
|
+
}
|
|
287
|
+
declare function DetailViewActionButton({ type, icon, isActive, count, onClick, ariaLabel, className, children, }: DetailViewActionButtonProps): ReactElement;
|
|
288
|
+
/**
|
|
289
|
+
* Export icons for host apps that want to build custom bottom bars
|
|
290
|
+
* but still use consistent icons.
|
|
291
|
+
*/
|
|
292
|
+
declare const DetailViewIcons: {
|
|
293
|
+
Back: typeof BackIcon;
|
|
294
|
+
Heart: typeof HeartIcon;
|
|
295
|
+
Comment: typeof CommentIcon;
|
|
296
|
+
Bookmark: typeof BookmarkIcon;
|
|
297
|
+
Share: typeof ShareIcon;
|
|
298
|
+
};
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* DetailView CSS - Injected at runtime
|
|
302
|
+
*
|
|
303
|
+
* Features:
|
|
304
|
+
* - Full-screen detail view
|
|
305
|
+
* - Expand/collapse animation
|
|
306
|
+
* - Scrollable content
|
|
307
|
+
* - Back gesture (swipe down)
|
|
308
|
+
*/
|
|
309
|
+
declare const DETAIL_VIEW_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\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n DETAIL VIEW - 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\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.sv-detail-view {\n position: fixed;\n inset: 0;\n z-index: var(--sv-detail-view-z-index, 1000);\n background: var(--sv-detail-view-bg, #000);\n overflow: hidden;\n touch-action: none;\n}\n\n/* States */\n.sv-detail-view--entering {\n animation: sv-detail-view-enter 0.3s cubic-bezier(0.32, 0.72, 0, 1) forwards;\n}\n\n.sv-detail-view--exiting {\n animation: sv-detail-view-exit 0.3s cubic-bezier(0.32, 0.72, 0, 1) forwards;\n}\n\n.sv-detail-view--dragging {\n transition: none;\n}\n\n@keyframes sv-detail-view-enter {\n from {\n opacity: 0;\n transform: translateY(100%) scale(0.9);\n }\n to {\n opacity: 1;\n transform: translateY(0) scale(1);\n }\n}\n\n@keyframes sv-detail-view-exit {\n from {\n opacity: 1;\n transform: translateY(0) scale(1);\n }\n to {\n opacity: 0;\n transform: translateY(100%) scale(0.9);\n }\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\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n BACKDROP\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\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.sv-detail-view__backdrop {\n position: absolute;\n inset: 0;\n background: var(--sv-detail-view-backdrop-bg, rgba(0, 0, 0, 0.8));\n opacity: 1;\n transition: opacity 0.3s ease;\n}\n\n.sv-detail-view--exiting .sv-detail-view__backdrop {\n opacity: 0;\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\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n CONTENT 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\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.sv-detail-view__container {\n position: absolute;\n inset: 0;\n display: flex;\n flex-direction: column;\n will-change: transform;\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\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\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.sv-detail-view__header {\n position: sticky;\n top: 0;\n z-index: 10;\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: var(--sv-detail-view-header-padding, 12px 16px);\n background: var(--sv-detail-view-header-bg, rgba(0, 0, 0, 0.8));\n backdrop-filter: blur(10px);\n -webkit-backdrop-filter: blur(10px);\n}\n\n.sv-detail-view__back-button {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 40px;\n height: 40px;\n padding: 0;\n border: none;\n border-radius: 50%;\n background: var(--sv-detail-view-back-bg, rgba(255, 255, 255, 0.1));\n color: var(--sv-detail-view-back-color, #fff);\n cursor: pointer;\n transition: background 0.2s ease;\n}\n\n.sv-detail-view__back-button:hover {\n background: var(--sv-detail-view-back-hover-bg, rgba(255, 255, 255, 0.2));\n}\n\n.sv-detail-view__back-button svg {\n width: 24px;\n height: 24px;\n}\n\n.sv-detail-view__title {\n font-size: var(--sv-detail-view-title-font-size, 16px);\n font-weight: 600;\n color: var(--sv-detail-view-title-color, #fff);\n}\n\n.sv-detail-view__actions {\n display: flex;\n gap: 8px;\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\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n DRAG INDICATOR\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\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.sv-detail-view__drag-indicator {\n position: absolute;\n top: 8px;\n left: 50%;\n transform: translateX(-50%);\n width: 36px;\n height: 5px;\n background: var(--sv-detail-view-drag-indicator-bg, rgba(255, 255, 255, 0.3));\n border-radius: 3px;\n z-index: 20;\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\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n SCROLL CONTENT\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\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.sv-detail-view__scroll {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n -webkit-overflow-scrolling: touch;\n overscroll-behavior-y: contain;\n /* Allow vertical scroll but block horizontal (prevents Feed swipe) */\n touch-action: pan-y;\n /* Padding bottom for bottom bar */\n padding-bottom: 70px;\n}\n\n.sv-detail-view__content {\n min-height: 100%;\n /* No horizontal padding - gallery should be full width */\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\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n IMAGE GALLERY\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\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.sv-detail-view__gallery {\n position: relative;\n width: 100%;\n aspect-ratio: 1;\n background: var(--sv-detail-view-gallery-bg, #111);\n overflow: hidden;\n}\n\n.sv-detail-view__gallery-image {\n width: 100%;\n height: 100%;\n object-fit: contain;\n}\n\n/* Gallery pagination */\n.sv-detail-view__gallery-pagination {\n position: absolute;\n bottom: 12px;\n left: 50%;\n transform: translateX(-50%);\n display: flex;\n gap: 6px;\n padding: 6px 12px;\n background: rgba(0, 0, 0, 0.5);\n border-radius: 20px;\n}\n\n.sv-detail-view__gallery-dot {\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background: rgba(255, 255, 255, 0.5);\n border: none;\n padding: 0;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.sv-detail-view__gallery-dot--active {\n background: #fff;\n transform: scale(1.2);\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\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n AUTHOR SECTION\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\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.sv-detail-view__author {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 16px 0;\n border-bottom: 1px solid var(--sv-detail-view-border-color, rgba(255, 255, 255, 0.1));\n}\n\n.sv-detail-view__author-avatar {\n width: 44px;\n height: 44px;\n border-radius: 50%;\n object-fit: cover;\n}\n\n.sv-detail-view__author-info {\n flex: 1;\n}\n\n.sv-detail-view__author-name {\n font-size: 15px;\n font-weight: 600;\n color: var(--sv-detail-view-text-color, #fff);\n}\n\n.sv-detail-view__author-date {\n font-size: 13px;\n color: var(--sv-detail-view-secondary-color, rgba(255, 255, 255, 0.6));\n margin-top: 2px;\n}\n\n.sv-detail-view__follow-button {\n padding: 8px 20px;\n background: var(--sv-detail-view-follow-bg, #fe2c55);\n border: none;\n border-radius: 4px;\n font-size: 14px;\n font-weight: 600;\n color: #fff;\n cursor: pointer;\n transition: opacity 0.2s ease;\n}\n\n.sv-detail-view__follow-button:hover {\n opacity: 0.9;\n}\n\n.sv-detail-view__follow-button--following {\n background: var(--sv-detail-view-following-bg, rgba(255, 255, 255, 0.1));\n color: var(--sv-detail-view-following-color, #fff);\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\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n CAPTION SECTION\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\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.sv-detail-view__caption {\n padding: 16px;\n font-size: var(--sv-detail-view-caption-font-size, 15px);\n line-height: 1.5;\n color: var(--sv-detail-view-text-color, #fff);\n white-space: pre-wrap;\n word-break: break-word;\n}\n\n/* Hashtags in caption */\n.sv-detail-view__hashtag {\n color: var(--sv-detail-view-hashtag-color, #4dabff);\n cursor: pointer;\n}\n\n.sv-detail-view__hashtag:hover {\n text-decoration: underline;\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\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n STATS SECTION\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\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.sv-detail-view__stats {\n display: flex;\n gap: 24px;\n padding: 16px 0;\n border-top: 1px solid var(--sv-detail-view-border-color, rgba(255, 255, 255, 0.1));\n}\n\n.sv-detail-view__stat {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 14px;\n color: var(--sv-detail-view-secondary-color, rgba(255, 255, 255, 0.6));\n}\n\n.sv-detail-view__stat-value {\n font-weight: 600;\n color: var(--sv-detail-view-text-color, #fff);\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\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n ACTION BAR (Bottom)\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\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.sv-detail-view__action-bar {\n position: sticky;\n bottom: 0;\n display: flex;\n justify-content: space-around;\n padding: 12px 16px;\n background: var(--sv-detail-view-action-bar-bg, rgba(0, 0, 0, 0.9));\n backdrop-filter: blur(10px);\n -webkit-backdrop-filter: blur(10px);\n border-top: 1px solid var(--sv-detail-view-border-color, rgba(255, 255, 255, 0.1));\n}\n\n.sv-detail-view__action {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 4px;\n padding: 8px 16px;\n border: none;\n background: transparent;\n color: var(--sv-detail-view-action-color, #fff);\n cursor: pointer;\n transition: opacity 0.2s ease;\n}\n\n.sv-detail-view__action:hover {\n opacity: 0.8;\n}\n\n.sv-detail-view__action--active {\n color: var(--sv-detail-view-action-active-color, #fe2c55);\n}\n\n.sv-detail-view__action svg {\n width: 24px;\n height: 24px;\n}\n\n.sv-detail-view__action-label {\n font-size: 12px;\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\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n MUSIC BAR\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\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.sv-detail-view__music {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 12px;\n margin: 0 16px 16px;\n background: var(--sv-detail-view-music-bg, rgba(255, 255, 255, 0.05));\n border-radius: 8px;\n border: none;\n width: calc(100% - 32px);\n cursor: pointer;\n text-align: left;\n}\n\n.sv-detail-view__music-cover {\n width: 48px;\n height: 48px;\n border-radius: 4px;\n object-fit: cover;\n}\n\n.sv-detail-view__music-info {\n flex: 1;\n overflow: hidden;\n}\n\n.sv-detail-view__music-title {\n font-size: 14px;\n font-weight: 500;\n color: var(--sv-detail-view-text-color, #fff);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.sv-detail-view__music-artist {\n font-size: 12px;\n color: var(--sv-detail-view-secondary-color, rgba(255, 255, 255, 0.6));\n margin-top: 2px;\n}\n\n.sv-detail-view__music-icon {\n width: 24px;\n height: 24px;\n color: var(--sv-detail-view-secondary-color, rgba(255, 255, 255, 0.6));\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\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n HEADER - Author Info (Plan Layout)\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\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.sv-detail-view__header-author {\n display: flex;\n align-items: center;\n gap: 10px;\n flex: 1;\n min-width: 0;\n margin-left: 12px;\n}\n\n.sv-detail-view__header-avatar {\n width: 32px;\n height: 32px;\n border-radius: 50%;\n object-fit: cover;\n flex-shrink: 0;\n}\n\n.sv-detail-view__header-name {\n font-size: 15px;\n font-weight: 600;\n color: var(--sv-detail-view-text-color, #fff);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.sv-detail-view__follow-btn {\n padding: 6px 16px;\n font-size: 13px;\n font-weight: 600;\n border: none;\n border-radius: 4px;\n background: var(--sv-detail-view-follow-bg, #fe2c55);\n color: #fff;\n cursor: pointer;\n transition: background 0.2s ease, opacity 0.2s ease;\n flex-shrink: 0;\n}\n\n.sv-detail-view__follow-btn:hover {\n opacity: 0.9;\n}\n\n.sv-detail-view__follow-btn--following {\n background: var(--sv-detail-view-following-bg, rgba(255, 255, 255, 0.12));\n color: var(--sv-detail-view-text-color, #fff);\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\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n BOTTOM ACTION BAR (Plan Layout)\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\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.sv-detail-view__bottom-bar {\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0;\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 12px;\n padding-bottom: max(10px, env(safe-area-inset-bottom));\n background: var(--sv-detail-view-bottom-bar-bg, rgba(0, 0, 0, 0.95));\n border-top: 1px solid var(--sv-detail-view-border-color, rgba(255, 255, 255, 0.1));\n z-index: 20;\n}\n\n.sv-detail-view__comment-input {\n flex: 1;\n display: flex;\n align-items: center;\n background: var(--sv-detail-view-input-bg, rgba(255, 255, 255, 0.08));\n border-radius: 18px;\n min-width: 0;\n overflow: hidden;\n}\n\n.sv-detail-view__bottom-bar .sv-detail-view__comment-input input,\n.sv-detail-view__comment-field,\ninput.sv-detail-view__comment-field {\n flex: 1;\n width: 100%;\n height: auto;\n padding: 10px 14px;\n margin: 0;\n border: none;\n border-radius: 0;\n background: transparent;\n background-color: transparent;\n font-family: inherit;\n font-size: 14px;\n line-height: 1.4;\n color: var(--sv-detail-view-text-color, #fff);\n outline: none;\n box-shadow: none;\n -webkit-appearance: none;\n -moz-appearance: none;\n appearance: none;\n}\n\n.sv-detail-view__bottom-bar .sv-detail-view__comment-input input::placeholder,\n.sv-detail-view__comment-field::placeholder,\ninput.sv-detail-view__comment-field::placeholder {\n color: var(--sv-detail-view-placeholder-color, rgba(255, 255, 255, 0.5));\n opacity: 1;\n}\n\n.sv-detail-view__bottom-bar .sv-detail-view__comment-input input:focus,\n.sv-detail-view__comment-field:focus,\ninput.sv-detail-view__comment-field:focus {\n outline: none;\n box-shadow: none;\n border: none;\n}\n\n.sv-detail-view__bottom-actions {\n display: flex;\n align-items: center;\n gap: 2px;\n flex-shrink: 0;\n}\n\n.sv-detail-view__action-btn {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n min-width: 40px;\n padding: 4px 6px;\n background: none;\n border: none;\n color: var(--sv-detail-view-text-color, #fff);\n cursor: pointer;\n transition: transform 0.15s ease, color 0.15s ease;\n}\n\n.sv-detail-view__action-btn:hover {\n transform: scale(1.05);\n}\n\n.sv-detail-view__action-btn:active {\n transform: scale(0.95);\n}\n\n.sv-detail-view__action-btn--active {\n color: var(--sv-detail-view-active-color, #fe2c55);\n}\n\n.sv-detail-view__action-btn svg {\n width: 22px;\n height: 22px;\n}\n\n.sv-detail-view__action-count {\n font-size: 11px;\n margin-top: 2px;\n color: var(--sv-detail-view-secondary-color, rgba(255, 255, 255, 0.7));\n}\n\n.sv-detail-view__action-btn--active .sv-detail-view__action-count {\n color: var(--sv-detail-view-active-color, #fe2c55);\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\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n ACCESSIBILITY\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\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.sv-detail-view:focus-visible {\n outline: 2px solid var(--sv-detail-view-focus-color, #4dabff);\n outline-offset: -2px;\n}\n\n.sv-detail-view__sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n}\n";
|
|
310
|
+
|
|
311
|
+
export { DETAIL_VIEW_CSS, DetailViewActionButton, type DetailViewActionButtonProps, type DetailViewActionType, DetailViewActions, type DetailViewActionsProps, DetailViewAuthor, type DetailViewAuthorProps, DetailViewBottomBar, type DetailViewBottomBarProps, DetailViewCaption, type DetailViewCaptionProps, DetailViewCommentInput, type DetailViewCommentInputProps, type DetailViewContextValue, DetailViewGallery, type DetailViewGalleryProps, DetailViewHeadless, type DetailViewHeadlessProps, DetailViewIcons, DetailViewMusic, type DetailViewMusicProps, DetailViewStats, type DetailViewStatsProps, formatCount as formatDetailViewCount, useDetailViewContext };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { DETAIL_VIEW_CSS, DetailViewActionButton, DetailViewActions, DetailViewAuthor, DetailViewBottomBar, DetailViewCaption, DetailViewCommentInput, DetailViewGallery, DetailViewHeadless, DetailViewIcons, DetailViewMusic, DetailViewStats, formatCount as formatDetailViewCount, useDetailViewContext } from '../../chunk-FR7UQSZP.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { ErrorBoundary } from '../../chunk-
|
|
1
|
+
export { ErrorBoundary } from '../../chunk-IWSBYOSS.js';
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ReactNode, ReactElement } from 'react';
|
|
3
|
+
|
|
4
|
+
interface ImageCarouselProps {
|
|
5
|
+
/** Array of image URLs */
|
|
6
|
+
images: string[];
|
|
7
|
+
/** Current active index (controlled) */
|
|
8
|
+
currentIndex?: number;
|
|
9
|
+
/** Called when index changes */
|
|
10
|
+
onIndexChange?: (index: number) => void;
|
|
11
|
+
/** Show pagination indicators */
|
|
12
|
+
showIndicators?: boolean;
|
|
13
|
+
/** Indicator style: 'dots' or 'counter' (e.g., "1/5") */
|
|
14
|
+
indicatorStyle?: 'dots' | 'counter';
|
|
15
|
+
/** Show navigation arrows (desktop) */
|
|
16
|
+
showArrows?: boolean;
|
|
17
|
+
/** Enable pinch-to-zoom */
|
|
18
|
+
enableZoom?: boolean;
|
|
19
|
+
/** Maximum zoom scale */
|
|
20
|
+
maxZoomScale?: number;
|
|
21
|
+
/** Lazy load images (only load visible + adjacent) */
|
|
22
|
+
lazyLoad?: boolean;
|
|
23
|
+
/** Custom image renderer */
|
|
24
|
+
renderImage?: (url: string, index: number, isLoaded: boolean) => ReactNode;
|
|
25
|
+
/** Custom placeholder renderer */
|
|
26
|
+
renderPlaceholder?: (index: number) => ReactNode;
|
|
27
|
+
/** Swipe threshold (percentage of width) */
|
|
28
|
+
swipeThreshold?: number;
|
|
29
|
+
/** Called when zoom state changes */
|
|
30
|
+
onZoomChange?: (isZoomed: boolean) => void;
|
|
31
|
+
/** Called when swipe direction is locked (to allow/block scroll) */
|
|
32
|
+
onSwipeDirectionChange?: (direction: 'horizontal' | 'vertical' | null) => void;
|
|
33
|
+
/** Additional class name */
|
|
34
|
+
className?: string;
|
|
35
|
+
}
|
|
36
|
+
declare function ImageCarouselHeadlessBase({ images, currentIndex: controlledIndex, onIndexChange, showIndicators, indicatorStyle, showArrows, enableZoom, maxZoomScale, lazyLoad, renderImage, renderPlaceholder, swipeThreshold, onZoomChange, onSwipeDirectionChange, className, }: ImageCarouselProps): ReactElement;
|
|
37
|
+
declare const ImageCarouselHeadless: react.MemoExoticComponent<typeof ImageCarouselHeadlessBase>;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* ImageCarousel CSS - Injected at runtime
|
|
41
|
+
*
|
|
42
|
+
* Features:
|
|
43
|
+
* - Horizontal swipe carousel
|
|
44
|
+
* - Pagination indicators (dots)
|
|
45
|
+
* - Smooth transitions
|
|
46
|
+
* - Touch-friendly design
|
|
47
|
+
*/
|
|
48
|
+
declare const IMAGE_CAROUSEL_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\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n IMAGE CAROUSEL - 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\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.sv-image-carousel {\n position: relative;\n width: 100%;\n height: 100%;\n overflow: hidden;\n touch-action: pan-y pinch-zoom;\n user-select: none;\n -webkit-user-select: none;\n background: var(--sv-carousel-bg, #000);\n}\n\n/* Dragging state - only for styling, does not block scroll */\n.sv-image-carousel--dragging {\n /* Do not set touch-action: none here - to detect direction */\n -webkit-user-drag: none;\n}\n\n/* Direction-locked states */\n.sv-image-carousel--swiping-horizontal {\n /* When swiping horizontally, block scroll, prevent overscroll */\n touch-action: none !important;\n overscroll-behavior: contain;\n}\n\n.sv-image-carousel--swiping-vertical {\n /* When swiping vertically, allow scroll, block carousel swipe */\n touch-action: pan-y;\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\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n TRACK - Horizontal sliding 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\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.sv-image-carousel-track {\n display: flex;\n height: 100%;\n will-change: transform;\n transition: transform 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94);\n}\n\n.sv-image-carousel-track--dragging {\n transition: none;\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\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n SLIDE - Individual image 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\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.sv-image-carousel-slide {\n flex: 0 0 100%;\n width: 100%;\n height: 100%;\n display: flex;\n align-items: center;\n justify-content: center;\n overflow: hidden;\n position: relative;\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\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n IMAGE\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\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.sv-image-carousel-image {\n max-width: 100%;\n max-height: 100%;\n width: 100%;\n height: 100%;\n object-fit: contain;\n pointer-events: none;\n transition: transform 0.2s ease-out;\n}\n\n.sv-image-carousel-image--loading {\n opacity: 0;\n}\n\n.sv-image-carousel-image--loaded {\n opacity: 1;\n transition: opacity 0.3s ease;\n}\n\n/* Zoomed image */\n.sv-image-carousel-image--zoomed {\n cursor: grab;\n pointer-events: auto;\n}\n\n.sv-image-carousel-image--zoomed:active {\n cursor: grabbing;\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\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n PLACEHOLDER / SKELETON\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\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.sv-image-carousel-placeholder {\n position: absolute;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--sv-carousel-placeholder-bg, rgba(255, 255, 255, 0.1));\n}\n\n.sv-image-carousel-skeleton {\n width: 60%;\n height: 60%;\n background: linear-gradient(\n 90deg,\n rgba(255, 255, 255, 0.05) 25%,\n rgba(255, 255, 255, 0.1) 50%,\n rgba(255, 255, 255, 0.05) 75%\n );\n background-size: 200% 100%;\n animation: sv-carousel-shimmer 1.5s infinite;\n border-radius: 8px;\n}\n\n@keyframes sv-carousel-shimmer {\n 0% {\n background-position: 200% 0;\n }\n 100% {\n background-position: -200% 0;\n }\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\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n PAGINATION INDICATORS (Dots)\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\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.sv-image-carousel-indicators {\n position: absolute;\n bottom: var(--sv-carousel-indicators-bottom, 16px);\n left: 50%;\n transform: translateX(-50%);\n display: flex;\n gap: var(--sv-carousel-indicators-gap, 6px);\n padding: 6px 12px;\n border-radius: 20px;\n z-index: 10;\n}\n\n.sv-image-carousel-dot {\n width: var(--sv-carousel-dot-size, 6px);\n height: var(--sv-carousel-dot-size, 6px);\n border-radius: 50%;\n background: var(--sv-carousel-dot-color, rgba(255, 255, 255, 0.5));\n transition: all 0.2s ease;\n cursor: pointer;\n border: none;\n padding: 0;\n}\n\n.sv-image-carousel-dot:hover {\n background: var(--sv-carousel-dot-hover, rgba(255, 255, 255, 0.7));\n}\n\n.sv-image-carousel-dot--active {\n background: var(--sv-carousel-dot-active, #fff);\n transform: scale(1.2);\n}\n\n/* Compact mode for many images (> 5) */\n.sv-image-carousel-indicators--compact .sv-image-carousel-dot {\n width: 4px;\n height: 4px;\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\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n COUNTER (Alternative to dots)\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\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.sv-image-carousel-counter {\n position: absolute;\n top: var(--sv-carousel-counter-top, 16px);\n right: var(--sv-carousel-counter-right, 16px);\n padding: 4px 10px;\n background: var(--sv-carousel-counter-bg, rgba(0, 0, 0, 0.6));\n border-radius: 12px;\n font-size: var(--sv-carousel-counter-font-size, 12px);\n font-weight: 500;\n color: var(--sv-carousel-counter-color, #fff);\n z-index: 10;\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\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n NAVIGATION ARROWS (Optional)\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\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.sv-image-carousel-nav {\n position: absolute;\n top: 50%;\n transform: translateY(-50%);\n width: 40px;\n height: 40px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--sv-carousel-nav-bg, rgba(0, 0, 0, 0.4));\n border: none;\n border-radius: 50%;\n color: var(--sv-carousel-nav-color, #fff);\n cursor: pointer;\n z-index: 10;\n opacity: 0;\n transition: opacity 0.2s ease;\n}\n\n.sv-image-carousel:hover .sv-image-carousel-nav {\n opacity: 1;\n}\n\n.sv-image-carousel-nav:hover {\n background: var(--sv-carousel-nav-hover-bg, rgba(0, 0, 0, 0.6));\n}\n\n.sv-image-carousel-nav:disabled {\n opacity: 0.3;\n cursor: not-allowed;\n}\n\n.sv-image-carousel-nav--prev {\n left: 12px;\n}\n\n.sv-image-carousel-nav--next {\n right: 12px;\n}\n\n.sv-image-carousel-nav svg {\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\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n ZOOM OVERLAY\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\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.sv-image-carousel-zoom-container {\n position: absolute;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n overflow: hidden;\n touch-action: none;\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\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n ACCESSIBILITY\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\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.sv-image-carousel:focus-visible {\n outline: 2px solid var(--sv-carousel-focus-color, #4dabff);\n outline-offset: 2px;\n}\n\n.sv-image-carousel-dot:focus-visible {\n outline: 2px solid var(--sv-carousel-focus-color, #4dabff);\n outline-offset: 2px;\n}\n\n/* Screen reader only */\n.sv-image-carousel-sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n}\n";
|
|
49
|
+
|
|
50
|
+
export { IMAGE_CAROUSEL_CSS, ImageCarouselHeadless, type ImageCarouselProps };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { IMAGE_CAROUSEL_CSS, ImageCarouselHeadless } from '../../chunk-Q6MG7AVG.js';
|