@xhub-short/ui 0.1.0-beta.9 → 1.0.0-beta.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/dist/CommentSheet.css-DuBy01rU.d.ts +219 -0
  2. package/dist/VideoSlotPlayIndicator-DPs8Xt5C.d.ts +51 -0
  3. package/dist/chunk-3OB3OVYR.js +349 -0
  4. package/dist/chunk-4RIMQOBR.js +58 -0
  5. package/dist/chunk-5MKYDI4X.js +1 -0
  6. package/dist/chunk-5Y43HNRG.js +296 -0
  7. package/dist/chunk-7WXAQHJI.js +350 -0
  8. package/dist/chunk-BADA7OLG.js +564 -0
  9. package/dist/chunk-BEJAJFV6.js +191 -0
  10. package/dist/chunk-BNI7CYRI.js +334 -0
  11. package/dist/{chunk-RMLTPW5S.js → chunk-CAWE42LH.js} +4 -3
  12. package/dist/chunk-DGKMO3AE.js +717 -0
  13. package/dist/chunk-DR7KR7OT.js +103 -0
  14. package/dist/chunk-GSNIZ6DF.js +605 -0
  15. package/dist/chunk-HXQPEZRG.js +105 -0
  16. package/dist/{chunk-FNXTPQ6L.js → chunk-IC2KUU4V.js} +31 -1340
  17. package/dist/chunk-IWSBYOSS.js +91 -0
  18. package/dist/chunk-MFJS65C5.js +368 -0
  19. package/dist/{chunk-AC2IFAJR.js → chunk-NJXIYSDZ.js} +12 -1
  20. package/dist/{chunk-CL6BS7GB.js → chunk-OM4L7RE5.js} +12 -2
  21. package/dist/chunk-QCRRF76W.js +75 -0
  22. package/dist/chunk-QUEJHA24.js +508 -0
  23. package/dist/chunk-UYBQTE4M.js +337 -0
  24. package/dist/chunk-VJ744W5N.js +603 -0
  25. package/dist/chunk-VXW7AOGM.js +285 -0
  26. package/dist/{chunk-AQHD6LPS.js → chunk-YB7AXTX7.js} +1 -1
  27. package/dist/components/ActionBar/index.d.ts +7 -2
  28. package/dist/components/ActionBar/index.js +1 -1
  29. package/dist/components/AdvanceMenu/index.d.ts +80 -0
  30. package/dist/components/AdvanceMenu/index.js +1 -0
  31. package/dist/components/ArticleSlot/index.d.ts +213 -0
  32. package/dist/components/ArticleSlot/index.js +1 -0
  33. package/dist/components/AuthorInfo/index.js +1 -1
  34. package/dist/components/BottomSheet/index.d.ts +87 -0
  35. package/dist/components/BottomSheet/index.js +1 -0
  36. package/dist/components/CleanModeOverlay/index.d.ts +60 -0
  37. package/dist/components/CleanModeOverlay/index.js +1 -0
  38. package/dist/components/CommentSheet/index.d.ts +1 -1
  39. package/dist/components/CommentSheet/index.js +1 -1
  40. package/dist/components/DetailView/index.d.ts +314 -0
  41. package/dist/components/DetailView/index.js +1 -0
  42. package/dist/components/ErrorBoundary/index.js +1 -1
  43. package/dist/components/{VideoFeed → Feed}/index.d.ts +64 -45
  44. package/dist/components/Feed/index.js +1 -0
  45. package/dist/components/ImageCarousel/index.d.ts +50 -0
  46. package/dist/components/ImageCarousel/index.js +1 -0
  47. package/dist/components/Playlist/index.d.ts +117 -0
  48. package/dist/components/Playlist/index.js +1 -0
  49. package/dist/components/ProgressBar/index.js +1 -1
  50. package/dist/components/QualityPicker/index.d.ts +35 -0
  51. package/dist/components/QualityPicker/index.js +1 -0
  52. package/dist/components/ReportSheet/index.d.ts +74 -0
  53. package/dist/components/ReportSheet/index.js +1 -0
  54. package/dist/components/Skeleton/index.js +1 -1
  55. package/dist/components/SpeedPicker/index.d.ts +32 -0
  56. package/dist/components/SpeedPicker/index.js +1 -0
  57. package/dist/components/VideoInfo/index.d.ts +7 -3
  58. package/dist/components/VideoInfo/index.js +1 -1
  59. package/dist/components/VideoPlayer/index.js +1 -1
  60. package/dist/components/VideoSlot/index.d.ts +31 -68
  61. package/dist/components/VideoSlot/index.js +2 -1
  62. package/dist/components/VirtualSlider/index.js +1 -1
  63. package/dist/index.d.ts +40 -10
  64. package/dist/index.js +23 -13
  65. package/package.json +8 -4
  66. package/dist/CommentSheet.css-BeCrEaUG.d.ts +0 -221
  67. package/dist/chunk-2FSDVYER.js +0 -737
  68. package/dist/chunk-ECR42RKK.js +0 -571
  69. package/dist/chunk-KWHMZ6H5.js +0 -562
  70. package/dist/chunk-SZXFH334.js +0 -204
  71. package/dist/chunk-UNV3NWN6.js +0 -148
  72. package/dist/chunk-WCRDTBCZ.js +0 -357
  73. package/dist/chunk-XDIH66C4.js +0 -1519
  74. package/dist/components/VideoFeed/index.js +0 -1
