@therealtinhtute/baroiplayer 1.2.1 → 2.0.0-beta.1

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 (302) hide show
  1. package/README.md +90 -71
  2. package/dist/components/icons/index.d.ts +36 -0
  3. package/dist/components/icons/index.d.ts.map +1 -0
  4. package/dist/components/icons/svg-icons/ArrowLeftIcon.d.ts +4 -0
  5. package/dist/components/icons/svg-icons/ArrowLeftIcon.d.ts.map +1 -0
  6. package/dist/components/icons/svg-icons/ArrowRightIcon.d.ts +5 -0
  7. package/dist/components/icons/svg-icons/ArrowRightIcon.d.ts.map +1 -0
  8. package/dist/components/icons/svg-icons/AudioIcon.d.ts +5 -0
  9. package/dist/components/icons/svg-icons/AudioIcon.d.ts.map +1 -0
  10. package/dist/components/icons/svg-icons/BackwardIcon.d.ts +5 -0
  11. package/dist/components/icons/svg-icons/BackwardIcon.d.ts.map +1 -0
  12. package/dist/components/icons/svg-icons/CameraIcon.d.ts +5 -0
  13. package/dist/components/icons/svg-icons/CameraIcon.d.ts.map +1 -0
  14. package/dist/components/icons/svg-icons/CheckIcon.d.ts +5 -0
  15. package/dist/components/icons/svg-icons/CheckIcon.d.ts.map +1 -0
  16. package/dist/components/icons/svg-icons/EnablePiPIcon.d.ts +4 -0
  17. package/dist/components/icons/svg-icons/EnablePiPIcon.d.ts.map +1 -0
  18. package/dist/components/icons/svg-icons/ForwardIcon.d.ts +5 -0
  19. package/dist/components/icons/svg-icons/ForwardIcon.d.ts.map +1 -0
  20. package/dist/components/icons/svg-icons/FullscreenEnterIcon.d.ts +5 -0
  21. package/dist/components/icons/svg-icons/FullscreenEnterIcon.d.ts.map +1 -0
  22. package/dist/components/icons/svg-icons/FullscreenExitIcon.d.ts +5 -0
  23. package/dist/components/icons/svg-icons/FullscreenExitIcon.d.ts.map +1 -0
  24. package/dist/components/icons/svg-icons/LoadingIcon.d.ts +5 -0
  25. package/dist/components/icons/svg-icons/LoadingIcon.d.ts.map +1 -0
  26. package/dist/components/icons/svg-icons/PauseIcon.d.ts +5 -0
  27. package/dist/components/icons/svg-icons/PauseIcon.d.ts.map +1 -0
  28. package/dist/components/icons/svg-icons/PlayIcon.d.ts +5 -0
  29. package/dist/components/icons/svg-icons/PlayIcon.d.ts.map +1 -0
  30. package/dist/components/icons/svg-icons/PlaybackSpeedIcon.d.ts +5 -0
  31. package/dist/components/icons/svg-icons/PlaybackSpeedIcon.d.ts.map +1 -0
  32. package/dist/components/icons/svg-icons/QualityIcon.d.ts +5 -0
  33. package/dist/components/icons/svg-icons/QualityIcon.d.ts.map +1 -0
  34. package/dist/components/icons/svg-icons/SettingsIcon.d.ts +5 -0
  35. package/dist/components/icons/svg-icons/SettingsIcon.d.ts.map +1 -0
  36. package/dist/components/icons/svg-icons/SliderIcon.d.ts +5 -0
  37. package/dist/components/icons/svg-icons/SliderIcon.d.ts.map +1 -0
  38. package/dist/components/icons/svg-icons/SubtitleIcon.d.ts +5 -0
  39. package/dist/components/icons/svg-icons/SubtitleIcon.d.ts.map +1 -0
  40. package/dist/components/icons/svg-icons/SubtitleOffIcon.d.ts +5 -0
  41. package/dist/components/icons/svg-icons/SubtitleOffIcon.d.ts.map +1 -0
  42. package/dist/components/icons/svg-icons/UnPiPIcon.d.ts +4 -0
  43. package/dist/components/icons/svg-icons/UnPiPIcon.d.ts.map +1 -0
  44. package/dist/components/icons/svg-icons/VolumeMutedIcon.d.ts +5 -0
  45. package/dist/components/icons/svg-icons/VolumeMutedIcon.d.ts.map +1 -0
  46. package/dist/components/icons/svg-icons/VolumeOneIcon.d.ts +5 -0
  47. package/dist/components/icons/svg-icons/VolumeOneIcon.d.ts.map +1 -0
  48. package/dist/components/icons/svg-icons/VolumeThreeIcon.d.ts +5 -0
  49. package/dist/components/icons/svg-icons/VolumeThreeIcon.d.ts.map +1 -0
  50. package/dist/components/icons/svg-icons/VolumeTwoIcon.d.ts +5 -0
  51. package/dist/components/icons/svg-icons/VolumeTwoIcon.d.ts.map +1 -0
  52. package/dist/components/variants/gradient/gradient-audio.d.ts +13 -0
  53. package/dist/components/variants/gradient/gradient-audio.d.ts.map +1 -0
  54. package/dist/components/variants/gradient/gradient-controls.d.ts +4 -0
  55. package/dist/components/variants/gradient/gradient-controls.d.ts.map +1 -0
  56. package/dist/components/variants/gradient/gradient-glyphs.d.ts +30 -0
  57. package/dist/components/variants/gradient/gradient-glyphs.d.ts.map +1 -0
  58. package/dist/components/variants/gradient/gradient-video.d.ts +16 -0
  59. package/dist/components/variants/gradient/gradient-video.d.ts.map +1 -0
  60. package/dist/index.css +1 -1
  61. package/dist/index.d.ts +5 -0
  62. package/dist/index.d.ts.map +1 -0
  63. package/dist/index.js +1 -41
  64. package/dist/index.js.map +1 -1
  65. package/dist/index.mjs +750 -5640
  66. package/dist/index.mjs.map +1 -1
  67. package/dist/package.json +3 -0
  68. package/package.json +110 -114
  69. package/src/components/variants/gradient/gradient-audio.tsx +47 -0
  70. package/src/components/variants/gradient/gradient-controls.tsx +254 -0
  71. package/src/components/variants/gradient/gradient-glyphs.test.tsx +69 -0
  72. package/src/components/variants/gradient/gradient-glyphs.tsx +129 -0
  73. package/src/components/variants/gradient/gradient-skin.css +211 -0
  74. package/src/components/variants/gradient/gradient-video.tsx +70 -0
  75. package/src/index.ts +5 -198
  76. package/src/test/accessibility-utils.ts +0 -59
  77. package/dist/context/media.js +0 -1
  78. package/dist/context/media.mjs +0 -3
  79. package/dist/context/store.js +0 -1
  80. package/dist/context/store.mjs +0 -3
  81. package/dist/context-Bzd5QCKM.cjs +0 -7
  82. package/dist/context-Bzd5QCKM.cjs.map +0 -1
  83. package/dist/context-DD_SH4tT.js +0 -1053
  84. package/dist/context-DD_SH4tT.js.map +0 -1
  85. package/dist/core-events-BRnLMB7s.cjs +0 -2
  86. package/dist/core-events-BRnLMB7s.cjs.map +0 -1
  87. package/dist/core-events-v_mKdj5p.js +0 -417
  88. package/dist/core-events-v_mKdj5p.js.map +0 -1
  89. package/dist/core-plugins-CMBv-yVh.cjs +0 -2
  90. package/dist/core-plugins-CMBv-yVh.cjs.map +0 -1
  91. package/dist/core-plugins-CqCxLkbd.js +0 -754
  92. package/dist/core-plugins-CqCxLkbd.js.map +0 -1
  93. package/dist/core.js +0 -15
  94. package/dist/core.js.map +0 -1
  95. package/dist/core.mjs +0 -960
  96. package/dist/core.mjs.map +0 -1
  97. package/dist/enhanced-components-BwjBqSA1.js +0 -2858
  98. package/dist/enhanced-components-BwjBqSA1.js.map +0 -1
  99. package/dist/enhanced-components-C-ka-XLp.cjs +0 -2
  100. package/dist/enhanced-components-C-ka-XLp.cjs.map +0 -1
  101. package/dist/hooks-B-IIWPJr.js +0 -1842
  102. package/dist/hooks-B-IIWPJr.js.map +0 -1
  103. package/dist/hooks-DcHzmBwA.cjs +0 -4
  104. package/dist/hooks-DcHzmBwA.cjs.map +0 -1
  105. package/dist/minimal-components-BYsMQde5.js +0 -1610
  106. package/dist/minimal-components-BYsMQde5.js.map +0 -1
  107. package/dist/minimal-components-CsxQbDp7.cjs +0 -2
  108. package/dist/minimal-components-CsxQbDp7.cjs.map +0 -1
  109. package/dist/minimal-components.css +0 -1
  110. package/dist/mona-loading.gif +0 -0
  111. package/dist/performance-monitor-DCSijLJg.js +0 -312
  112. package/dist/performance-monitor-DCSijLJg.js.map +0 -1
  113. package/dist/performance-monitor-wNFKmqMr.cjs +0 -2
  114. package/dist/performance-monitor-wNFKmqMr.cjs.map +0 -1
  115. package/dist/rolldown-runtime-BmowowmI.js +0 -14
  116. package/dist/rolldown-runtime-mLOUI7ql.cjs +0 -1
  117. package/dist/utils-D2gQ7c2R.js +0 -64
  118. package/dist/utils-D2gQ7c2R.js.map +0 -1
  119. package/dist/utils-DJaAwiZ9.cjs +0 -2
  120. package/dist/utils-DJaAwiZ9.cjs.map +0 -1
  121. package/dist/utils.js +0 -1
  122. package/dist/utils.mjs +0 -3
  123. package/src/adapters/videojs-adapter.tsx +0 -470
  124. package/src/assets/mona-loading.gif +0 -0
  125. package/src/components/AnimateLoading.tsx +0 -111
  126. package/src/components/LoadingState.tsx +0 -239
  127. package/src/components/__tests__/media-player-accessibility.test.tsx +0 -510
  128. package/src/components/__tests__/media-player-react19.test.tsx +0 -457
  129. package/src/components/accessibility/keyboard-help-overlay.tsx +0 -207
  130. package/src/components/audio-player.tsx +0 -85
  131. package/src/components/basic/index.ts +0 -37
  132. package/src/components/enhanced/advanced-features.tsx +0 -311
  133. package/src/components/enhanced/debug-panel.tsx +0 -448
  134. package/src/components/enhanced/enhanced-controls.tsx +0 -597
  135. package/src/components/enhanced/enhanced-media-player.tsx +0 -566
  136. package/src/components/enhanced/error-handling.tsx +0 -338
  137. package/src/components/enhanced/index.ts +0 -39
  138. package/src/components/enhanced/media-player-enhanced.tsx +0 -383
  139. package/src/components/examples/basic-video-player.tsx +0 -50
  140. package/src/components/examples/custom-controls-example.tsx +0 -63
  141. package/src/components/examples/enhanced-controls-example.tsx +0 -100
  142. package/src/components/examples/enhanced-media-player-example.tsx +0 -302
  143. package/src/components/examples/loading-states-demo.tsx +0 -141
  144. package/src/components/examples/react-19-demo.tsx +0 -349
  145. package/src/components/examples/volume-orientation-demo.tsx +0 -105
  146. package/src/components/icon-demo.tsx +0 -196
  147. package/src/components/legacy.tsx +0 -87
  148. package/src/components/media-metadata-display.tsx +0 -99
  149. package/src/components/media-player-audio.tsx +0 -39
  150. package/src/components/media-player-controls.tsx +0 -223
  151. package/src/components/media-player-error.tsx +0 -163
  152. package/src/components/media-player-fullscreen.tsx +0 -109
  153. package/src/components/media-player-hls.tsx +0 -111
  154. package/src/components/media-player-loading.tsx +0 -76
  155. package/src/components/media-player-play.tsx +0 -75
  156. package/src/components/media-player-root.tsx +0 -338
  157. package/src/components/media-player-seek.tsx +0 -168
  158. package/src/components/media-player-time.tsx +0 -99
  159. package/src/components/media-player-tooltip.tsx +0 -58
  160. package/src/components/media-player-video.tsx +0 -54
  161. package/src/components/media-player-volume.tsx +0 -155
  162. package/src/components/media-player.tsx +0 -292
  163. package/src/components/media-suspense.tsx +0 -344
  164. package/src/components/player-settings-form.tsx +0 -158
  165. package/src/components/react-player-wrapper.tsx +0 -651
  166. package/src/components/simple-video-player.tsx +0 -62
  167. package/src/components/ui/blur-poster.tsx +0 -96
  168. package/src/components/ui/empty-state.tsx +0 -91
  169. package/src/components/ui/enhanced-seek-bar.tsx +0 -254
  170. package/src/components/ui/error-state.tsx +0 -124
  171. package/src/components/ui/fullscreen-button.tsx +0 -81
  172. package/src/components/ui/loading-skeleton.tsx +0 -107
  173. package/src/components/ui/media-resource-preloader.tsx +0 -458
  174. package/src/components/ui/offline-message.tsx +0 -98
  175. package/src/components/ui/play-button.tsx +0 -99
  176. package/src/components/ui/seek-bar.tsx +0 -191
  177. package/src/components/ui/time-display.tsx +0 -61
  178. package/src/components/ui/volume-control.tsx +0 -190
  179. package/src/components/unified/base-media-player.tsx +0 -252
  180. package/src/components/unified/media-player.tsx +0 -75
  181. package/src/components/variants/minimal/AccessibleMinimalPlayer.tsx +0 -587
  182. package/src/components/variants/minimal/EnhancedMinimalMediaPlayer.tsx +0 -573
  183. package/src/components/variants/minimal/MinimalControls.tsx +0 -124
  184. package/src/components/variants/minimal/MinimalLoading.tsx +0 -28
  185. package/src/components/variants/minimal/MinimalMediaPlayer.tsx +0 -318
  186. package/src/components/variants/minimal/MinimalOverlay.tsx +0 -58
  187. package/src/components/variants/minimal/MinimalPlayButton.tsx +0 -56
  188. package/src/components/variants/minimal/MinimalSeekBar.tsx +0 -140
  189. package/src/components/variants/minimal/MinimalVolumeControl.tsx +0 -75
  190. package/src/components/variants/minimal/SimpleMinimalPlayer.tsx +0 -206
  191. package/src/components/variants/minimal/components/CenterPlayButton.tsx +0 -22
  192. package/src/components/variants/minimal/components/ControlBar.tsx +0 -142
  193. package/src/components/variants/minimal/components/EnhancedSettingsMenu.tsx +0 -412
  194. package/src/components/variants/minimal/components/PlaybackControls.tsx +0 -46
  195. package/src/components/variants/minimal/components/RightControls.tsx +0 -164
  196. package/src/components/variants/minimal/components/SeekBar.tsx +0 -127
  197. package/src/components/variants/minimal/components/SettingsDropdown.tsx +0 -68
  198. package/src/components/variants/minimal/components/SubtitleDisplay.tsx +0 -21
  199. package/src/components/variants/minimal/components/TimeDisplay.tsx +0 -15
  200. package/src/components/variants/minimal/components/VideoElement.tsx +0 -35
  201. package/src/components/variants/minimal/components/VolumeControl.tsx +0 -220
  202. package/src/components/variants/minimal/index.ts +0 -23
  203. package/src/components/video-player.tsx +0 -100
  204. package/src/context/__tests__/media-store.test.ts +0 -509
  205. package/src/context/error-handling.ts +0 -398
  206. package/src/context/media-context.tsx +0 -254
  207. package/src/context/media-provider.tsx +0 -264
  208. package/src/context/media-store.ts +0 -387
  209. package/src/context/persistence.ts +0 -462
  210. package/src/core/events/event-system.ts +0 -448
  211. package/src/core/events/hooks.ts +0 -325
  212. package/src/core/events/index.ts +0 -22
  213. package/src/core/events/middleware.ts +0 -286
  214. package/src/core/index.ts +0 -22
  215. package/src/core/optimization/bundle-optimizer.tsx +0 -312
  216. package/src/core/performance/cicd.ts +0 -98
  217. package/src/core/performance/index.ts +0 -38
  218. package/src/core/performance/media-loading-optimizer.ts +0 -545
  219. package/src/core/performance/performance-budgets.ts +0 -437
  220. package/src/core/performance/performance-monitor.tsx +0 -488
  221. package/src/core/performance/performance-testing.ts +0 -461
  222. package/src/core/plugins/__tests__/registry.test.ts +0 -595
  223. package/src/core/plugins/base-plugin.ts +0 -225
  224. package/src/core/plugins/enhanced-plugin-system.ts +0 -435
  225. package/src/core/plugins/examples/analytics-plugin.ts +0 -241
  226. package/src/core/plugins/index.ts +0 -39
  227. package/src/core/plugins/registry.ts +0 -546
  228. package/src/core/plugins/types.ts +0 -169
  229. package/src/core/plugins/utils.ts +0 -317
  230. package/src/core/progressive-loading.tsx +0 -331
  231. package/src/core/providers/enhanced-hls-provider.ts +0 -307
  232. package/src/core/providers/lazy-provider.tsx +0 -14
  233. package/src/core/providers/service-provider.tsx +0 -164
  234. package/src/core/utils.tsx +0 -34
  235. package/src/features/media-session/media-session-manager.ts +0 -411
  236. package/src/features/picture-in-picture/pip-manager.ts +0 -428
  237. package/src/features/playlist/playlist-manager.ts +0 -626
  238. package/src/features/subtitles/subtitle-manager.ts +0 -435
  239. package/src/features/subtitles/subtitle-parser.ts +0 -284
  240. package/src/features/thumbnails/thumbnail-generator.ts +0 -528
  241. package/src/hooks/__tests__/currentTime-fix.test.ts +0 -149
  242. package/src/hooks/__tests__/use-media-player.test.ts +0 -712
  243. package/src/hooks/__tests__/use-media-state.test.tsx +0 -316
  244. package/src/hooks/accessibility/index.ts +0 -27
  245. package/src/hooks/accessibility/use-accessibility-preferences.ts +0 -190
  246. package/src/hooks/accessibility/use-focus-management.ts +0 -183
  247. package/src/hooks/accessibility/use-keyboard-shortcuts.ts +0 -152
  248. package/src/hooks/accessibility/use-screen-reader.ts +0 -212
  249. package/src/hooks/core/index.ts +0 -47
  250. package/src/hooks/legacy.ts +0 -21
  251. package/src/hooks/use-buffer-health.ts +0 -218
  252. package/src/hooks/use-enhanced-media-player.ts +0 -575
  253. package/src/hooks/use-focus-trap.tsx +0 -162
  254. package/src/hooks/use-intelligent-preloading.ts +0 -387
  255. package/src/hooks/use-keyboard-controls.ts +0 -115
  256. package/src/hooks/use-keyboard-shortcuts.ts +0 -255
  257. package/src/hooks/use-media-actions.ts +0 -184
  258. package/src/hooks/use-media-metadata.ts +0 -91
  259. package/src/hooks/use-media-optimistic.ts +0 -264
  260. package/src/hooks/use-media-player.ts +0 -343
  261. package/src/hooks/use-media-state.ts +0 -194
  262. package/src/hooks/use-memory-optimization.ts +0 -360
  263. package/src/hooks/use-network-status.ts +0 -124
  264. package/src/hooks/use-optimistic-controls.ts +0 -95
  265. package/src/hooks/use-optimized-media.ts +0 -283
  266. package/src/hooks/use-smart-preload.ts +0 -229
  267. package/src/hooks/use-touch-gestures.ts +0 -461
  268. package/src/hooks/useEnhancedSubtitles.ts +0 -258
  269. package/src/hooks/useKeyboardShortcuts.ts +0 -106
  270. package/src/hooks/useMediaControls.ts +0 -52
  271. package/src/hooks/useScreenshot.ts +0 -77
  272. package/src/hooks/useSubtitles.ts +0 -91
  273. package/src/hooks/useVideoPlayer.ts +0 -278
  274. package/src/icons/components/FullscreenIcon.tsx +0 -36
  275. package/src/icons/components/SettingsIcon.tsx +0 -37
  276. package/src/icons/components/animated/LoadingIcon.tsx +0 -27
  277. package/src/icons/components/animated/PlayPauseIcon.tsx +0 -42
  278. package/src/icons/components/media/PauseIcon.tsx +0 -38
  279. package/src/icons/components/media/PlayIcon.tsx +0 -37
  280. package/src/icons/components/volume/VolumeIcon.tsx +0 -38
  281. package/src/icons/components/volume/VolumeOffIcon.tsx +0 -38
  282. package/src/icons/index.ts +0 -56
  283. package/src/icons/provider.tsx +0 -58
  284. package/src/icons/types.ts +0 -60
  285. package/src/index-enhanced.ts +0 -35
  286. package/src/index-legacy.ts +0 -324
  287. package/src/index.css +0 -102
  288. package/src/lib/__tests__/async-utils.test.ts +0 -291
  289. package/src/lib/async-utils.ts +0 -194
  290. package/src/lib/deprecation.ts +0 -51
  291. package/src/lib/format-time.ts +0 -37
  292. package/src/lib/index.ts +0 -4
  293. package/src/lib/utils.ts +0 -6
  294. package/src/styles/globals.css +0 -462
  295. package/src/styles/minimal-player.css +0 -621
  296. package/src/styles/pixel-art.css +0 -41
  297. package/src/styles/videojs.css +0 -100
  298. package/src/types/assets.d.ts +0 -29
  299. package/src/types/events.ts +0 -47
  300. package/src/types/formats.ts +0 -79
  301. package/src/types/index.ts +0 -203
  302. package/src/types/videojs-plugins.d.ts +0 -14
