@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,571 +0,0 @@
1
- import { clsx2 } from './chunk-EDWS2IPH.js';
2
- import { injectComponentCSS } from './chunk-RMLTPW5S.js';
3
- import { memo, useInsertionEffect, useMemo, useEffect, useCallback, useRef, useState } from 'react';
4
- import { jsxs, jsx } from 'react/jsx-runtime';
5
-
6
- // src/components/ProgressBar/ProgressBar.css.ts
7
- var PROGRESS_BAR_CSS = `
8
- /* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550
9
- * ProgressBar Container
10
- * \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */
11
-
12
- .sv-progress-bar {
13
- /* Layout */
14
- position: relative;
15
- width: 100%;
16
-
17
- /* Interactive area - larger than visual for easier touch */
18
- height: var(--sv-progress-bar-touch-height, 24px);
19
- display: flex;
20
- align-items: center;
21
-
22
- /* Cursor */
23
- cursor: pointer;
24
-
25
- /* Prevent text selection during seek */
26
- user-select: none;
27
- -webkit-user-select: none;
28
- touch-action: none;
29
- }
30
-
31
- .sv-progress-bar--disabled {
32
- cursor: default;
33
- pointer-events: none;
34
- }
35
-
36
- /* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
37
- * Track Wrapper (contains track + tooltip)
38
- * \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
39
-
40
- .sv-progress-bar__track-wrapper {
41
- position: relative;
42
- flex: 1;
43
- display: flex;
44
- align-items: center;
45
- }
46
-
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
- * Track (background bar)
49
- * \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
50
-
51
- .sv-progress-bar__track {
52
- position: relative;
53
- width: 100%;
54
- height: var(--sv-progress-bar-height, 3px);
55
-
56
- /* Visual */
57
- background: var(--sv-progress-bar-track-bg, rgba(255, 255, 255, 0.2));
58
- border-radius: var(--sv-progress-bar-radius, 1.5px);
59
- overflow: hidden;
60
- }
61
-
62
- /* Expand track on hover/active for better visibility */
63
- .sv-progress-bar:hover .sv-progress-bar__track,
64
- .sv-progress-bar--seeking .sv-progress-bar__track {
65
- height: var(--sv-progress-bar-height-active, 5px);
66
- }
67
-
68
- /* Disable transition during seeking for immediate feedback */
69
- .sv-progress-bar--seeking .sv-progress-bar__fill,
70
- .sv-progress-bar--seeking .sv-progress-bar__handle {
71
- transition: none;
72
- }
73
-
74
- /* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
75
- * Buffered Fill (shows buffered progress)
76
- * \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
77
-
78
- .sv-progress-bar__buffered {
79
- position: absolute;
80
- top: 0;
81
- left: 0;
82
- height: 100%;
83
-
84
- /* Visual */
85
- background: var(--sv-progress-bar-buffered-bg, rgba(255, 255, 255, 0.3));
86
- border-radius: inherit;
87
-
88
- /* Performance: Use scaleX for GPU acceleration */
89
- transform-origin: left center;
90
- transform: scaleX(0);
91
-
92
- /* Smooth transition for buffered updates */
93
- transition: transform 0.3s ease-out;
94
- }
95
-
96
- /* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
97
- * Progress Fill (shows playback progress)
98
- * IMPORTANT: Designed for Direct DOM Update (ADR 005)
99
- * - Uses scaleX() for 60fps smooth animation
100
- * - Wired component will update transform directly via DOM manipulation
101
- * \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
102
-
103
- .sv-progress-bar__fill {
104
- position: absolute;
105
- top: 0;
106
- left: 0;
107
- height: 100%;
108
- width: 100%;
109
-
110
- /* Visual */
111
- background: var(--sv-progress-bar-fill-bg, var(--sv-color-accent, #fe2c55));
112
- border-radius: inherit;
113
-
114
- /* Performance: Use scaleX for GPU acceleration */
115
- transform-origin: left center;
116
- transform: scaleX(0);
117
-
118
- /* Smooth transition for headless mode (timeupdate ~250ms intervals)
119
- * For RAF-based Direct DOM Update (wired mode), this has minimal impact
120
- * because transform updates every 16ms anyway */
121
- transition: var(--sv-progress-bar-fill-transition, transform 0.25s linear);
122
- will-change: transform;
123
- }
124
-
125
- /* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
126
- * Seek Handle (thumb indicator)
127
- * \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
128
-
129
- .sv-progress-bar__handle {
130
- position: absolute;
131
- top: 50%;
132
-
133
- /* Size */
134
- width: var(--sv-progress-bar-handle-size, 12px);
135
- height: var(--sv-progress-bar-handle-size, 12px);
136
-
137
- /* Positioning - will be set via left % */
138
- left: 0;
139
- transform: translate(-50%, -50%) scale(0);
140
-
141
- /* Visual */
142
- background: var(--sv-progress-bar-handle-bg, #fff);
143
- border-radius: 50%;
144
- box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
145
-
146
- /* Animation - smooth position + show/hide */
147
- transition: left 0.25s linear, transform 0.15s ease-out;
148
- }
149
-
150
- /* Show handle on hover/seeking */
151
- .sv-progress-bar:hover .sv-progress-bar__handle,
152
- .sv-progress-bar--seeking .sv-progress-bar__handle {
153
- transform: translate(-50%, -50%) scale(1);
154
- }
155
-
156
- /* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
157
- * Time Display (optional, shows current/duration)
158
- * \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
159
-
160
- .sv-progress-bar__time {
161
- display: flex;
162
- justify-content: space-between;
163
- padding: var(--sv-spacing-xs, 4px) 0;
164
-
165
- font-family: var(--sv-font-family, 'Urbanist', sans-serif);
166
- font-size: var(--sv-font-size-xs, 11px);
167
- font-variant-numeric: tabular-nums;
168
- color: var(--sv-text-secondary, rgba(255, 255, 255, 0.7));
169
- }
170
-
171
- .sv-progress-bar__time-current,
172
- .sv-progress-bar__time-duration {
173
- /* Ensure consistent width for changing numbers */
174
- min-width: 2.5em;
175
- }
176
-
177
- .sv-progress-bar__time-current {
178
- text-align: left;
179
- }
180
-
181
- .sv-progress-bar__time-duration {
182
- text-align: right;
183
- }
184
-
185
- /* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
186
- * Seek Tooltip (shows time at cursor position during hover)
187
- * \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
188
-
189
- .sv-progress-bar__tooltip {
190
- position: absolute;
191
- /* Position above the container (not inside track to avoid overflow:hidden) */
192
- top: 0;
193
- left: 0;
194
- transform: translate(-50%, -100%);
195
- margin-top: -8px;
196
-
197
- /* Visual */
198
- padding: 4px 8px;
199
- background: var(--sv-bg-overlay, rgba(0, 0, 0, 0.8));
200
- border-radius: var(--sv-border-radius-sm, 4px);
201
-
202
- /* Typography */
203
- font-family: var(--sv-font-family, 'Urbanist', sans-serif);
204
- font-size: var(--sv-font-size-xs, 11px);
205
- font-variant-numeric: tabular-nums;
206
- color: var(--sv-text-primary, #fff);
207
- white-space: nowrap;
208
-
209
- /* Hidden by default */
210
- opacity: 0;
211
- visibility: hidden;
212
- transition: opacity 0.15s ease, visibility 0.15s ease;
213
-
214
- /* Prevent tooltip from capturing pointer events */
215
- pointer-events: none;
216
-
217
- /* Ensure tooltip is above other elements */
218
- z-index: 10;
219
- }
220
-
221
- .sv-progress-bar:hover .sv-progress-bar__tooltip,
222
- .sv-progress-bar--seeking .sv-progress-bar__tooltip {
223
- opacity: 1;
224
- visibility: visible;
225
- }
226
-
227
- /* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
228
- * Minimal Variant (for use inside VideoSlot overlay)
229
- * \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
230
-
231
- .sv-progress-bar--minimal {
232
- height: auto;
233
- }
234
-
235
- .sv-progress-bar--minimal .sv-progress-bar__track {
236
- height: var(--sv-progress-bar-height-minimal, 2px);
237
- }
238
-
239
- .sv-progress-bar--minimal:hover .sv-progress-bar__track {
240
- height: var(--sv-progress-bar-height-minimal, 2px);
241
- }
242
-
243
- .sv-progress-bar--minimal .sv-progress-bar__handle {
244
- display: none;
245
- }
246
-
247
- /* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
248
- * Auto-hide Variant
249
- * Shows progress bar only when video is paused or user is seeking/hovering
250
- * \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
251
-
252
- .sv-progress-bar--auto-hide {
253
- /* Smooth transition for show/hide */
254
- transition: opacity 0.3s ease, visibility 0.3s ease, transform 0.3s ease;
255
- opacity: 1;
256
- visibility: visible;
257
- transform: translateY(0);
258
- }
259
-
260
- .sv-progress-bar--auto-hide.sv-progress-bar--hidden {
261
- opacity: 0;
262
- visibility: hidden;
263
- transform: translateY(8px);
264
- pointer-events: none;
265
- }
266
-
267
- /* Show on hover even when auto-hide is enabled */
268
- .sv-progress-bar--auto-hide:hover {
269
- opacity: 1;
270
- visibility: visible;
271
- transform: translateY(0);
272
- }
273
-
274
- /* Always show when seeking */
275
- .sv-progress-bar--auto-hide.sv-progress-bar--seeking {
276
- opacity: 1;
277
- visibility: visible;
278
- transform: translateY(0);
279
- }
280
-
281
- /* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
282
- * Reduced Motion (Accessibility)
283
- * \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
284
-
285
- @media (prefers-reduced-motion: reduce) {
286
- .sv-progress-bar__fill,
287
- .sv-progress-bar__buffered,
288
- .sv-progress-bar__handle,
289
- .sv-progress-bar__tooltip {
290
- transition: none;
291
- }
292
- }
293
- `;
294
- var CSS_PREFIX = "sv-progress-bar";
295
- function formatTime(seconds) {
296
- if (!Number.isFinite(seconds) || seconds < 0) return "0:00";
297
- const h = Math.floor(seconds / 3600);
298
- const m = Math.floor(seconds % 3600 / 60);
299
- const s = Math.floor(seconds % 60);
300
- if (h > 0) {
301
- return `${h}:${m.toString().padStart(2, "0")}:${s.toString().padStart(2, "0")}`;
302
- }
303
- return `${m}:${s.toString().padStart(2, "0")}`;
304
- }
305
- function calculateProgress(currentTime, duration) {
306
- if (!duration || duration <= 0) return 0;
307
- return Math.min(100, Math.max(0, currentTime / duration * 100));
308
- }
309
- function calculateTimeFromPosition(clientX, rect, duration) {
310
- const x = clientX - rect.left;
311
- const percentage = Math.min(1, Math.max(0, x / rect.width));
312
- return percentage * duration;
313
- }
314
- function useProgressBarRefs({
315
- externalFillRef,
316
- externalBufferedRef,
317
- externalHandleRef,
318
- externalCurrentTimeRef,
319
- externalDurationRef
320
- }) {
321
- const containerRef = useRef(null);
322
- const internalFillRef = useRef(null);
323
- const internalBufferedRef = useRef(null);
324
- const internalHandleRef = useRef(null);
325
- const internalCurrentTimeRef = useRef(null);
326
- const internalDurationRef = useRef(null);
327
- const tooltipRef = useRef(null);
328
- return {
329
- containerRef,
330
- tooltipRef,
331
- fillRef: externalFillRef ?? internalFillRef,
332
- bufferedRef: externalBufferedRef ?? internalBufferedRef,
333
- handleRef: externalHandleRef ?? internalHandleRef,
334
- currentTimeRef: externalCurrentTimeRef ?? internalCurrentTimeRef,
335
- durationRef: externalDurationRef ?? internalDurationRef,
336
- hasExternalCurrentTimeRef: !!externalCurrentTimeRef,
337
- hasExternalDurationRef: !!externalDurationRef
338
- };
339
- }
340
- function useSeekHandlers({
341
- containerRef,
342
- duration,
343
- isSeekable,
344
- onSeek,
345
- onSeekStart,
346
- onSeekEnd
347
- }) {
348
- const [isSeeking, setIsSeeking] = useState(false);
349
- const [hoverTime, setHoverTime] = useState(null);
350
- const [hoverPosition, setHoverPosition] = useState(0);
351
- const handleSeek = useCallback(
352
- (clientX) => {
353
- if (!isSeekable || !containerRef.current) return;
354
- const rect = containerRef.current.getBoundingClientRect();
355
- const time = calculateTimeFromPosition(clientX, rect, duration);
356
- onSeek?.(time);
357
- },
358
- [isSeekable, duration, onSeek, containerRef]
359
- );
360
- const handlePointerDown = useCallback(
361
- (e) => {
362
- if (!isSeekable) return;
363
- e.preventDefault();
364
- e.stopPropagation();
365
- if (typeof e.currentTarget.setPointerCapture === "function") {
366
- e.currentTarget.setPointerCapture(e.pointerId);
367
- }
368
- setIsSeeking(true);
369
- onSeekStart?.();
370
- handleSeek(e.clientX);
371
- },
372
- [isSeekable, onSeekStart, handleSeek]
373
- );
374
- const handlePointerMove = useCallback(
375
- (e) => {
376
- if (!containerRef.current) return;
377
- const rect = containerRef.current.getBoundingClientRect();
378
- const time = calculateTimeFromPosition(e.clientX, rect, duration);
379
- const position = (e.clientX - rect.left) / rect.width * 100;
380
- setHoverTime(time);
381
- setHoverPosition(Math.min(100, Math.max(0, position)));
382
- if (isSeeking) handleSeek(e.clientX);
383
- },
384
- [duration, isSeeking, handleSeek, containerRef]
385
- );
386
- const handlePointerUp = useCallback(
387
- (e) => {
388
- e.stopPropagation();
389
- if (isSeeking) {
390
- if (typeof e.currentTarget.releasePointerCapture === "function") {
391
- e.currentTarget.releasePointerCapture(e.pointerId);
392
- }
393
- setIsSeeking(false);
394
- onSeekEnd?.();
395
- }
396
- },
397
- [isSeeking, onSeekEnd]
398
- );
399
- const handlePointerLeave = useCallback(() => {
400
- setHoverTime(null);
401
- if (isSeeking) {
402
- setIsSeeking(false);
403
- onSeekEnd?.();
404
- }
405
- }, [isSeeking, onSeekEnd]);
406
- return {
407
- isSeeking,
408
- hoverTime,
409
- hoverPosition,
410
- handlePointerDown,
411
- handlePointerMove,
412
- handlePointerUp,
413
- handlePointerLeave
414
- };
415
- }
416
- function ProgressBarHeadlessBase({
417
- currentTime,
418
- duration,
419
- buffered = 0,
420
- seekable = false,
421
- className,
422
- onSeek,
423
- onSeekStart,
424
- onSeekEnd,
425
- showTime = false,
426
- showTooltip,
427
- minimal = false,
428
- autoHide = true,
429
- visible,
430
- fillRef: externalFillRef,
431
- bufferedRef: externalBufferedRef,
432
- handleRef: externalHandleRef,
433
- currentTimeRef: externalCurrentTimeRef,
434
- durationRef: externalDurationRef
435
- }) {
436
- useInsertionEffect(() => {
437
- return injectComponentCSS("progress-bar", PROGRESS_BAR_CSS);
438
- }, []);
439
- const refs = useProgressBarRefs({
440
- externalFillRef,
441
- externalBufferedRef,
442
- externalHandleRef,
443
- externalCurrentTimeRef,
444
- externalDurationRef
445
- });
446
- const progress = useMemo(() => calculateProgress(currentTime, duration), [currentTime, duration]);
447
- const bufferedPercent = useMemo(() => Math.min(100, Math.max(0, buffered * 100)), [buffered]);
448
- const isSeekable = seekable && !!onSeek && duration > 0;
449
- const effectiveShowTooltip = showTooltip ?? isSeekable;
450
- const {
451
- isSeeking,
452
- hoverTime,
453
- hoverPosition,
454
- handlePointerDown,
455
- handlePointerMove,
456
- handlePointerUp,
457
- handlePointerLeave
458
- } = useSeekHandlers({
459
- containerRef: refs.containerRef,
460
- duration,
461
- isSeekable,
462
- onSeek,
463
- onSeekStart,
464
- onSeekEnd
465
- });
466
- useEffect(() => {
467
- if (!refs.hasExternalCurrentTimeRef && refs.currentTimeRef.current) {
468
- refs.currentTimeRef.current.textContent = formatTime(currentTime);
469
- }
470
- }, [currentTime, refs]);
471
- useEffect(() => {
472
- if (!refs.hasExternalDurationRef && refs.durationRef.current) {
473
- refs.durationRef.current.textContent = formatTime(duration);
474
- }
475
- }, [duration, refs]);
476
- const stopBubble = useCallback((e) => {
477
- e.stopPropagation();
478
- }, []);
479
- const isHidden = visible !== void 0 ? !visible : autoHide && !isSeeking && hoverTime === null;
480
- return /* @__PURE__ */ jsxs(
481
- "div",
482
- {
483
- className: clsx2(
484
- CSS_PREFIX,
485
- !isSeekable && `${CSS_PREFIX}--disabled`,
486
- isSeeking && `${CSS_PREFIX}--seeking`,
487
- minimal && `${CSS_PREFIX}--minimal`,
488
- autoHide && `${CSS_PREFIX}--auto-hide`,
489
- isHidden && `${CSS_PREFIX}--hidden`,
490
- className
491
- ),
492
- onClick: stopBubble,
493
- onKeyDown: stopBubble,
494
- onPointerDown: stopBubble,
495
- onPointerUp: stopBubble,
496
- onTouchStart: stopBubble,
497
- onTouchEnd: stopBubble,
498
- children: [
499
- /* @__PURE__ */ jsxs("div", { className: `${CSS_PREFIX}__track-wrapper`, children: [
500
- /* @__PURE__ */ jsxs(
501
- "div",
502
- {
503
- ref: refs.containerRef,
504
- className: `${CSS_PREFIX}__track`,
505
- onPointerDown: handlePointerDown,
506
- onPointerMove: handlePointerMove,
507
- onPointerUp: handlePointerUp,
508
- onPointerLeave: handlePointerLeave,
509
- onClick: (e) => e.stopPropagation(),
510
- onKeyDown: (e) => e.stopPropagation(),
511
- role: isSeekable ? "slider" : "progressbar",
512
- "aria-label": "Video progress",
513
- "aria-valuemin": 0,
514
- "aria-valuemax": duration || 100,
515
- "aria-valuenow": currentTime,
516
- "aria-valuetext": `${formatTime(currentTime)} of ${formatTime(duration)}`,
517
- tabIndex: isSeekable ? 0 : -1,
518
- children: [
519
- /* @__PURE__ */ jsx(
520
- "div",
521
- {
522
- ref: refs.bufferedRef,
523
- className: `${CSS_PREFIX}__buffered`,
524
- style: { transform: `scaleX(${bufferedPercent / 100})` },
525
- "aria-hidden": "true"
526
- }
527
- ),
528
- /* @__PURE__ */ jsx(
529
- "div",
530
- {
531
- ref: refs.fillRef,
532
- className: `${CSS_PREFIX}__fill`,
533
- style: { transform: `scaleX(${progress / 100})` },
534
- "aria-hidden": "true"
535
- }
536
- ),
537
- isSeekable && !minimal && /* @__PURE__ */ jsx(
538
- "div",
539
- {
540
- ref: refs.handleRef,
541
- className: `${CSS_PREFIX}__handle`,
542
- style: { left: `${progress}%` },
543
- "aria-hidden": "true"
544
- }
545
- )
546
- ]
547
- }
548
- ),
549
- effectiveShowTooltip && hoverTime !== null && /* @__PURE__ */ jsx(
550
- "div",
551
- {
552
- ref: refs.tooltipRef,
553
- className: `${CSS_PREFIX}__tooltip`,
554
- style: { left: `${hoverPosition}%` },
555
- "aria-hidden": "true",
556
- children: formatTime(hoverTime)
557
- }
558
- )
559
- ] }),
560
- showTime && /* @__PURE__ */ jsxs("div", { className: `${CSS_PREFIX}__time`, children: [
561
- /* @__PURE__ */ jsx("span", { ref: refs.currentTimeRef, className: `${CSS_PREFIX}__time-current`, children: formatTime(currentTime) }),
562
- /* @__PURE__ */ jsx("span", { ref: refs.durationRef, className: `${CSS_PREFIX}__time-duration`, children: formatTime(duration) })
563
- ] })
564
- ]
565
- }
566
- );
567
- }
568
- var ProgressBarHeadless = memo(ProgressBarHeadlessBase);
569
- ProgressBarHeadless.displayName = "ProgressBarHeadless";
570
-
571
- export { PROGRESS_BAR_CSS, ProgressBarHeadless, calculateProgress, formatTime };