@@ -0,0 +1,213 @@
1
+ import * as react from 'react';
2
+ import { ReactNode, ReactElement } from 'react';
3
+ import { Article, MusicInfo } from '@xhub-short/contracts';
4
+ import { b as VideoSlotPlayIndicatorInnerProps } from '../../VideoSlotPlayIndicator-DPs8Xt5C.js';
5
+
6
+ /** CSS class for article slot */
7
+ declare const ARTICLE_SLOT_CLASS = "sv-article-slot";
8
+ /** CSS class for active state */
9
+ declare const ARTICLE_SLOT_ACTIVE_CLASS = "sv-article-slot--active";
10
+ /** CSS class for clean mode */
11
+ declare const ARTICLE_SLOT_CLEAN_MODE_CLASS = "sv-article-slot--clean-mode";
12
+ /** Data attribute for article ID */
13
+ declare const ARTICLE_ID_ATTR = "data-article-id";
14
+ /** Data attribute for active state */
15
+ declare const ARTICLE_ACTIVE_ATTR = "data-active";
16
+ interface ArticleSlotContextValue {
17
+ /** The article data */
18
+ article: Article;
19
+ /** Current image index in carousel */
20
+ currentImageIndex: number;
21
+ /** Total number of images */
22
+ totalImages: number;
23
+ /** Whether this slot is active (visible) */
24
+ isActive: boolean;
25
+ /** Whether in clean mode */
26
+ isCleanMode: boolean;
27
+ /** Timestamp of last user music toggle (for PlayIndicator) */
28
+ lastMusicToggleTime: number;
29
+ /** Music info (if any) */
30
+ music?: MusicInfo;
31
+ /** Whether music is playing */
32
+ isMusicPlaying: boolean;
33
+ /** Toggle music playback */
34
+ toggleMusic: () => void;
35
+ /** Navigate to specific image */
36
+ goToImage: (index: number) => void;
37
+ /** Go to next image */
38
+ nextImage: () => void;
39
+ /** Go to previous image */
40
+ prevImage: () => void;
41
+ /** Expand caption / open detail view */
42
+ expandCaption: () => void;
43
+ }
44
+ /**
45
+ * Hook to access ArticleSlot context
46
+ * @throws if used outside ArticleSlotHeadless
47
+ */
48
+ declare function useArticleSlotContext(): ArticleSlotContextValue;
49
+ /**
50
+ * Hook to optionally access ArticleSlot context
51
+ * Returns null if used outside ArticleSlotHeadless
52
+ */
53
+ declare function useOptionalArticleSlotContext(): ArticleSlotContextValue | null;
54
+ interface ArticleSlotHeadlessProps {
55
+ /** The article data */
56
+ article: Article;
57
+ /** Whether this slot is active (visible in viewport) */
58
+ isActive?: boolean;
59
+ /** Current image index (controlled) */
60
+ currentImageIndex?: number;
61
+ /** Called when image index changes */
62
+ onImageIndexChange?: (index: number) => void;
63
+ /** Music info for this post */
64
+ music?: MusicInfo;
65
+ /** Whether music is playing */
66
+ isMusicPlaying?: boolean;
67
+ /** Toggle music playback */
68
+ onToggleMusic?: () => void;
69
+ /**
70
+ * Last music toggle timestamp (controlled from parent for PlayIndicator sync).
71
+ * If provided, overrides internal tracking.
72
+ */
73
+ lastMusicToggleTime?: number;
74
+ /** Whether in clean mode (hide overlay) */
75
+ isCleanMode?: boolean;
76
+ /** Handle single tap */
77
+ onTap?: () => void;
78
+ /** Handle double tap (usually for like) */
79
+ onDoubleTap?: () => void;
80
+ /** Handle long press */
81
+ onLongPress?: () => void;
82
+ /** Called when "Read More" is clicked */
83
+ onReadMoreClick?: () => void;
84
+ /** Disable tap gestures */
85
+ disableTap?: boolean;
86
+ /** Enable pinch-to-zoom on images */
87
+ enableZoom?: boolean;
88
+ /** Custom placeholder renderer for images */
89
+ renderPlaceholder?: (index: number) => ReactNode;
90
+ /** Show image counter (1/5) */
91
+ showCounter?: boolean;
92
+ /** Show pagination dots */
93
+ showIndicators?: boolean;
94
+ /** Additional class name */
95
+ className?: string;
96
+ /** Called when swipe direction changes (for gesture locking) */
97
+ onSwipeDirectionChange?: (direction: 'horizontal' | 'vertical' | null) => void;
98
+ /** Children (render prop or ReactNode) */
99
+ children?: ReactNode | ((context: ArticleSlotContextValue) => ReactNode);
100
+ /** Custom styles */
101
+ style?: React.CSSProperties;
102
+ }
103
+ declare function ArticleSlotHeadlessBase({ article, isActive, currentImageIndex: controlledIndex, onImageIndexChange, music, isMusicPlaying, onToggleMusic, lastMusicToggleTime: controlledToggleTime, isCleanMode, onTap, onDoubleTap, onLongPress, onReadMoreClick, disableTap, enableZoom, renderPlaceholder, showCounter, showIndicators, className, onSwipeDirectionChange, children, style, }: ArticleSlotHeadlessProps): ReactElement;
104
+ declare const ArticleSlotHeadless: react.MemoExoticComponent<typeof ArticleSlotHeadlessBase>;
105
+ /**
106
+ * Overlay container for author, caption, actions
107
+ */
108
+ interface ArticleSlotOverlayProps {
109
+ children?: ReactNode;
110
+ className?: string;
111
+ }
112
+ declare function ArticleSlotOverlay({ children, className }: ArticleSlotOverlayProps): ReactElement;
113
+ /**
114
+ * Bottom content area (author, caption, read more)
115
+ */
116
+ interface ArticleSlotBottomProps {
117
+ children?: ReactNode;
118
+ className?: string;
119
+ /** Click handler */
120
+ onClick?: () => void;
121
+ }
122
+ declare function ArticleSlotBottom({ children, className, onClick, }: ArticleSlotBottomProps): ReactElement;
123
+ /**
124
+ * Actions container (right side)
125
+ */
126
+ interface ArticleSlotActionsProps {
127
+ children?: ReactNode;
128
+ className?: string;
129
+ }
130
+ declare function ArticleSlotActions({ children, className }: ArticleSlotActionsProps): ReactElement;
131
+ /**
132
+ * Caption component with optional expansion
133
+ */
134
+ interface ArticleSlotCaptionProps {
135
+ /** Maximum lines to show (default: 2) */
136
+ maxLines?: number;
137
+ /** Whether caption is expanded */
138
+ expanded?: boolean;
139
+ /** Class name */
140
+ className?: string;
141
+ }
142
+ declare function ArticleSlotCaption({ maxLines, expanded, className, }: ArticleSlotCaptionProps): ReactElement;
143
+ /**
144
+ * Read More button
145
+ */
146
+ interface ArticleSlotReadMoreProps {
147
+ /** Button label */
148
+ label?: string;
149
+ /** Class name */
150
+ className?: string;
151
+ /** Click handler (overrides context) */
152
+ onClick?: () => void;
153
+ }
154
+ declare function ArticleSlotReadMore({ label, className, onClick, }: ArticleSlotReadMoreProps): ReactElement;
155
+ /**
156
+ * Music bar component
157
+ */
158
+ interface ArticleSlotMusicProps {
159
+ /** Class name */
160
+ className?: string;
161
+ /**
162
+ * Click handler
163
+ */
164
+ onClick?: () => void;
165
+ /**
166
+ * Custom fallback element when cover image fails to load or is not provided.
167
+ * If not provided, a default vinyl disc SVG will be used.
168
+ *
169
+ * @example
170
+ * ```tsx
171
+ * <ArticleSlotMusic
172
+ * fallbackCover={<MyCustomMusicIcon className="my-icon" />}
173
+ * />
174
+ * ```
175
+ */
176
+ fallbackCover?: ReactNode;
177
+ }
178
+ declare function ArticleSlotMusic({ className, onClick, fallbackCover, }: ArticleSlotMusicProps): ReactElement | null;
179
+ /**
180
+ * Props for ArticleSlotPlayIndicator
181
+ * Uses same props as VideoSlotPlayIndicatorInner, minus context-derived props
182
+ */
183
+ type ArticleSlotPlayIndicatorProps = Omit<VideoSlotPlayIndicatorInnerProps, 'lastUserToggleTime' | 'isPlaying'>;
184
+ /**
185
+ * ArticleSlotPlayIndicator - Shows play/pause icon when user toggles music
186
+ *
187
+ * Reuses the same visual component as VideoSlot but reads from ArticleSlot context.
188
+ * This ensures UI consistency across Video and Article posts.
189
+ *
190
+ * @example
191
+ * ```tsx
192
+ * <ArticleSlotHeadless article={article}>
193
+ * <ArticleSlotPlayIndicator persistWhenPaused />
194
+ * </ArticleSlotHeadless>
195
+ * ```
196
+ */
197
+ declare function ArticleSlotPlayIndicator(props: ArticleSlotPlayIndicatorProps): ReactElement | null;
198
+ declare namespace ArticleSlotPlayIndicator {
199
+ var displayName: string;
200
+ }
201
+
202
+ /**
203
+ * ArticleSlot CSS - Injected at runtime
204
+ *
205
+ * Features:
206
+ * - Full-screen article display
207
+ * - Overlay for author, caption, actions
208
+ * - Music bar (optional)
209
+ * - Read more button
210
+ */
211
+ declare const ARTICLE_SLOT_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 ARTICLE SLOT - 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-article-slot {\n position: relative;\n width: 100%;\n height: 100%;\n overflow: hidden;\n background: var(--sv-article-bg, #000);\n touch-action: pan-y;\n user-select: none;\n -webkit-user-select: none;\n}\n\n.sv-article-slot--active {\n z-index: 1;\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 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-article-slot__images {\n position: absolute;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\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 OVERLAY (Author, Caption, Actions)\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-article-slot__overlay {\n position: absolute;\n inset: 0;\n pointer-events: none;\n display: flex;\n flex-direction: column;\n z-index: 2;\n}\n\n.sv-article-slot__overlay > * {\n pointer-events: auto;\n}\n\n/* Gradient background for better text visibility */\n.sv-article-slot__gradient {\n position: absolute;\n left: 0;\n right: 0;\n pointer-events: none;\n}\n\n.sv-article-slot__gradient--top {\n top: 0;\n height: 120px;\n background: linear-gradient(\n to bottom,\n rgba(0, 0, 0, 0.5) 0%,\n rgba(0, 0, 0, 0.3) 50%,\n transparent 100%\n );\n}\n\n.sv-article-slot__gradient--bottom {\n bottom: 0;\n height: 200px;\n background: linear-gradient(\n to top,\n rgba(0, 0, 0, 0.7) 0%,\n rgba(0, 0, 0, 0.4) 50%,\n transparent 100%\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 TOP BAR (Counter, Badge)\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-article-slot__top-bar {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n padding: var(--sv-article-top-padding, 16px);\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n z-index: 10;\n}\n\n.sv-article-slot__counter {\n padding: 4px 10px;\n background: var(--sv-article-counter-bg, rgba(0, 0, 0, 0.6));\n border-radius: 12px;\n font-size: var(--sv-article-counter-font-size, 12px);\n font-weight: 500;\n color: var(--sv-article-counter-color, #fff);\n}\n\n/* Image badge (e.g., \"Photo\") */\n.sv-article-slot__badge {\n padding: 4px 8px;\n background: var(--sv-article-badge-bg, rgba(255, 255, 255, 0.2));\n border-radius: 4px;\n font-size: var(--sv-article-badge-font-size, 11px);\n font-weight: 500;\n color: var(--sv-article-badge-color, #fff);\n text-transform: uppercase;\n letter-spacing: 0.5px;\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 CONTENT (Author, Caption, Music, Read More)\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-article-slot__bottom {\n position: absolute;\n bottom: calc(var(--sv-safe-area-bottom, 0px) + var(--sv-playlist-bar-offset, 0px));\n left: 0;\n right: var(--sv-article-action-bar-width, 72px);\n padding: var(--sv-article-bottom-padding, 16px);\n display: flex;\n flex-direction: column;\n gap: 12px;\n z-index: 5;\n transition: bottom 0.3s ease-in-out;\n}\n\n/* Author section */\n.sv-article-slot__author {\n display: flex;\n align-items: center;\n gap: 10px;\n}\n\n.sv-article-slot__author-avatar {\n width: var(--sv-article-avatar-size, 40px);\n height: var(--sv-article-avatar-size, 40px);\n border-radius: 50%;\n object-fit: cover;\n border: 2px solid var(--sv-article-avatar-border, rgba(255, 255, 255, 0.3));\n}\n\n.sv-article-slot__author-name {\n font-size: var(--sv-article-author-font-size, 15px);\n font-weight: 600;\n color: var(--sv-article-author-color, #fff);\n text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);\n}\n\n/* Caption section */\n.sv-article-slot__caption {\n font-size: var(--sv-article-caption-font-size, 14px);\n line-height: 1.4;\n color: var(--sv-article-caption-color, #fff);\n text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);\n display: -webkit-box;\n -webkit-line-clamp: var(--sv-article-caption-lines, 2);\n -webkit-box-orient: vertical;\n overflow: hidden;\n}\n\n.sv-article-slot__caption--expanded {\n -webkit-line-clamp: unset;\n overflow: visible;\n}\n\n/* Read more button */\n.sv-article-slot__read-more {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 8px 16px;\n background: var(--sv-article-read-more-bg, rgba(255, 255, 255, 0.2));\n border: none;\n border-radius: 20px;\n font-size: var(--sv-article-read-more-font-size, 13px);\n font-weight: 500;\n color: var(--sv-article-read-more-color, #fff);\n cursor: pointer;\n transition: background 0.2s ease;\n width: fit-content;\n}\n\n.sv-article-slot__read-more:hover {\n background: var(--sv-article-read-more-hover-bg, rgba(255, 255, 255, 0.3));\n}\n\n.sv-article-slot__read-more svg {\n width: 16px;\n height: 16px;\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 (Right side)\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-article-slot__actions {\n position: absolute;\n right: 0;\n bottom: calc(var(--sv-safe-area-bottom, 0px) + var(--sv-playlist-bar-offset, 0px));\n width: var(--sv-article-action-bar-width, 72px);\n padding: var(--sv-article-actions-padding, 16px 8px);\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 20px;\n z-index: 5;\n transition: bottom 0.3s ease-in-out;\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-article-slot__music {\n overflow: hidden;\n aspect-ratio: 1/1;\n background: transparent;\n width: fit-content;\n height: fit-content;\n border: none;\n}\n\n.sv-article-slot__music-cover {\n width: 44px;\n height: 44px;\n object-fit: cover;\n border-radius: 999px;\n border: 2px solid var(--sv-article-music-border, rgba(255, 255, 255, 0.3));\n}\n\n.sv-article-slot__music-cover--playing {\n animation: sv-music-rotate 4s linear infinite;\n}\n\n@keyframes sv-music-rotate {\n from {\n transform: rotate(0deg);\n }\n to {\n transform: rotate(360deg);\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 LIKE ANIMATION\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-article-slot__like-animation {\n position: absolute;\n inset: 0;\n pointer-events: none;\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 CLEAN MODE (Hide 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-article-slot--clean-mode .sv-article-slot__overlay,\n.sv-article-slot--clean-mode .sv-article-slot__top-bar,\n.sv-article-slot--clean-mode .sv-article-slot__bottom,\n.sv-article-slot--clean-mode .sv-article-slot__actions,\n.sv-article-slot--clean-mode .sv-article-slot__gradient {\n opacity: 0;\n transition: opacity 0.3s ease;\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 LOADING STATE\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-article-slot--loading .sv-article-slot__skeleton {\n position: absolute;\n inset: 0;\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-article-shimmer 1.5s infinite;\n}\n\n@keyframes sv-article-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 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-article-slot:focus-visible {\n outline: 2px solid var(--sv-article-focus-color, #4dabff);\n outline-offset: -2px;\n}\n\n.sv-article-slot__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";
212
+
213
+ export { ARTICLE_ACTIVE_ATTR, ARTICLE_ID_ATTR, ARTICLE_SLOT_ACTIVE_CLASS, ARTICLE_SLOT_CLASS, ARTICLE_SLOT_CLEAN_MODE_CLASS, ARTICLE_SLOT_CSS, ArticleSlotActions, type ArticleSlotActionsProps, ArticleSlotBottom, type ArticleSlotBottomProps, ArticleSlotCaption, type ArticleSlotCaptionProps, type ArticleSlotContextValue, ArticleSlotHeadless, type ArticleSlotHeadlessProps, ArticleSlotMusic, type ArticleSlotMusicProps, ArticleSlotOverlay, type ArticleSlotOverlayProps, ArticleSlotPlayIndicator, type ArticleSlotPlayIndicatorProps, ArticleSlotReadMore, type ArticleSlotReadMoreProps, ARTICLE_ACTIVE_ATTR as IMAGE_POST_ACTIVE_ATTR, ARTICLE_ID_ATTR as IMAGE_POST_ID_ATTR, ARTICLE_SLOT_ACTIVE_CLASS as IMAGE_POST_SLOT_ACTIVE_CLASS, ARTICLE_SLOT_CLASS as IMAGE_POST_SLOT_CLASS, ARTICLE_SLOT_CLEAN_MODE_CLASS as IMAGE_POST_SLOT_CLEAN_MODE_CLASS, ARTICLE_SLOT_CSS as IMAGE_POST_SLOT_CSS, ArticleSlotActions as ImagePostSlotActions, type ArticleSlotActionsProps as ImagePostSlotActionsProps, ArticleSlotBottom as ImagePostSlotBottom, type ArticleSlotBottomProps as ImagePostSlotBottomProps, ArticleSlotCaption as ImagePostSlotCaption, type ArticleSlotCaptionProps as ImagePostSlotCaptionProps, type ArticleSlotContextValue as ImagePostSlotContextValue, ArticleSlotHeadless as ImagePostSlotHeadless, type ArticleSlotHeadlessProps as ImagePostSlotHeadlessProps, ArticleSlotMusic as ImagePostSlotMusic, type ArticleSlotMusicProps as ImagePostSlotMusicProps, ArticleSlotOverlay as ImagePostSlotOverlay, type ArticleSlotOverlayProps as ImagePostSlotOverlayProps, ArticleSlotPlayIndicator as ImagePostSlotPlayIndicator, type ArticleSlotPlayIndicatorProps as ImagePostSlotPlayIndicatorProps, ArticleSlotReadMore as ImagePostSlotReadMore, type ArticleSlotReadMoreProps as ImagePostSlotReadMoreProps, useArticleSlotContext, useArticleSlotContext as useImagePostSlotContext, useOptionalArticleSlotContext, useOptionalArticleSlotContext as useOptionalImagePostSlotContext };
@@ -0,0 +1 @@
1
+ export { ARTICLE_ACTIVE_ATTR, ARTICLE_ID_ATTR, ARTICLE_SLOT_ACTIVE_CLASS, ARTICLE_SLOT_CLASS, ARTICLE_SLOT_CLEAN_MODE_CLASS, ARTICLE_SLOT_CSS, ArticleSlotActions, ArticleSlotBottom, ArticleSlotCaption, ArticleSlotHeadless, ArticleSlotMusic, ArticleSlotOverlay, ArticleSlotPlayIndicator, ArticleSlotReadMore, ARTICLE_ACTIVE_ATTR as IMAGE_POST_ACTIVE_ATTR, ARTICLE_ID_ATTR as IMAGE_POST_ID_ATTR, ARTICLE_SLOT_ACTIVE_CLASS as IMAGE_POST_SLOT_ACTIVE_CLASS, ARTICLE_SLOT_CLASS as IMAGE_POST_SLOT_CLASS, ARTICLE_SLOT_CLEAN_MODE_CLASS as IMAGE_POST_SLOT_CLEAN_MODE_CLASS, ARTICLE_SLOT_CSS as IMAGE_POST_SLOT_CSS, ArticleSlotActions as ImagePostSlotActions, ArticleSlotBottom as ImagePostSlotBottom, ArticleSlotCaption as ImagePostSlotCaption, ArticleSlotHeadless as ImagePostSlotHeadless, ArticleSlotMusic as ImagePostSlotMusic, ArticleSlotOverlay as ImagePostSlotOverlay, ArticleSlotPlayIndicator as ImagePostSlotPlayIndicator, ArticleSlotReadMore as ImagePostSlotReadMore, useArticleSlotContext, useArticleSlotContext as useImagePostSlotContext, useOptionalArticleSlotContext, useOptionalArticleSlotContext as useOptionalImagePostSlotContext } from '../../chunk-BNI7CYRI.js';
@@ -1 +1 @@
1
- export { AUTHOR_INFO_CSS, AuthorAvatar, AuthorDescription, AuthorInfoContext, AuthorInfoHeadless, AuthorName, FollowButton, useAuthorInfoContext, useOptionalAuthorInfoContext } from '../../chunk-2FSDVYER.js';
1
+ export { AUTHOR_INFO_CSS, AuthorAvatar, AuthorDescription, AuthorInfoContext, AuthorInfoHeadless, AuthorName, FollowButton, useAuthorInfoContext, useOptionalAuthorInfoContext } from '../../chunk-3OB3OVYR.js';
@@ -0,0 +1,87 @@
1
+ import * as react from 'react';
2
+ import { ReactNode, ReactElement } from 'react';
3
+
4
+ interface BottomSheetContextValue {
5
+ isOpen: boolean;
6
+ onClose: () => void;
7
+ }
8
+ /**
9
+ * Hook to access bottom sheet context
10
+ * Must be used within BottomSheetHeadless
11
+ */
12
+ declare function useBottomSheetContext(): BottomSheetContextValue;
13
+ interface BottomSheetHeadlessProps {
14
+ /** Whether sheet is open */
15
+ isOpen: boolean;
16
+ /** Close callback */
17
+ onClose: () => void;
18
+ /** Sheet content */
19
+ children: ReactNode;
20
+ /** Sheet height (CSS value: "auto", "50vh", "80%", "400px") */
21
+ height?: string;
22
+ /** Root class name for sheet */
23
+ className?: string;
24
+ /** Backdrop class name */
25
+ backdropClassName?: string;
26
+ /** Content wrapper class name */
27
+ contentClassName?: string;
28
+ /** Close on backdrop click (default: true) */
29
+ closeOnBackdropClick?: boolean;
30
+ /** Close on escape key (default: true) */
31
+ closeOnEscape?: boolean;
32
+ /** Show drag handle (default: false) */
33
+ showDragHandle?: boolean;
34
+ /** Enable drag-to-dismiss (default: true) */
35
+ enableDragToDismiss?: boolean;
36
+ /** Drag threshold to close in pixels (default: 150) */
37
+ dragCloseThreshold?: number;
38
+ /** Custom aria-label */
39
+ ariaLabel?: string;
40
+ /** Custom z-index */
41
+ zIndex?: number;
42
+ /** Animation duration in ms (default: 300) */
43
+ animationDuration?: number;
44
+ /**
45
+ * CSS selector for drag handle element(s).
46
+ * Default: ".sv-bottom-sheet__handle"
47
+ * Example: ".sv-comment-sheet__header" for CommentSheet
48
+ */
49
+ dragHandleSelector?: string;
50
+ /**
51
+ * CSS selector for scroll container (for overscroll-to-dismiss).
52
+ * Default: ".sv-bottom-sheet__content"
53
+ * Example: ".sv-comment-sheet__list" for CommentSheet
54
+ */
55
+ scrollContainerSelector?: string;
56
+ /**
57
+ * CSS selector for elements that should NOT trigger drag.
58
+ * Example: ".sv-comment-sheet__input-container" for CommentSheet
59
+ */
60
+ dragExcludeSelector?: string;
61
+ /**
62
+ * Callback to lock/unlock global gestures (e.g., Feed swipe).
63
+ * Used to replace global touchmove blockers with centralized lock.
64
+ */
65
+ onGestureLock?: (isLocked: boolean) => void;
66
+ }
67
+ declare function BottomSheetHeadlessComponent({ isOpen, onClose, children, height, className, backdropClassName, contentClassName, closeOnBackdropClick, closeOnEscape, showDragHandle, enableDragToDismiss, dragCloseThreshold, ariaLabel, zIndex, animationDuration, dragHandleSelector, scrollContainerSelector, dragExcludeSelector, onGestureLock, }: BottomSheetHeadlessProps): ReactElement | null;
68
+ declare const BottomSheetHeadless: react.MemoExoticComponent<typeof BottomSheetHeadlessComponent>;
69
+
70
+ /**
71
+ * BottomSheet CSS
72
+ *
73
+ * Base bottom sheet component styles.
74
+ * Features:
75
+ * - Portal-based rendering support
76
+ * - Slide-up/down animations
77
+ * - Backdrop with fade
78
+ * - Drag handle
79
+ * - iOS-safe scroll lock via body class
80
+ */
81
+ declare const BOTTOM_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\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 /* Bottom sheet theming */\n --sv-sheet-bg: #ffffff;\n --sv-sheet-backdrop-bg: rgba(0, 0, 0, 0.5);\n --sv-sheet-handle-bg: rgba(0, 0, 0, 0.2);\n --sv-sheet-border-radius: 24px;\n --sv-sheet-z-index: 1000;\n --sv-sheet-animation-duration: 300ms;\n --sv-sheet-animation-easing: cubic-bezier(0.32, 0.72, 0, 1);\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\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-bottom-sheet-backdrop {\n position: fixed;\n inset: 0;\n background: var(--sv-sheet-backdrop-bg);\n z-index: 50;\n opacity: 0;\n visibility: hidden;\n pointer-events: none;\n transition: \n opacity var(--sv-sheet-animation-duration) ease,\n visibility 0s linear var(--sv-sheet-animation-duration);\n}\n\n.sv-bottom-sheet-backdrop[data-state=\"open\"] {\n opacity: 1;\n visibility: visible;\n pointer-events: auto;\n transition: \n opacity var(--sv-sheet-animation-duration) ease,\n visibility 0s linear 0s;\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 SHEET 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/* Keyframes */\n@keyframes sv-sheet-slide-up {\n from { transform: translateY(100vh); }\n to { transform: translateY(0); }\n}\n\n@keyframes sv-sheet-slide-down {\n from { transform: translateY(0); }\n to { transform: translateY(100vh); }\n}\n\n.sv-bottom-sheet {\n position: fixed;\n left: 0;\n right: 0;\n bottom: 0;\n background: var(--sv-sheet-bg);\n border-radius: var(--sv-sheet-border-radius) var(--sv-sheet-border-radius) 0 0;\n z-index: 51;\n display: flex;\n flex-direction: column;\n max-height: var(--sv-sheet-max-height, 80vh);\n transform: translateY(100vh);\n overflow: hidden;\n touch-action: pan-y;\n isolation: isolate;\n pointer-events: none;\n will-change: transform;\n outline: none;\n}\n\n.sv-bottom-sheet[data-state=\"open\"] {\n transform: translateY(0);\n pointer-events: auto;\n animation: sv-sheet-slide-up var(--sv-sheet-animation-duration) \n var(--sv-sheet-animation-easing) forwards;\n}\n\n.sv-bottom-sheet[data-state=\"closing\"] {\n pointer-events: none;\n animation: sv-sheet-slide-down var(--sv-sheet-animation-duration) \n var(--sv-sheet-animation-easing) forwards !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 DRAG HANDLE\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-bottom-sheet__handle {\n display: flex;\n justify-content: center;\n padding: 12px 0 8px;\n cursor: grab;\n touch-action: none;\n flex-shrink: 0;\n}\n\n.sv-bottom-sheet__handle:active {\n cursor: grabbing;\n}\n\n.sv-bottom-sheet__handle-bar {\n width: 36px;\n height: 4px;\n background: var(--sv-sheet-handle-bg);\n border-radius: 2px;\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 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 */\n\n.sv-bottom-sheet__content {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n -webkit-overflow-scrolling: touch;\n overscroll-behavior: contain;\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 BODY SCROLL LOCK\n Disable scroll on underlying content when sheet is open\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\nbody.sv-bottom-sheet-open {\n overflow: hidden !important;\n position: fixed !important;\n width: 100% !important;\n /* top is set dynamically via JS to preserve scroll position */\n}\n\n/* CRITICAL: Disable VirtualSlider/VideoFeed swipe when sheet is open */\nbody.sv-bottom-sheet-open .sv-slider,\nbody.sv-bottom-sheet-open .sv-video-feed {\n pointer-events: none !important;\n touch-action: none !important;\n}\n\nbody.sv-bottom-sheet-open .sv-bottom-sheet,\nbody.sv-bottom-sheet-open .sv-bottom-sheet-backdrop {\n touch-action: auto !important;\n}\n";
82
+ /**
83
+ * Inject BottomSheet CSS into document
84
+ */
85
+ declare function injectBottomSheetCSS(): void;
86
+
87
+ export { BOTTOM_SHEET_CSS, type BottomSheetContextValue, BottomSheetHeadless, type BottomSheetHeadlessProps, injectBottomSheetCSS, useBottomSheetContext };
@@ -0,0 +1 @@
1
+ export { BOTTOM_SHEET_CSS, BottomSheetHeadless, injectBottomSheetCSS, useBottomSheetContext } from '../../chunk-UYBQTE4M.js';
@@ -0,0 +1,60 @@
1
+ import * as react from 'react';
2
+ import { ReactNode, ReactElement } from 'react';
3
+
4
+ interface CleanModeOverlayHeadlessProps {
5
+ /** Whether clean mode is active */
6
+ isActive: boolean;
7
+ /** Whether video is playing */
8
+ isPlaying: boolean;
9
+ /** Current playback speed */
10
+ speed: number;
11
+ /** Current playback time in seconds */
12
+ currentTime: number;
13
+ /** Total duration in seconds */
14
+ duration: number;
15
+ /** Callback to toggle play/pause */
16
+ onTogglePlay: () => void;
17
+ /** Callback when speed changes */
18
+ onSpeedChange: (speed: number) => void;
19
+ /** Callback when user seeks */
20
+ onSeek: (time: number) => void;
21
+ /** Callback to exit clean mode */
22
+ onExit: () => void;
23
+ /** Available speed options (default: [0.5, 0.75, 1, 1.25, 1.5, 2]) */
24
+ speeds?: readonly number[];
25
+ /** Auto-hide delay in ms (default: 3000, 0 to disable) */
26
+ hideDelay?: number;
27
+ /** Custom exit icon */
28
+ exitIcon?: ReactNode;
29
+ /** Custom play icon */
30
+ playIcon?: ReactNode;
31
+ /** Custom pause icon */
32
+ pauseIcon?: ReactNode;
33
+ /** Custom class name */
34
+ className?: string;
35
+ /** Aria label for the overlay */
36
+ ariaLabel?: string;
37
+ }
38
+ declare function CleanModeOverlayHeadlessComponent({ isActive, isPlaying, speed, currentTime, duration, onTogglePlay, onSpeedChange, onSeek, onExit, speeds, hideDelay, exitIcon, playIcon, pauseIcon, className, ariaLabel, }: CleanModeOverlayHeadlessProps): ReactElement | null;
39
+ declare const CleanModeOverlayHeadless: react.MemoExoticComponent<typeof CleanModeOverlayHeadlessComponent>;
40
+
41
+ /**
42
+ * CleanModeOverlay CSS-in-TS
43
+ *
44
+ * Floating control bar for clean mode (TikTok-style).
45
+ * Layout: [Exit] ─── [Progress Bar] ─── [Play/Pause | Speed]
46
+ *
47
+ * NOTE: This CSS is injected WITHOUT @layer to ensure it resists
48
+ * global resets like `* { margin: 0; padding: 0; }`.
49
+ * Host app can still override via higher specificity selectors.
50
+ */
51
+ declare const CLEAN_MODE_OVERLAY_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\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-clean-mode-container {\n /* Colors */\n --sv-clean-mode-bg: rgba(40, 40, 40, 0.85);\n --sv-clean-mode-text: rgba(255, 255, 255, 0.95);\n --sv-clean-mode-divider: rgba(255, 255, 255, 0.2);\n --sv-clean-mode-progress-bg: rgba(255, 255, 255, 0.3);\n --sv-clean-mode-progress-fill: rgba(255, 255, 255, 0.9);\n --sv-clean-mode-progress-thumb: #ffffff;\n \n /* Layout */\n --sv-clean-mode-radius: 50px;\n --sv-clean-mode-button-size: 48px;\n --sv-clean-mode-progress-height: 4px;\n \n /* Animation */\n --sv-clean-mode-duration: 200ms;\n --sv-clean-mode-easing: cubic-bezier(0.4, 0, 0.2, 1);\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 MAIN CONTAINER - Full width bar at 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 */\n\n.sv-clean-mode-container {\n position: absolute;\n bottom: 24px;\n left: 16px;\n right: 16px;\n z-index: 80;\n \n display: flex;\n align-items: center;\n gap: 12px;\n margin: 0;\n padding: 0;\n \n /* Animation */\n opacity: 1;\n transition: opacity var(--sv-clean-mode-duration) var(--sv-clean-mode-easing);\n \n /* Prevent text selection */\n user-select: none;\n -webkit-user-select: none;\n pointer-events: none;\n}\n\n.sv-clean-mode-container[data-hidden=\"true\"] {\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\n LEFT PILL - Exit button\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-clean-mode-left {\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n \n width: var(--sv-clean-mode-button-size);\n height: var(--sv-clean-mode-button-size);\n margin: 0;\n padding: 0;\n \n background: var(--sv-clean-mode-bg);\n border-radius: var(--sv-clean-mode-radius);\n backdrop-filter: blur(12px);\n -webkit-backdrop-filter: blur(12px);\n \n pointer-events: auto;\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 CENTER - Progress 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 */\n\n.sv-clean-mode-center {\n flex: 1;\n min-width: 0;\n display: flex;\n align-items: center;\n margin: 0;\n padding: 0;\n \n pointer-events: auto;\n}\n\n.sv-clean-mode-progress {\n position: relative;\n width: 100%;\n height: 24px;\n margin: 0;\n padding: 0;\n display: flex;\n align-items: center;\n cursor: pointer;\n touch-action: none;\n}\n\n.sv-clean-mode-progress-track {\n position: absolute;\n left: 0;\n right: 0;\n height: var(--sv-clean-mode-progress-height);\n margin: 0;\n padding: 0;\n background: var(--sv-clean-mode-progress-bg);\n border-radius: calc(var(--sv-clean-mode-progress-height) / 2);\n overflow: hidden;\n}\n\n.sv-clean-mode-progress-fill {\n height: 100%;\n margin: 0;\n padding: 0;\n background: var(--sv-clean-mode-progress-fill);\n border-radius: inherit;\n transition: width 100ms linear;\n}\n\n.sv-clean-mode-progress-thumb {\n position: absolute;\n width: 14px;\n height: 14px;\n margin: 0;\n padding: 0;\n background: var(--sv-clean-mode-progress-thumb);\n border-radius: 50%;\n transform: translateX(-50%);\n box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3);\n opacity: 0;\n transition: opacity 150ms ease;\n}\n\n.sv-clean-mode-progress:hover .sv-clean-mode-progress-thumb,\n.sv-clean-mode-progress[data-dragging=\"true\"] .sv-clean-mode-progress-thumb {\n opacity: 1;\n}\n\n.sv-clean-mode-progress[data-dragging=\"true\"] .sv-clean-mode-progress-track {\n height: 6px;\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 RIGHT PILL - Play/Pause + Speed\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-clean-mode-right {\n display: flex;\n align-items: center;\n flex-shrink: 0;\n \n height: var(--sv-clean-mode-button-size);\n margin: 0;\n padding: 0 4px;\n \n background: var(--sv-clean-mode-bg);\n border-radius: var(--sv-clean-mode-radius);\n backdrop-filter: blur(12px);\n -webkit-backdrop-filter: blur(12px);\n \n pointer-events: auto;\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 BUTTONS\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-clean-mode-button {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n \n height: 40px;\n margin: 0;\n padding: 0 14px;\n \n background: transparent;\n border: none;\n \n color: var(--sv-clean-mode-text);\n font-size: 15px;\n font-weight: 600;\n white-space: nowrap;\n \n cursor: pointer;\n transition: opacity 150ms ease;\n}\n\n.sv-clean-mode-button:active {\n opacity: 0.7;\n}\n\n.sv-clean-mode-button svg {\n width: 22px;\n height: 22px;\n margin: 0;\n padding: 0;\n flex-shrink: 0;\n}\n\n/* Exit button - icon only */\n.sv-clean-mode-exit {\n width: 40px;\n height: 40px;\n padding: 0;\n}\n\n.sv-clean-mode-exit svg {\n width: 20px;\n height: 20px;\n}\n\n/* Play/Pause button - icon only */\n.sv-clean-mode-play {\n width: 40px;\n padding: 0;\n}\n\n/* Speed button */\n.sv-clean-mode-speed {\n padding: 0 16px 0 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\n DIVIDER\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-clean-mode-divider {\n width: 1px;\n height: 24px;\n margin: 0;\n padding: 0;\n background: var(--sv-clean-mode-divider);\n flex-shrink: 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\n TAP AREA (for showing hidden 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 */\n\n.sv-clean-mode-tap-area {\n position: absolute;\n inset: 0;\n z-index: 70;\n margin: 0;\n padding: 0;\n cursor: pointer;\n}\n\n/* Hide tap area when bar is visible */\n.sv-clean-mode-tap-area[data-visible=\"true\"] {\n pointer-events: none;\n}\n";
52
+ /**
53
+ * Inject CleanModeOverlay CSS into document.
54
+ *
55
+ * NOTE: Injected WITHOUT @layer (layered: false) so it resists
56
+ * global resets. Host app can still override with higher specificity.
57
+ */
58
+ declare function injectCleanModeOverlayCSS(): void;
59
+
60
+ export { CLEAN_MODE_OVERLAY_CSS, CleanModeOverlayHeadless, type CleanModeOverlayHeadlessProps, injectCleanModeOverlayCSS };
@@ -0,0 +1 @@
1
+ export { CLEAN_MODE_OVERLAY_CSS, CleanModeOverlayHeadless, injectCleanModeOverlayCSS } from '../../chunk-QUEJHA24.js';
@@ -1,4 +1,4 @@
1
- export { n as COMMENT_SHEET_CSS, f as CommentInput, g as CommentInputProps, h as CommentItemComponent, i as CommentItemProps, d as CommentList, e as CommentListProps, C as CommentSheet, j as CommentSheetContext, l as CommentSheetContextValue, a as CommentSheetHeadless, b as CommentSheetHeadlessProps, m as CommentSheetI18n, R as ReplyTarget, S as SheetHeader, c as SheetHeaderProps, u as useCommentSheetContext, k as useOptionalCommentSheetContext } from '../../CommentSheet.css-BeCrEaUG.js';
1
+ export { C as COMMENT_SHEET_CSS, a as CommentInput, b as CommentInputProps, c as CommentItemComponent, d as CommentItemProps, e as CommentList, f as CommentListProps, g as CommentSheet, h as CommentSheetContext, i as CommentSheetContextValue, j as CommentSheetHeadless, k as CommentSheetHeadlessProps, l as CommentSheetI18n, R as ReplyTarget, S as SheetHeader, m as SheetHeaderProps, u as useCommentSheetContext, n as useOptionalCommentSheetContext } from '../../CommentSheet.css-DuBy01rU.js';
2
2
  import * as react from 'react';
3
3
  import { ReactNode, ReactElement } from 'react';
4
4
  import { CommentItem, ReplyItem } from '@xhub-short/contracts';
@@ -1 +1 @@
1
- export { COMMENT_SHEET_CSS, CommentInput, CommentItemComponent, CommentItemSkeleton, CommentList, CommentListSkeleton, CommentMenu, CommentSheet, CommentSheetContext, CommentSheetHeadless, DeleteConfirmDialog, SheetHeader, useCommentMenuContext, useCommentSheetContext, useOptionalCommentSheetContext } from '../../chunk-FNXTPQ6L.js';
1
+ export { COMMENT_SHEET_CSS, CommentInput, CommentItemComponent, CommentItemSkeleton, CommentList, CommentListSkeleton, CommentMenu, CommentSheet, CommentSheetContext, CommentSheetHeadless, DeleteConfirmDialog, SheetHeader, useCommentMenuContext, useCommentSheetContext, useOptionalCommentSheetContext } from '../../chunk-IC2KUU4V.js';