@@ -1,107 +0,0 @@
1
- import { memo } from "react"
2
- import { cn } from "../../lib/utils"
3
-
4
- interface LoadingSkeletonProps {
5
- className?: string
6
- variant?: "text" | "circular" | "rectangular" | "rounded"
7
- animation?: "pulse" | "wave" | "none"
8
- width?: number | string
9
- height?: number | string
10
- }
11
-
12
- const variantStyles = {
13
- text: "rounded",
14
- circular: "rounded-full",
15
- rectangular: "rounded-none",
16
- rounded: "rounded-lg"
17
- }
18
-
19
- const animationStyles = {
20
- pulse: "animate-pulse",
21
- wave: "animate-pulse",
22
- none: ""
23
- }
24
-
25
- const LoadingSkeletonComponent = memo(function LoadingSkeleton({
26
- className,
27
- variant = "text",
28
- animation = "pulse",
29
- width,
30
- height
31
- }: LoadingSkeletonProps) {
32
- return (
33
- <div
34
- className={cn(
35
- "bg-[color:var(--media-skeleton)]",
36
- variantStyles[variant],
37
- animation === "wave" &&
38
- "bg-[length:200%_100%] bg-gradient-to-r from-[color:var(--media-skeleton)] via-[color:var(--media-skeleton-light)] to-[color:var(--media-skeleton)]",
39
- animationStyles[animation],
40
- className
41
- )}
42
- style={{ width, height }}
43
- role="status"
44
- aria-label="Loading content"
45
- />
46
- )
47
- })
48
-
49
- interface LoadingSkeletonListProps {
50
- count?: number
51
- className?: string
52
- itemClassName?: string
53
- }
54
-
55
- export const LoadingSkeletonList = memo(function LoadingSkeletonList({
56
- count = 3,
57
- className,
58
- itemClassName
59
- }: LoadingSkeletonListProps) {
60
- return (
61
- <div className={cn("space-y-4", className)}>
62
- {Array.from({ length: count }).map((_, i) => (
63
- <LoadingSkeletonComponent
64
- key={i}
65
- variant="rounded"
66
- width="100%"
67
- height={60}
68
- className={itemClassName}
69
- />
70
- ))}
71
- </div>
72
- )
73
- })
74
-
75
- interface LoadingPlayerSkeletonProps {
76
- className?: string
77
- showTimeDisplay?: boolean
78
- showControls?: boolean
79
- }
80
-
81
- export const LoadingPlayerSkeleton = memo(function LoadingPlayerSkeleton({
82
- className,
83
- showTimeDisplay = true,
84
- showControls = true
85
- }: LoadingPlayerSkeletonProps) {
86
- return (
87
- <div className={cn("relative overflow-hidden rounded-lg bg-black", className)}>
88
- <LoadingSkeletonComponent
89
- variant="rectangular"
90
- width="100%"
91
- height="100%"
92
- className="aspect-video"
93
- />
94
- <div className="absolute right-0 bottom-0 left-0 p-4">
95
- {showTimeDisplay && (
96
- <div className="mb-2 flex justify-between">
97
- <LoadingSkeletonComponent variant="text" width={60} height={16} />
98
- <LoadingSkeletonComponent variant="text" width={60} height={16} />
99
- </div>
100
- )}
101
- {showControls && <LoadingSkeletonComponent variant="rounded" width="100%" height={8} />}
102
- </div>
103
- </div>
104
- )
105
- })
106
-
107
- export { LoadingSkeletonComponent as LoadingSkeleton }
@@ -1,458 +0,0 @@
1
- /**
2
- * Media Resource Preloader using React 19's resource preloading APIs
3
- * Implements intelligent preloading strategies based on user behavior and network conditions
4
- */
5
-
6
- import React, { useEffect, useRef, useMemo } from "react"
7
- import { preconnect, prefetchDNS, preinit, preload } from "react-dom"
8
- import { MediaSource } from "../../types"
9
-
10
- interface MediaResourcePreloaderProps {
11
- /** Media sources to preload */
12
- sources: MediaSource[]
13
- /** Enable intelligent preloading based on user behavior */
14
- enableIntelligentPreloading?: boolean
15
- /** Network-aware preloading */
16
- adaptToNetworkConditions?: boolean
17
- /** Preload priority level */
18
- priority?: "high" | "low" | "auto"
19
- /** Custom preloading strategy */
20
- strategy?: "conservative" | "aggressive" | "adaptive"
21
- }
22
-
23
- interface PreloadingConfig {
24
- dnsPrefetch: string[]
25
- preconnect: string[]
26
- preload: Array<{ url: string; type: string }>
27
- preinit: Array<{ url: string; type: string }>
28
- }
29
-
30
- export const MediaResourcePreloader: React.FC<MediaResourcePreloaderProps> = ({
31
- sources,
32
- enableIntelligentPreloading = true,
33
- adaptToNetworkConditions = true,
34
- priority = "auto",
35
- strategy = "adaptive"
36
- }) => {
37
- const networkInfoRef = useRef<any>(null)
38
- const userBehaviorRef = useRef<UserBehaviorTracker | null>(null)
39
- const preloadingHistoryRef = useRef<Map<string, number>>(new Map())
40
-
41
- // Helper functions (must be declared before use)
42
- function shouldUseCrossOrigin(url: string): boolean {
43
- return !url.includes(window.location.origin)
44
- }
45
-
46
- function getAssetIntegrity(url: string): string | undefined {
47
- // Return integrity hash if available for the asset
48
- // This would typically come from a build process or asset manifest
49
- return undefined
50
- }
51
-
52
- function preloadLikelyContent(sources: string[]): void {
53
- sources.forEach((url) => {
54
- // Mark as preloaded
55
- preloadingHistoryRef.current.set(url, Date.now())
56
-
57
- // Preload the content
58
- preload(url, {
59
- as: "fetch" as any,
60
- crossOrigin: "anonymous"
61
- } as any)
62
- })
63
- }
64
-
65
- function adjustPreloadingStrategy(): void {
66
- // Adjust preloading based on network conditions
67
- if (!networkInfoRef.current) return
68
-
69
- const { effectiveType, downlink } = networkInfoRef.current
70
-
71
- // This would update the preloading configuration
72
- // Implementation depends on specific requirements
73
- }
74
-
75
- // Analyze sources and determine preloading configuration
76
- const preloadingConfig = useMemo((): PreloadingConfig => {
77
- const config: PreloadingConfig = {
78
- dnsPrefetch: [],
79
- preconnect: [],
80
- preload: [],
81
- preinit: []
82
- }
83
-
84
- sources.forEach((source) => {
85
- const url = new URL(source.src)
86
- const domain = url.origin
87
-
88
- // DNS prefetch for CDN domains
89
- if (isCDNDomain(domain)) {
90
- config.dnsPrefetch.push(domain)
91
- }
92
-
93
- // Preconnect to media domains
94
- if (shouldPreconnect(source.type || "", strategy)) {
95
- config.preconnect.push(domain)
96
- }
97
-
98
- // Preload media files based on strategy (basic check without refs)
99
- if (shouldPreloadBasic(source, priority, strategy)) {
100
- config.preload.push({
101
- url: source.src,
102
- type: getPreloadType(source.type || "")
103
- })
104
- }
105
-
106
- // Preinit critical resources
107
- if (shouldPreinit(source, strategy)) {
108
- config.preinit.push({
109
- url: source.src,
110
- type: "script"
111
- })
112
- }
113
- })
114
-
115
- return config
116
- }, [sources, priority, strategy])
117
-
118
- // Store the filtered preloading config
119
- const [filteredPreloadingConfig, setFilteredPreloadingConfig] = React.useState(preloadingConfig)
120
-
121
- // Update filtered config when preloading config or refs change (safe ref access in effect)
122
- React.useEffect(() => {
123
- const filtered = { ...preloadingConfig }
124
- filtered.preload = preloadingConfig.preload.filter(({ url }) => {
125
- const source = sources.find((s) => s.src === url)
126
- if (!source) return false
127
-
128
- // Inline the full shouldPreload logic to avoid function hoisting issues
129
- // Check if already preloaded recently
130
- const lastPreload = preloadingHistoryRef.current.get(source.src)
131
- if (lastPreload && Date.now() - lastPreload < 300000) return false // 5 minutes
132
-
133
- // Strategy-based decision
134
- if (strategy === "conservative") {
135
- return priority === "high" && (source.type as string) === "hls"
136
- }
137
-
138
- if (strategy === "aggressive") {
139
- return true
140
- }
141
-
142
- // Adaptive strategy (simplified version)
143
- if (networkInfoRef.current) {
144
- const { effectiveType, saveData } = networkInfoRef.current
145
-
146
- if (saveData) return false
147
- if (effectiveType === "slow-2g" || effectiveType === "2g") {
148
- return priority === "high" && (source.type as string) === "hls"
149
- }
150
- if (effectiveType === "3g") {
151
- return ["hls", "m3u8"].includes(source.type || "")
152
- }
153
- }
154
-
155
- return priority !== "low"
156
- })
157
-
158
- setFilteredPreloadingConfig(filtered)
159
- }, [preloadingConfig, sources, priority, strategy])
160
-
161
- // Initialize network monitoring
162
- useEffect(() => {
163
- if (adaptToNetworkConditions && "connection" in navigator) {
164
- networkInfoRef.current = (navigator as any).connection
165
-
166
- const handleNetworkChange = () => {
167
- adjustPreloadingStrategy()
168
- }
169
-
170
- networkInfoRef.current.addEventListener("change", handleNetworkChange)
171
-
172
- return () => {
173
- networkInfoRef.current?.removeEventListener("change", handleNetworkChange)
174
- }
175
- }
176
- }, [adaptToNetworkConditions])
177
-
178
- // Initialize user behavior tracking
179
- useEffect(() => {
180
- if (enableIntelligentPreloading) {
181
- userBehaviorRef.current = new UserBehaviorTracker()
182
- userBehaviorRef.current.startTracking()
183
-
184
- return () => {
185
- userBehaviorRef.current?.stopTracking()
186
- }
187
- }
188
- }, [enableIntelligentPreloading])
189
-
190
- // Apply DNS prefetching
191
- useEffect(() => {
192
- filteredPreloadingConfig.dnsPrefetch.forEach((domain) => {
193
- prefetchDNS(domain)
194
- })
195
- }, [filteredPreloadingConfig.dnsPrefetch])
196
-
197
- // Apply preconnections
198
- useEffect(() => {
199
- filteredPreloadingConfig.preconnect.forEach((origin) => {
200
- preconnect(origin, { crossOrigin: "anonymous" })
201
- })
202
- }, [filteredPreloadingConfig.preconnect])
203
-
204
- // Apply preloading
205
- useEffect(() => {
206
- filteredPreloadingConfig.preload.forEach(({ url, type }) => {
207
- const crossOrigin = shouldUseCrossOrigin(url) ? "anonymous" : undefined
208
-
209
- preload(url, {
210
- as: type as any,
211
- crossOrigin,
212
- integrity: getAssetIntegrity(url)
213
- } as any)
214
- })
215
- }, [filteredPreloadingConfig.preload, priority])
216
-
217
- // Apply preinit for critical resources
218
- useEffect(() => {
219
- filteredPreloadingConfig.preinit.forEach(({ url, type }) => {
220
- const crossOrigin = shouldUseCrossOrigin(url) ? "anonymous" : undefined
221
-
222
- preinit(url, {
223
- as: type as any,
224
- crossOrigin
225
- } as any)
226
- })
227
- }, [filteredPreloadingConfig.preinit])
228
-
229
- // Intelligent preloading based on user behavior
230
- useEffect(() => {
231
- if (!enableIntelligentPreloading || !userBehaviorRef.current) return
232
-
233
- const handleUserBehavior = (behavior: UserBehaviorData) => {
234
- if (behavior.isLikelyToInteract) {
235
- preloadLikelyContent(behavior.predictedSources)
236
- }
237
- }
238
-
239
- userBehaviorRef.current.onBehaviorChange(handleUserBehavior)
240
- }, [enableIntelligentPreloading])
241
-
242
- // Helper functions
243
- function isCDNDomain(domain: string): boolean {
244
- const cdnDomains = [
245
- "cdn.jsdelivr.net",
246
- "cdnjs.cloudflare.com",
247
- "unpkg.com",
248
- "cloudflare.com",
249
- "fastly.net",
250
- "akamaized.net"
251
- ]
252
-
253
- return cdnDomains.some((cdn) => domain.includes(cdn))
254
- }
255
-
256
- function shouldPreconnect(mediaType: string, strategy: string): boolean {
257
- if (strategy === "aggressive") return true
258
- if (strategy === "conservative") return ["hls", "m3u8"].includes(mediaType)
259
- return ["hls", "m3u8", "mp4"].includes(mediaType)
260
- }
261
-
262
- function shouldPreloadBasic(source: MediaSource, priority: string, strategy: string): boolean {
263
- // Basic strategy-based decision without ref access
264
- if (strategy === "conservative") {
265
- return priority === "high" && (source.type as string) === "hls"
266
- }
267
-
268
- if (strategy === "aggressive") {
269
- return true
270
- }
271
-
272
- // Adaptive strategy (basic version)
273
- return priority !== "low"
274
- }
275
-
276
- function shouldPreload(
277
- source: MediaSource,
278
- priority: string,
279
- strategy: string,
280
- preloadingHistory: Map<string, number>,
281
- networkInfo: any
282
- ): boolean {
283
- // Check if already preloaded recently
284
- const lastPreload = preloadingHistory.get(source.src)
285
- if (lastPreload && Date.now() - lastPreload < 300000) return false // 5 minutes
286
-
287
- // Strategy-based decision
288
- if (strategy === "conservative") {
289
- return priority === "high" && (source.type as string) === "hls"
290
- }
291
-
292
- if (strategy === "aggressive") {
293
- return true
294
- }
295
-
296
- // Adaptive strategy
297
- return shouldAdaptivePreload(source, priority, networkInfo)
298
- }
299
-
300
- function shouldAdaptivePreload(
301
- source: MediaSource,
302
- priority: string,
303
- networkInfo: any
304
- ): boolean {
305
- // Consider network conditions
306
- if (networkInfo) {
307
- const { effectiveType, saveData } = networkInfo
308
-
309
- if (saveData) return false
310
- if (effectiveType === "slow-2g" || effectiveType === "2g") {
311
- return priority === "high" && (source.type as string) === "hls"
312
- }
313
- if (effectiveType === "3g") {
314
- return ["hls", "m3u8"].includes(source.type || "")
315
- }
316
- }
317
-
318
- // Consider user behavior
319
- if (userBehaviorRef.current) {
320
- const behavior = userBehaviorRef.current.getCurrentBehavior()
321
- if (behavior.engagementScore > 0.7) {
322
- return true
323
- }
324
- }
325
-
326
- return priority !== "low"
327
- }
328
-
329
- function shouldPreinit(source: MediaSource, strategy: string): boolean {
330
- return strategy === "aggressive" && (source.type as string) === "hls"
331
- }
332
-
333
- function getPreloadType(mediaType: string): string {
334
- switch (mediaType) {
335
- case "hls":
336
- case "m3u8":
337
- return "fetch"
338
- case "mp4":
339
- case "webm":
340
- return "video"
341
- case "mp3":
342
- case "wav":
343
- return "audio"
344
- default:
345
- return "fetch"
346
- }
347
- }
348
-
349
- // This component doesn't render anything visible
350
- return null
351
- }
352
-
353
- /**
354
- * User behavior tracker for intelligent preloading
355
- */
356
- class UserBehaviorTracker {
357
- private behaviorData: UserBehaviorData = {
358
- isLikelyToInteract: false,
359
- engagementScore: 0,
360
- predictedSources: [],
361
- interactionHistory: []
362
- }
363
-
364
- private listeners: ((behavior: UserBehaviorData) => void)[] = []
365
- private mouseMoveTimer: number | null = null
366
-
367
- public startTracking(): void {
368
- // Track mouse movements as interaction indicators
369
- document.addEventListener("mousemove", this.handleMouseMove)
370
- document.addEventListener("scroll", this.handleScroll)
371
- document.addEventListener("keydown", this.handleKeydown)
372
-
373
- // Track focus events
374
- document.addEventListener("focusin", this.handleFocus)
375
- document.addEventListener("visibilitychange", this.handleVisibilityChange)
376
- }
377
-
378
- public stopTracking(): void {
379
- document.removeEventListener("mousemove", this.handleMouseMove)
380
- document.removeEventListener("scroll", this.handleScroll)
381
- document.removeEventListener("keydown", this.handleKeydown)
382
- document.removeEventListener("focusin", this.handleFocus)
383
- document.removeEventListener("visibilitychange", this.handleVisibilityChange)
384
-
385
- if (this.mouseMoveTimer) {
386
- clearTimeout(this.mouseMoveTimer)
387
- }
388
- }
389
-
390
- public onBehaviorChange(listener: (behavior: UserBehaviorData) => void): void {
391
- this.listeners.push(listener)
392
- }
393
-
394
- public getCurrentBehavior(): UserBehaviorData {
395
- return this.behaviorData
396
- }
397
-
398
- private handleMouseMove = (): void => {
399
- if (this.mouseMoveTimer) return
400
-
401
- this.mouseMoveTimer = window.setTimeout(() => {
402
- this.updateEngagementScore(0.1)
403
- this.mouseMoveTimer = null
404
- }, 100)
405
- }
406
-
407
- private handleScroll = (): void => {
408
- this.updateEngagementScore(0.2)
409
- }
410
-
411
- private handleKeydown = (): void => {
412
- this.updateEngagementScore(0.3)
413
- this.behaviorData.isLikelyToInteract = true
414
- }
415
-
416
- private handleFocus = (): void => {
417
- this.updateEngagementScore(0.4)
418
- this.behaviorData.isLikelyToInteract = true
419
- }
420
-
421
- private handleVisibilityChange = (): void => {
422
- if (!document.hidden) {
423
- this.updateEngagementScore(0.5)
424
- this.behaviorData.isLikelyToInteract = true
425
- }
426
- }
427
-
428
- private updateEngagementScore(increment: number): void {
429
- this.behaviorData.engagementScore = Math.min(1, this.behaviorData.engagementScore + increment)
430
-
431
- // Decay engagement score over time
432
- setTimeout(() => {
433
- this.behaviorData.engagementScore = Math.max(
434
- 0,
435
- this.behaviorData.engagementScore - increment * 0.5
436
- )
437
- this.notifyListeners()
438
- }, 30000) // 30 seconds decay
439
-
440
- this.notifyListeners()
441
- }
442
-
443
- private notifyListeners(): void {
444
- this.listeners.forEach((listener) => listener(this.behaviorData))
445
- }
446
- }
447
-
448
- interface UserBehaviorData {
449
- isLikelyToInteract: boolean
450
- engagementScore: number
451
- predictedSources: string[]
452
- interactionHistory: Array<{
453
- type: string
454
- timestamp: number
455
- }>
456
- }
457
-
458
- export default MediaResourcePreloader
@@ -1,98 +0,0 @@
1
- import { RefreshCw, WifiOff } from "lucide-react"
2
- import { memo, useCallback } from "react"
3
- import { cn } from "../../lib/utils"
4
-
5
- interface OfflineMessageProps {
6
- className?: string
7
- title?: string
8
- message?: string
9
- onRetry?: () => void
10
- retryLabel?: string
11
- showRetry?: boolean
12
- }
13
-
14
- const OfflineMessageComponent = memo(function OfflineMessage({
15
- className,
16
- title = "You're offline",
17
- message = "Check your internet connection and try again.",
18
- onRetry,
19
- retryLabel = "Retry",
20
- showRetry = true
21
- }: OfflineMessageProps) {
22
- const handleRetry = useCallback(() => {
23
- onRetry?.()
24
- }, [onRetry])
25
-
26
- return (
27
- <div
28
- className={cn(
29
- "flex flex-col items-center justify-center p-8 text-center",
30
- "rounded-lg bg-[color:var(--media-bg)]",
31
- className
32
- )}
33
- role="alert"
34
- aria-live="polite">
35
- <div className="mb-4 rounded-full bg-[color:var(--media-control-bg)] p-4" aria-hidden="true">
36
- <WifiOff size={48} className="text-[color:var(--media-text-secondary)]" />
37
- </div>
38
- <h3 className="mb-2 font-semibold text-[color:var(--media-text)] text-lg">{title}</h3>
39
- <p className="mb-4 max-w-sm text-[color:var(--media-text-secondary)] text-sm">{message}</p>
40
- {showRetry && onRetry && (
41
- <button
42
- onClick={handleRetry}
43
- className={cn(
44
- "inline-flex items-center gap-2 rounded-lg px-4 py-2",
45
- "bg-[color:var(--media-primary)] text-white",
46
- "transition-opacity hover:opacity-90",
47
- "focus:outline-none focus:ring-2 focus:ring-[color:var(--media-primary)] focus:ring-offset-2"
48
- )}
49
- aria-label={retryLabel}>
50
- <RefreshCw size={16} />
51
- {retryLabel}
52
- </button>
53
- )}
54
- </div>
55
- )
56
- })
57
-
58
- interface OfflineBannerProps {
59
- className?: string
60
- onRetry?: () => void
61
- }
62
-
63
- export const OfflineBanner = memo(function OfflineBanner({
64
- className,
65
- onRetry
66
- }: OfflineBannerProps) {
67
- return (
68
- <div
69
- className={cn(
70
- "flex items-center justify-between gap-4 p-3 px-4",
71
- "rounded-lg border border-amber-500/20 bg-amber-500/10",
72
- className
73
- )}
74
- role="alert"
75
- aria-live="polite">
76
- <div className="flex items-center gap-3">
77
- <WifiOff size={20} className="text-amber-500" aria-hidden="true" />
78
- <span className="text-amber-500 text-sm">
79
- You're offline. Some features may be limited.
80
- </span>
81
- </div>
82
- {onRetry && (
83
- <button
84
- onClick={onRetry}
85
- className={cn(
86
- "rounded px-3 py-1 text-sm",
87
- "bg-amber-500/20 text-amber-500",
88
- "transition-colors hover:bg-amber-500/30"
89
- )}
90
- aria-label="Retry connection check">
91
- Retry
92
- </button>
93
- )}
94
- </div>
95
- )
96
- })
97
-
98
- export { OfflineMessageComponent as OfflineMessage }