@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
@@ -1,357 +0,0 @@
1
- import { VirtualSlider } from './chunk-AQHD6LPS.js';
2
- import { clsx2 } from './chunk-EDWS2IPH.js';
3
- import { injectComponentCSS } from './chunk-RMLTPW5S.js';
4
- import { createContext, useContext, useInsertionEffect, useRef, useMemo, useCallback } from 'react';
5
- import { jsx, jsxs } from 'react/jsx-runtime';
6
-
7
- // src/components/VideoFeed/VideoFeed.css.ts
8
- var VIDEO_FEED_CSS = `
9
- /* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550
10
- * VideoFeed Styles
11
- * \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */
12
-
13
- .sv-video-feed {
14
- position: relative;
15
- width: 100%;
16
- height: 100%;
17
- overflow: hidden;
18
- background: var(--sv-bg-primary, #000);
19
- touch-action: pan-y;
20
- user-select: none;
21
- -webkit-user-select: none;
22
- }
23
-
24
- /* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
25
- * Feed Container (holds all slots)
26
- * \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
27
-
28
- .sv-video-feed__container {
29
- position: relative;
30
- width: 100%;
31
- height: 100%;
32
- will-change: transform;
33
- }
34
-
35
- /* Smooth transition when not swiping */
36
- .sv-video-feed__container--snapping {
37
- transition: transform 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94);
38
- }
39
-
40
- /* No transition during swipe for immediate feedback */
41
- .sv-video-feed__container--swiping {
42
- transition: none;
43
- }
44
-
45
- /* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
46
- * Video Slot Wrapper
47
- * \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
48
-
49
- .sv-video-feed__slot {
50
- position: absolute;
51
- top: 0;
52
- left: 0;
53
- width: 100%;
54
- height: 100%;
55
- will-change: transform, opacity;
56
- backface-visibility: hidden;
57
- -webkit-backface-visibility: hidden;
58
- }
59
-
60
- /* Active slot */
61
- .sv-video-feed__slot--active {
62
- z-index: 2;
63
- }
64
-
65
- /* Adjacent slots (for preview) */
66
- .sv-video-feed__slot--adjacent {
67
- z-index: 1;
68
- pointer-events: none;
69
- }
70
-
71
- /* Transition for smooth snap animations (when not swiping) */
72
- .sv-video-feed__slot--transitioning {
73
- transition: transform 0.175s cubic-bezier(0.25, 0.46, 0.45, 0.94),
74
- opacity 0.2s ease;
75
- }
76
-
77
- /* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
78
- * Loading State
79
- * \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
80
-
81
- .sv-video-feed__loading {
82
- position: absolute;
83
- top: 50%;
84
- left: 50%;
85
- transform: translate(-50%, -50%);
86
- display: flex;
87
- flex-direction: column;
88
- align-items: center;
89
- gap: var(--sv-spacing-md, 16px);
90
- color: var(--sv-text-secondary, #999);
91
- }
92
-
93
- .sv-video-feed__loading-spinner {
94
- width: 32px;
95
- height: 32px;
96
- border: 3px solid rgba(255, 255, 255, 0.2);
97
- border-top-color: var(--sv-color-primary, #fe2c55);
98
- border-radius: 50%;
99
- animation: sv-feed-spinner 0.8s linear infinite;
100
- }
101
-
102
- @keyframes sv-feed-spinner {
103
- to {
104
- transform: rotate(360deg);
105
- }
106
- }
107
-
108
- .sv-video-feed__loading-text {
109
- font-size: var(--sv-font-size-sm, 13px);
110
- font-family: var(--sv-font-family, 'Urbanist', sans-serif);
111
- }
112
-
113
- /* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
114
- * Empty State
115
- * \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
116
-
117
- .sv-video-feed__empty {
118
- position: absolute;
119
- top: 50%;
120
- left: 50%;
121
- transform: translate(-50%, -50%);
122
- text-align: center;
123
- color: var(--sv-text-secondary, #999);
124
- font-family: var(--sv-font-family, 'Urbanist', sans-serif);
125
- }
126
-
127
- .sv-video-feed__empty-icon {
128
- font-size: 48px;
129
- margin-bottom: var(--sv-spacing-md, 16px);
130
- }
131
-
132
- .sv-video-feed__empty-text {
133
- font-size: var(--sv-font-size-md, 14px);
134
- }
135
-
136
- /* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
137
- * End of Feed
138
- * Note: Positioned outside container but above slots. Uses safe-area-inset
139
- * to avoid being covered by device notch/home indicator.
140
- * \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
141
-
142
- .sv-video-feed__end {
143
- position: absolute;
144
- /* Safe bottom positioning - accounts for device UI */
145
- bottom: calc(var(--sv-spacing-xl, 32px) + env(safe-area-inset-bottom, 0px));
146
- left: 50%;
147
- transform: translateX(-50%);
148
- z-index: 10; /* Above slots (z-index 1-2) */
149
- padding: var(--sv-spacing-sm, 8px) var(--sv-spacing-md, 16px);
150
- background: rgba(0, 0, 0, 0.7);
151
- backdrop-filter: blur(8px);
152
- -webkit-backdrop-filter: blur(8px);
153
- border-radius: var(--sv-border-radius-md, 8px);
154
- color: var(--sv-text-secondary, #999);
155
- font-size: var(--sv-font-size-sm, 13px);
156
- font-family: var(--sv-font-family, 'Urbanist', sans-serif);
157
- pointer-events: none; /* Don't block interactions */
158
- animation: sv-feed-end-fade-in 0.3s ease-out;
159
- }
160
-
161
- @keyframes sv-feed-end-fade-in {
162
- from {
163
- opacity: 0;
164
- transform: translateX(-50%) translateY(10px);
165
- }
166
- to {
167
- opacity: 1;
168
- transform: translateX(-50%) translateY(0);
169
- }
170
- }
171
-
172
- /* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
173
- * Reduced Motion
174
- * \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
175
-
176
- @media (prefers-reduced-motion: reduce) {
177
- .sv-video-feed__container--snapping {
178
- transition: none;
179
- }
180
-
181
- .sv-video-feed__loading-spinner {
182
- animation: none;
183
- }
184
- }
185
- `;
186
- var VideoFeedContext = createContext(null);
187
- function useVideoFeedContext() {
188
- const context = useContext(VideoFeedContext);
189
- if (!context) {
190
- throw new Error("useVideoFeedContext must be used within a VideoFeed");
191
- }
192
- return context;
193
- }
194
- function useOptionalVideoFeedContext() {
195
- return useContext(VideoFeedContext);
196
- }
197
- function VideoFeedLoading({ text = "Loading..." }) {
198
- return /* @__PURE__ */ jsxs("div", { className: "sv-video-feed__loading", children: [
199
- /* @__PURE__ */ jsx("div", { className: "sv-video-feed__loading-spinner" }),
200
- /* @__PURE__ */ jsx("div", { className: "sv-video-feed__loading-text", children: text })
201
- ] });
202
- }
203
- function VideoFeedEmpty({ text = "No videos" }) {
204
- return /* @__PURE__ */ jsxs("div", { className: "sv-video-feed__empty", children: [
205
- /* @__PURE__ */ jsx("div", { className: "sv-video-feed__empty-icon", children: "\u{1F4ED}" }),
206
- /* @__PURE__ */ jsx("div", { className: "sv-video-feed__empty-text", children: text })
207
- ] });
208
- }
209
- function VideoFeedEnd({ text = "You've reached the end" }) {
210
- return /* @__PURE__ */ jsx("div", { className: "sv-video-feed__end", "aria-live": "polite", children: text });
211
- }
212
- function VideoFeedHeadless({
213
- feedState,
214
- swipeState,
215
- height,
216
- className,
217
- renderSlot,
218
- onIndexChange,
219
- onEndReached,
220
- endReachedThreshold = 2,
221
- bufferSize = 1,
222
- loadingText = "Loading...",
223
- emptyText = "No videos",
224
- endText = "You've reached the end",
225
- disableInlineTransforms = false
226
- }) {
227
- useInsertionEffect(() => {
228
- return injectComponentCSS("sv-video-feed", VIDEO_FEED_CSS);
229
- }, []);
230
- const { videos, isLoading, hasMore } = feedState;
231
- const { activeIndex, isSwiping, dragOffset, goToIndex } = swipeState;
232
- const containerHeightRef = useRef(
233
- typeof window !== "undefined" ? window.innerHeight : 800
234
- );
235
- const contextValue = useMemo(
236
- () => ({
237
- videos,
238
- activeIndex: Math.max(0, Math.min(videos.length - 1, activeIndex)),
239
- isSwiping,
240
- dragOffset,
241
- containerHeight: containerHeightRef.current,
242
- goToIndex,
243
- totalCount: videos.length
244
- }),
245
- [videos, activeIndex, isSwiping, dragOffset, goToIndex]
246
- );
247
- const keyExtractor = useCallback((video) => video.id, []);
248
- const renderItem = useCallback(
249
- (video, index, _isActive) => {
250
- return renderSlot(video, index);
251
- },
252
- [renderSlot]
253
- );
254
- const loadingComponent = useMemo(() => /* @__PURE__ */ jsx(VideoFeedLoading, { text: loadingText }), [loadingText]);
255
- const emptyComponent = useMemo(() => /* @__PURE__ */ jsx(VideoFeedEmpty, { text: emptyText }), [emptyText]);
256
- const endComponent = useMemo(() => /* @__PURE__ */ jsx(VideoFeedEnd, { text: endText }), [endText]);
257
- const sliderProps = {
258
- // Required
259
- items: videos,
260
- keyExtractor,
261
- renderItem,
262
- // Swipe state
263
- activeIndex,
264
- isSwiping,
265
- dragOffset,
266
- goToIndex,
267
- // Callbacks
268
- onIndexChange,
269
- onEndReached,
270
- endReachedThreshold,
271
- bufferSize,
272
- // Loading states
273
- isLoading,
274
- hasMore,
275
- // Custom UI (video-specific styling)
276
- loadingComponent,
277
- emptyComponent,
278
- endComponent,
279
- // Styling - use sv-video-feed classes instead of sv-slider
280
- height,
281
- className: clsx2("sv-video-feed", className),
282
- disableInlineTransforms
283
- };
284
- return /* @__PURE__ */ jsx(VideoFeedContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx(VirtualSlider, { ...sliderProps }) });
285
- }
286
- VideoFeedHeadless.displayName = "VideoFeedHeadless";
287
- function useVideoFeedPosition(options) {
288
- const {
289
- totalCount,
290
- activeIndex,
291
- containerHeight,
292
- dragOffset,
293
- isSwiping,
294
- isResizing = false,
295
- bufferSize = 1
296
- } = options;
297
- return useMemo(() => {
298
- if (totalCount === 0) {
299
- return {
300
- slots: [],
301
- scrollOffset: 0,
302
- isAtStart: true,
303
- isAtLastIndex: true,
304
- clampedActiveIndex: 0
305
- };
306
- }
307
- const clampedActiveIndex = Math.max(0, Math.min(totalCount - 1, activeIndex));
308
- const slots = [];
309
- const startIndex = Math.max(0, clampedActiveIndex - bufferSize);
310
- const endIndex = Math.min(totalCount - 1, clampedActiveIndex + bufferSize);
311
- const baseOffset = -clampedActiveIndex * containerHeight;
312
- const scrollOffset = baseOffset + dragOffset;
313
- for (let i = startIndex; i <= endIndex; i++) {
314
- const signedDistance = i - clampedActiveIndex;
315
- const distance = Math.abs(signedDistance);
316
- const isActive = i === clampedActiveIndex;
317
- const top = i * containerHeight;
318
- const transform = `translateY(${top + scrollOffset}px)`;
319
- let opacity = 1;
320
- if (!isActive && !isResizing) {
321
- opacity = isSwiping ? 0.7 : 0.3;
322
- }
323
- slots.push({
324
- index: i,
325
- top,
326
- isActive,
327
- distance,
328
- signedDistance,
329
- transform,
330
- opacity
331
- });
332
- }
333
- return {
334
- slots,
335
- scrollOffset,
336
- isAtStart: clampedActiveIndex === 0,
337
- isAtLastIndex: clampedActiveIndex >= totalCount - 1,
338
- clampedActiveIndex
339
- };
340
- }, [totalCount, activeIndex, containerHeight, dragOffset, isSwiping, isResizing, bufferSize]);
341
- }
342
- function getSlotIndexFromPosition(yPosition, containerHeight, totalCount) {
343
- if (totalCount === 0 || containerHeight === 0) {
344
- return 0;
345
- }
346
- const rawIndex = Math.round(-yPosition / containerHeight);
347
- return Math.max(0, Math.min(totalCount - 1, rawIndex));
348
- }
349
-
350
- // src/components/VideoFeed/constants.ts
351
- var SLOT_INDEX_ATTR = "data-slot-index";
352
- var SLOT_ACTIVE_ATTR = "data-slot-active";
353
- var SLOT_INDEX_DATASET_KEY = "slotIndex";
354
- var SLOT_ACTIVE_DATASET_KEY = "slotActive";
355
- var VIDEO_FEED_CLASS_PREFIX = "sv-video-feed";
356
-
357
- export { SLOT_ACTIVE_ATTR, SLOT_ACTIVE_DATASET_KEY, SLOT_INDEX_ATTR, SLOT_INDEX_DATASET_KEY, VIDEO_FEED_CLASS_PREFIX, VIDEO_FEED_CSS, VideoFeedContext, VideoFeedHeadless, getSlotIndexFromPosition, useOptionalVideoFeedContext, useVideoFeedContext, useVideoFeedPosition };