@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.
Files changed (76) hide show
  1. package/dist/CommentSheet.css-DyEc3Sro.d.ts +217 -0
  2. package/dist/VideoSlotPlayIndicator-DPs8Xt5C.d.ts +51 -0
  3. package/dist/chunk-3OB3OVYR.js +349 -0
  4. package/dist/{chunk-WKX2WBVO.js → chunk-3XPJHUYL.js} +1 -39
  5. package/dist/chunk-4RIMQOBR.js +58 -0
  6. package/dist/chunk-4TUBNA2X.js +180 -0
  7. package/dist/{chunk-4YDIRPIN.js → chunk-ANCP53F3.js} +3 -3
  8. package/dist/{chunk-UXMA4KJZ.js → chunk-CAWE42LH.js} +5 -3
  9. package/dist/{chunk-ANGBSV7L.js → chunk-CIIZ3IHV.js} +10 -5
  10. package/dist/chunk-DR7KR7OT.js +103 -0
  11. package/dist/chunk-DXLCQ4FH.js +102 -0
  12. package/dist/chunk-EDWS2IPH.js +1 -0
  13. package/dist/chunk-FR7UQSZP.js +570 -0
  14. package/dist/chunk-IWSBYOSS.js +91 -0
  15. package/dist/chunk-JEY6R4KJ.js +334 -0
  16. package/dist/chunk-KMJ3PQ7M.js +1262 -0
  17. package/dist/chunk-MFJS65C5.js +368 -0
  18. package/dist/{chunk-HW4LXTFT.js → chunk-OM4L7RE5.js} +18 -6
  19. package/dist/chunk-PBIH2F2Q.js +344 -0
  20. package/dist/chunk-PJ4NMVMY.js +326 -0
  21. package/dist/chunk-Q6MG7AVG.js +531 -0
  22. package/dist/chunk-QCKVF2DR.js +713 -0
  23. package/dist/chunk-QCRRF76W.js +75 -0
  24. package/dist/chunk-QUEJHA24.js +508 -0
  25. package/dist/chunk-VXW7AOGM.js +285 -0
  26. package/dist/chunk-YB7AXTX7.js +430 -0
  27. package/dist/chunk-ZGWSJ6Z5.js +601 -0
  28. package/dist/components/ActionBar/index.js +1 -1
  29. package/dist/components/AdvanceMenu/index.d.ts +78 -0
  30. package/dist/components/AdvanceMenu/index.js +1 -0
  31. package/dist/components/AuthorInfo/index.d.ts +5 -1
  32. package/dist/components/AuthorInfo/index.js +1 -1
  33. package/dist/components/BottomSheet/index.d.ts +82 -0
  34. package/dist/components/BottomSheet/index.js +1 -0
  35. package/dist/components/CleanModeOverlay/index.d.ts +60 -0
  36. package/dist/components/CleanModeOverlay/index.js +1 -0
  37. package/dist/components/CommentSheet/index.d.ts +164 -0
  38. package/dist/components/CommentSheet/index.js +1 -0
  39. package/dist/components/DetailView/index.d.ts +311 -0
  40. package/dist/components/DetailView/index.js +1 -0
  41. package/dist/components/ErrorBoundary/index.js +1 -1
  42. package/dist/components/ImageCarousel/index.d.ts +50 -0
  43. package/dist/components/ImageCarousel/index.js +1 -0
  44. package/dist/components/ImagePostSlot/index.d.ts +207 -0
  45. package/dist/components/ImagePostSlot/index.js +1 -0
  46. package/dist/components/ProgressBar/index.d.ts +30 -2
  47. package/dist/components/ProgressBar/index.js +1 -1
  48. package/dist/components/QualityPicker/index.d.ts +35 -0
  49. package/dist/components/QualityPicker/index.js +1 -0
  50. package/dist/components/ReportSheet/index.d.ts +68 -0
  51. package/dist/components/ReportSheet/index.js +1 -0
  52. package/dist/components/Skeleton/index.js +1 -1
  53. package/dist/components/SpeedPicker/index.d.ts +32 -0
  54. package/dist/components/SpeedPicker/index.js +1 -0
  55. package/dist/components/VideoFeed/index.d.ts +12 -1
  56. package/dist/components/VideoFeed/index.js +1 -1
  57. package/dist/components/VideoInfo/index.d.ts +4 -2
  58. package/dist/components/VideoInfo/index.js +1 -1
  59. package/dist/components/VideoPlayer/index.d.ts +14 -41
  60. package/dist/components/VideoPlayer/index.js +1 -1
  61. package/dist/components/VideoSlot/index.d.ts +84 -65
  62. package/dist/components/VideoSlot/index.js +2 -1
  63. package/dist/components/VirtualSlider/index.d.ts +339 -0
  64. package/dist/components/VirtualSlider/index.js +1 -0
  65. package/dist/components/icons/index.js +1 -1
  66. package/dist/index.d.ts +107 -95
  67. package/dist/index.js +84 -27
  68. package/package.json +51 -7
  69. package/dist/chunk-2PTMP65P.js +0 -738
  70. package/dist/chunk-4MN72OZH.js +0 -148
  71. package/dist/chunk-DHQJBXQW.js +0 -562
  72. package/dist/chunk-SSJDO24Q.js +0 -204
  73. package/dist/chunk-XAOEHLOX.js +0 -1326
  74. package/dist/chunk-YW23IBKF.js +0 -530
  75. package/dist/chunk-ZZDQKP4R.js +0 -418
  76. package/dist/use-gesture-react.esm-3SV4QLEJ.js +0 -1893
@@ -0,0 +1,430 @@
1
+ import { injectComponentCSS } from './chunk-CAWE42LH.js';
2
+ import { createContext, useContext, useMemo, useInsertionEffect, useRef, useState, useEffect, useCallback } from 'react';
3
+ import { jsx, jsxs } from 'react/jsx-runtime';
4
+
5
+ // src/components/VirtualSlider/VirtualSlider.css.ts
6
+ var VIRTUAL_SLIDER_CSS = (
7
+ /* css */
8
+ `
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
+ * Container
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-slider {
14
+ position: relative;
15
+ width: 100%;
16
+ height: 100vh;
17
+ overflow: hidden;
18
+ background-color: var(--sv-slider-bg, #000);
19
+ touch-action: none;
20
+ -webkit-user-select: none;
21
+ user-select: none;
22
+ }
23
+
24
+ .sv-slider__container {
25
+ position: relative;
26
+ width: 100%;
27
+ height: 100%;
28
+ }
29
+
30
+ /* Transition during snap (not swiping) */
31
+ .sv-slider__container--snapping {
32
+ /* Transitions handled by individual slots */
33
+ }
34
+
35
+ /* During swipe - no transitions for immediate response */
36
+ .sv-slider__container--swiping {
37
+ /* Slots handle their own transitions */
38
+ }
39
+
40
+ /* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550
41
+ * Slots
42
+ * \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */
43
+
44
+ .sv-slider__slot {
45
+ position: absolute;
46
+ top: 0;
47
+ left: 0;
48
+ width: 100%;
49
+ height: 100%;
50
+ will-change: transform, opacity;
51
+ contain: layout style;
52
+ }
53
+
54
+ /* Active slot */
55
+ .sv-slider__slot--active {
56
+ z-index: 2;
57
+ }
58
+
59
+ /* Adjacent slots (before/after active) */
60
+ .sv-slider__slot--adjacent {
61
+ z-index: 1;
62
+ }
63
+
64
+ /* Smooth transition when snapping */
65
+ .sv-slider__slot--transitioning {
66
+ transition:
67
+ transform 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94),
68
+ opacity 0.3s ease;
69
+ }
70
+
71
+ /* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550
72
+ * Loading State
73
+ * \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */
74
+
75
+ .sv-slider__loading {
76
+ position: absolute;
77
+ top: 0;
78
+ left: 0;
79
+ right: 0;
80
+ bottom: 0;
81
+ display: flex;
82
+ flex-direction: column;
83
+ align-items: center;
84
+ justify-content: center;
85
+ gap: 16px;
86
+ background-color: var(--sv-slider-bg, #000);
87
+ color: var(--sv-slider-text, #fff);
88
+ }
89
+
90
+ .sv-slider__loading-spinner {
91
+ width: 40px;
92
+ height: 40px;
93
+ border: 3px solid rgba(255, 255, 255, 0.2);
94
+ border-top-color: var(--sv-color-primary, #fe2c55);
95
+ border-radius: 50%;
96
+ animation: sv-slider-spin 0.8s linear infinite;
97
+ }
98
+
99
+ @keyframes sv-slider-spin {
100
+ to {
101
+ transform: rotate(360deg);
102
+ }
103
+ }
104
+
105
+ .sv-slider__loading-text {
106
+ font-size: 14px;
107
+ color: var(--sv-slider-text-muted, rgba(255, 255, 255, 0.7));
108
+ }
109
+
110
+ /* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550
111
+ * Empty State
112
+ * \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */
113
+
114
+ .sv-slider__empty {
115
+ position: absolute;
116
+ top: 0;
117
+ left: 0;
118
+ right: 0;
119
+ bottom: 0;
120
+ display: flex;
121
+ flex-direction: column;
122
+ align-items: center;
123
+ justify-content: center;
124
+ gap: 12px;
125
+ background-color: var(--sv-slider-bg, #000);
126
+ color: var(--sv-slider-text, #fff);
127
+ }
128
+
129
+ .sv-slider__empty-icon {
130
+ font-size: 48px;
131
+ opacity: 0.5;
132
+ }
133
+
134
+ .sv-slider__empty-text {
135
+ font-size: 16px;
136
+ color: var(--sv-slider-text-muted, rgba(255, 255, 255, 0.7));
137
+ }
138
+
139
+ /* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550
140
+ * End of List
141
+ * \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */
142
+
143
+ .sv-slider__end {
144
+ position: absolute;
145
+ bottom: var(--sv-safe-area-bottom, 20px);
146
+ left: 0;
147
+ right: 0;
148
+ text-align: center;
149
+ padding: 12px 16px;
150
+ font-size: 14px;
151
+ color: var(--sv-slider-text-muted, rgba(255, 255, 255, 0.6));
152
+ pointer-events: none;
153
+ z-index: 10;
154
+ }
155
+
156
+ /* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550
157
+ * CSS Variables Reference
158
+ * \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550
159
+ *
160
+ * --sv-slider-bg: Background color (default: #000)
161
+ * --sv-slider-text: Text color (default: #fff)
162
+ * --sv-slider-text-muted: Muted text color (default: rgba(255,255,255,0.7))
163
+ * --sv-color-primary: Primary accent color (default: #fe2c55)
164
+ * --sv-safe-area-bottom: Bottom safe area for notched devices
165
+ *
166
+ * \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */
167
+ `
168
+ );
169
+ var VirtualSliderContext = createContext(null);
170
+ VirtualSliderContext.displayName = "VirtualSliderContext";
171
+ function useVirtualSliderContext() {
172
+ const context = useContext(VirtualSliderContext);
173
+ if (!context) {
174
+ throw new Error("useVirtualSliderContext must be used within a VirtualSlider");
175
+ }
176
+ return context;
177
+ }
178
+ function useOptionalVirtualSliderContext() {
179
+ return useContext(VirtualSliderContext);
180
+ }
181
+ function useSliderActiveIndex() {
182
+ const context = useVirtualSliderContext();
183
+ return context.activeIndex;
184
+ }
185
+ function useSliderIsSwiping() {
186
+ const context = useVirtualSliderContext();
187
+ return context.isSwiping;
188
+ }
189
+
190
+ // src/components/VirtualSlider/constants.ts
191
+ var SLIDER_CLASS = "sv-slider";
192
+ var SLIDER_CONTAINER_CLASS = "sv-slider__container";
193
+ var SLIDER_SLOT_CLASS = "sv-slider__slot";
194
+ var SLIDER_SLOT_ACTIVE_CLASS = "sv-slider__slot--active";
195
+ var SLIDER_SLOT_ADJACENT_CLASS = "sv-slider__slot--adjacent";
196
+ var SLIDER_SLOT_TRANSITIONING_CLASS = "sv-slider__slot--transitioning";
197
+ var SLIDER_CONTAINER_SWIPING_CLASS = "sv-slider__container--swiping";
198
+ var SLIDER_CONTAINER_SNAPPING_CLASS = "sv-slider__container--snapping";
199
+ var SLOT_INDEX_ATTR = "data-slot-index";
200
+ var SLOT_INDEX_DATASET_KEY = "slotIndex";
201
+ var SLOT_ACTIVE_ATTR = "data-slot-active";
202
+ var SLOT_ACTIVE_DATASET_KEY = "slotActive";
203
+ var DEFAULT_BUFFER_SIZE = 1;
204
+ var DEFAULT_END_REACHED_THRESHOLD = 2;
205
+ var DEFAULT_LOADING_TEXT = "Loading...";
206
+ var DEFAULT_EMPTY_TEXT = "No items";
207
+ var DEFAULT_END_TEXT = "You've reached the end";
208
+ function useSliderPosition(options) {
209
+ const {
210
+ totalCount,
211
+ activeIndex,
212
+ containerHeight,
213
+ dragOffset,
214
+ isSwiping,
215
+ isResizing = false,
216
+ bufferSize = 1
217
+ } = options;
218
+ return useMemo(() => {
219
+ if (totalCount === 0) {
220
+ return {
221
+ slots: [],
222
+ scrollOffset: 0,
223
+ isAtStart: true,
224
+ isAtLastIndex: true,
225
+ clampedActiveIndex: 0
226
+ };
227
+ }
228
+ const clampedActiveIndex = Math.max(0, Math.min(totalCount - 1, activeIndex));
229
+ const slots = [];
230
+ const startIndex = Math.max(0, clampedActiveIndex - bufferSize);
231
+ const endIndex = Math.min(totalCount - 1, clampedActiveIndex + bufferSize);
232
+ const baseOffset = -clampedActiveIndex * containerHeight;
233
+ const scrollOffset = baseOffset + dragOffset;
234
+ for (let i = startIndex; i <= endIndex; i++) {
235
+ const signedDistance = i - clampedActiveIndex;
236
+ const distance = Math.abs(signedDistance);
237
+ const isActive = i === clampedActiveIndex;
238
+ const top = i * containerHeight;
239
+ const transform = `translateY(${top + scrollOffset}px)`;
240
+ let opacity = 1;
241
+ if (!isActive && !isResizing) {
242
+ opacity = isSwiping ? 0.7 : 0.3;
243
+ }
244
+ slots.push({
245
+ index: i,
246
+ top,
247
+ isActive,
248
+ distance,
249
+ signedDistance,
250
+ transform,
251
+ opacity
252
+ });
253
+ }
254
+ return {
255
+ slots,
256
+ scrollOffset,
257
+ isAtStart: clampedActiveIndex === 0,
258
+ isAtLastIndex: clampedActiveIndex >= totalCount - 1,
259
+ clampedActiveIndex
260
+ };
261
+ }, [totalCount, activeIndex, containerHeight, dragOffset, isSwiping, isResizing, bufferSize]);
262
+ }
263
+ function getSlotIndexFromPosition(yPosition, containerHeight, totalCount) {
264
+ if (totalCount === 0 || containerHeight === 0) {
265
+ return 0;
266
+ }
267
+ const rawIndex = Math.round(-yPosition / containerHeight);
268
+ return Math.max(0, Math.min(totalCount - 1, rawIndex));
269
+ }
270
+ function DefaultLoading({ text = DEFAULT_LOADING_TEXT }) {
271
+ return /* @__PURE__ */ jsxs("div", { className: "sv-slider__loading", children: [
272
+ /* @__PURE__ */ jsx("div", { className: "sv-slider__loading-spinner" }),
273
+ /* @__PURE__ */ jsx("span", { className: "sv-slider__loading-text", children: text })
274
+ ] });
275
+ }
276
+ function DefaultEmpty({ text = DEFAULT_EMPTY_TEXT }) {
277
+ return /* @__PURE__ */ jsxs("div", { className: "sv-slider__empty", children: [
278
+ /* @__PURE__ */ jsx("span", { className: "sv-slider__empty-icon", children: "\u{1F4ED}" }),
279
+ /* @__PURE__ */ jsx("span", { className: "sv-slider__empty-text", children: text })
280
+ ] });
281
+ }
282
+ function DefaultEnd({ text = DEFAULT_END_TEXT }) {
283
+ return /* @__PURE__ */ jsx("div", { className: "sv-slider__end", children: text });
284
+ }
285
+ function VirtualSlider({
286
+ // Required
287
+ items,
288
+ keyExtractor,
289
+ renderItem,
290
+ // Swipe state
291
+ activeIndex,
292
+ isSwiping,
293
+ dragOffset,
294
+ goToIndex,
295
+ // Callbacks
296
+ onIndexChange,
297
+ onEndReached,
298
+ endReachedThreshold = DEFAULT_END_REACHED_THRESHOLD,
299
+ bufferSize = DEFAULT_BUFFER_SIZE,
300
+ // Loading states
301
+ isLoading = false,
302
+ hasMore = true,
303
+ // Custom UI
304
+ loadingComponent,
305
+ emptyComponent,
306
+ endComponent,
307
+ loadingText,
308
+ emptyText,
309
+ endText,
310
+ // Styling
311
+ height,
312
+ className,
313
+ disableInlineTransforms = false,
314
+ testId
315
+ }) {
316
+ useInsertionEffect(() => {
317
+ return injectComponentCSS("virtual-slider", VIRTUAL_SLIDER_CSS);
318
+ }, []);
319
+ const containerRef = useRef(null);
320
+ const prevActiveIndexRef = useRef(activeIndex);
321
+ const [containerHeight, setContainerHeight] = useState(
322
+ typeof window !== "undefined" ? window.innerHeight : 800
323
+ );
324
+ useEffect(() => {
325
+ const container = containerRef.current;
326
+ if (!container) return;
327
+ const updateHeight = () => {
328
+ const rect = container.getBoundingClientRect();
329
+ if (rect.height > 0) {
330
+ setContainerHeight(rect.height);
331
+ }
332
+ };
333
+ updateHeight();
334
+ const resizeObserver = new ResizeObserver(updateHeight);
335
+ resizeObserver.observe(container);
336
+ return () => resizeObserver.disconnect();
337
+ }, []);
338
+ const { slots, isAtLastIndex } = useSliderPosition({
339
+ totalCount: items.length,
340
+ activeIndex,
341
+ containerHeight,
342
+ dragOffset,
343
+ isSwiping,
344
+ bufferSize
345
+ });
346
+ useEffect(() => {
347
+ if (activeIndex !== prevActiveIndexRef.current) {
348
+ prevActiveIndexRef.current = activeIndex;
349
+ onIndexChange?.(activeIndex);
350
+ }
351
+ }, [activeIndex, onIndexChange]);
352
+ useEffect(() => {
353
+ if (items.length === 0) return;
354
+ const remainingItems = items.length - 1 - activeIndex;
355
+ if (remainingItems <= endReachedThreshold && hasMore && !isLoading) {
356
+ onEndReached?.();
357
+ }
358
+ }, [activeIndex, items.length, endReachedThreshold, hasMore, isLoading, onEndReached]);
359
+ const contextValue = useMemo(
360
+ () => ({
361
+ items,
362
+ activeIndex,
363
+ isSwiping,
364
+ dragOffset,
365
+ containerHeight,
366
+ goToIndex,
367
+ totalCount: items.length
368
+ }),
369
+ [items, activeIndex, isSwiping, dragOffset, containerHeight, goToIndex]
370
+ );
371
+ const buildSlotClassName = useCallback(
372
+ (isActive) => {
373
+ const classes = [SLIDER_SLOT_CLASS];
374
+ if (isActive) {
375
+ classes.push(SLIDER_SLOT_ACTIVE_CLASS);
376
+ } else {
377
+ classes.push(SLIDER_SLOT_ADJACENT_CLASS);
378
+ }
379
+ if (!isSwiping) {
380
+ classes.push(SLIDER_SLOT_TRANSITIONING_CLASS);
381
+ }
382
+ return classes.join(" ");
383
+ },
384
+ [isSwiping]
385
+ );
386
+ const buildContainerClassName = useCallback(() => {
387
+ const classes = [SLIDER_CONTAINER_CLASS];
388
+ if (isSwiping) {
389
+ classes.push(SLIDER_CONTAINER_SWIPING_CLASS);
390
+ } else {
391
+ classes.push(SLIDER_CONTAINER_SNAPPING_CLASS);
392
+ }
393
+ return classes.join(" ");
394
+ }, [isSwiping]);
395
+ const rootClassName = [SLIDER_CLASS, className].filter(Boolean).join(" ");
396
+ const rootStyle = height ? { height: typeof height === "number" ? `${height}px` : height } : void 0;
397
+ if (isLoading && items.length === 0) {
398
+ return /* @__PURE__ */ jsx("div", { ref: containerRef, className: rootClassName, style: rootStyle, "data-testid": testId, children: loadingComponent ?? /* @__PURE__ */ jsx(DefaultLoading, { text: loadingText }) });
399
+ }
400
+ if (!isLoading && items.length === 0) {
401
+ return /* @__PURE__ */ jsx("div", { ref: containerRef, className: rootClassName, style: rootStyle, "data-testid": testId, children: emptyComponent ?? /* @__PURE__ */ jsx(DefaultEmpty, { text: emptyText }) });
402
+ }
403
+ const showEndIndicator = isAtLastIndex && !hasMore && !isLoading;
404
+ return /* @__PURE__ */ jsx(VirtualSliderContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxs("div", { ref: containerRef, className: rootClassName, style: rootStyle, "data-testid": testId, children: [
405
+ /* @__PURE__ */ jsx("div", { className: buildContainerClassName(), children: slots.map((slot) => {
406
+ const item = items[slot.index];
407
+ if (item === void 0) return null;
408
+ const key = keyExtractor(item, slot.index);
409
+ const slotStyle = disableInlineTransforms ? void 0 : {
410
+ transform: slot.transform,
411
+ opacity: slot.opacity
412
+ };
413
+ return /* @__PURE__ */ jsx(
414
+ "div",
415
+ {
416
+ className: buildSlotClassName(slot.isActive),
417
+ style: slotStyle,
418
+ ...{ [SLOT_INDEX_ATTR]: slot.index },
419
+ ...{ [SLOT_ACTIVE_ATTR]: slot.isActive ? "true" : "false" },
420
+ children: renderItem(item, slot.index, slot.isActive)
421
+ },
422
+ key
423
+ );
424
+ }) }),
425
+ showEndIndicator && (endComponent ?? /* @__PURE__ */ jsx(DefaultEnd, { text: endText }))
426
+ ] }) });
427
+ }
428
+ VirtualSlider.displayName = "VirtualSlider";
429
+
430
+ export { DEFAULT_BUFFER_SIZE, DEFAULT_EMPTY_TEXT, DEFAULT_END_REACHED_THRESHOLD, DEFAULT_END_TEXT, DEFAULT_LOADING_TEXT, SLIDER_CLASS, SLIDER_CONTAINER_CLASS, SLIDER_CONTAINER_SNAPPING_CLASS, SLIDER_CONTAINER_SWIPING_CLASS, SLIDER_SLOT_ACTIVE_CLASS, SLIDER_SLOT_ADJACENT_CLASS, SLIDER_SLOT_CLASS, SLIDER_SLOT_TRANSITIONING_CLASS, SLOT_ACTIVE_ATTR, SLOT_ACTIVE_DATASET_KEY, SLOT_INDEX_ATTR, SLOT_INDEX_DATASET_KEY, VIRTUAL_SLIDER_CSS, VirtualSlider, VirtualSliderContext, getSlotIndexFromPosition, useOptionalVirtualSliderContext, useSliderActiveIndex, useSliderIsSwiping, useSliderPosition, useVirtualSliderContext };