@therealtinhtute/baroiplayer 1.0.0

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 (244) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +384 -0
  3. package/dist/context/media.js +2 -0
  4. package/dist/context/media.js.map +1 -0
  5. package/dist/context/media.mjs +15 -0
  6. package/dist/context/media.mjs.map +1 -0
  7. package/dist/context/store.js +2 -0
  8. package/dist/context/store.js.map +1 -0
  9. package/dist/context/store.mjs +5 -0
  10. package/dist/context/store.mjs.map +1 -0
  11. package/dist/context-BMteAJDN.js +1140 -0
  12. package/dist/context-BMteAJDN.js.map +1 -0
  13. package/dist/context-DCJ_scmO.cjs +23 -0
  14. package/dist/context-DCJ_scmO.cjs.map +1 -0
  15. package/dist/core-events-B5W_j8yU.js +480 -0
  16. package/dist/core-events-B5W_j8yU.js.map +1 -0
  17. package/dist/core-events-CN0-Vhhq.cjs +2 -0
  18. package/dist/core-events-CN0-Vhhq.cjs.map +1 -0
  19. package/dist/core-plugins-Bq9KLany.js +696 -0
  20. package/dist/core-plugins-Bq9KLany.js.map +1 -0
  21. package/dist/core-plugins-CPDSHMiQ.cjs +2 -0
  22. package/dist/core-plugins-CPDSHMiQ.cjs.map +1 -0
  23. package/dist/core.js +37 -0
  24. package/dist/core.js.map +1 -0
  25. package/dist/core.mjs +1217 -0
  26. package/dist/core.mjs.map +1 -0
  27. package/dist/enhanced-components-DHv0MFvG.js +1073 -0
  28. package/dist/enhanced-components-DHv0MFvG.js.map +1 -0
  29. package/dist/enhanced-components-DTIObgB7.cjs +2 -0
  30. package/dist/enhanced-components-DTIObgB7.cjs.map +1 -0
  31. package/dist/hooks-C_r8wexn.cjs +4 -0
  32. package/dist/hooks-C_r8wexn.cjs.map +1 -0
  33. package/dist/hooks-Da2wVXlF.js +1630 -0
  34. package/dist/hooks-Da2wVXlF.js.map +1 -0
  35. package/dist/index.css +1 -0
  36. package/dist/index.js +112 -0
  37. package/dist/index.js.map +1 -0
  38. package/dist/index.mjs +6126 -0
  39. package/dist/index.mjs.map +1 -0
  40. package/dist/minimal-components-DSq5sQpy.js +2002 -0
  41. package/dist/minimal-components-DSq5sQpy.js.map +1 -0
  42. package/dist/minimal-components-DflWiihN.cjs +2 -0
  43. package/dist/minimal-components-DflWiihN.cjs.map +1 -0
  44. package/dist/minimal-components.css +1 -0
  45. package/dist/mona-loading.gif +0 -0
  46. package/dist/performance-monitor-CUW6f5ll.cjs +2 -0
  47. package/dist/performance-monitor-CUW6f5ll.cjs.map +1 -0
  48. package/dist/performance-monitor-rMW1RgV3.js +302 -0
  49. package/dist/performance-monitor-rMW1RgV3.js.map +1 -0
  50. package/dist/utils-BnscpYYd.js +2798 -0
  51. package/dist/utils-BnscpYYd.js.map +1 -0
  52. package/dist/utils-D_czS_0K.cjs +9 -0
  53. package/dist/utils-D_czS_0K.cjs.map +1 -0
  54. package/dist/utils.js +2 -0
  55. package/dist/utils.js.map +1 -0
  56. package/dist/utils.mjs +7 -0
  57. package/dist/utils.mjs.map +1 -0
  58. package/package.json +114 -0
  59. package/src/adapters/videojs-adapter.tsx +470 -0
  60. package/src/assets/mona-loading.gif +0 -0
  61. package/src/components/AnimateLoading.tsx +115 -0
  62. package/src/components/LoadingState.tsx +248 -0
  63. package/src/components/accessibility/keyboard-help-overlay.tsx +213 -0
  64. package/src/components/audio-player.tsx +85 -0
  65. package/src/components/basic/index.ts +37 -0
  66. package/src/components/enhanced/advanced-features.tsx +316 -0
  67. package/src/components/enhanced/debug-panel.tsx +422 -0
  68. package/src/components/enhanced/enhanced-controls.tsx +600 -0
  69. package/src/components/enhanced/enhanced-media-player.tsx +509 -0
  70. package/src/components/enhanced/error-handling.tsx +345 -0
  71. package/src/components/enhanced/index.ts +39 -0
  72. package/src/components/enhanced/media-player-enhanced.tsx +349 -0
  73. package/src/components/examples/basic-video-player.tsx +55 -0
  74. package/src/components/examples/custom-controls-example.tsx +63 -0
  75. package/src/components/examples/enhanced-controls-example.tsx +114 -0
  76. package/src/components/examples/enhanced-media-player-example.tsx +293 -0
  77. package/src/components/examples/loading-states-demo.tsx +142 -0
  78. package/src/components/examples/react-19-demo.tsx +381 -0
  79. package/src/components/examples/volume-orientation-demo.tsx +114 -0
  80. package/src/components/icon-demo.tsx +209 -0
  81. package/src/components/icons/index.tsx +166 -0
  82. package/src/components/icons/svg-icons/ArrowLeftIcon.tsx +18 -0
  83. package/src/components/icons/svg-icons/ArrowRightIcon.tsx +18 -0
  84. package/src/components/icons/svg-icons/AudioIcon.tsx +22 -0
  85. package/src/components/icons/svg-icons/BackwardIcon.tsx +12 -0
  86. package/src/components/icons/svg-icons/CameraIcon.tsx +19 -0
  87. package/src/components/icons/svg-icons/CheckIcon.tsx +19 -0
  88. package/src/components/icons/svg-icons/EnablePiPIcon.tsx +17 -0
  89. package/src/components/icons/svg-icons/ForwardIcon.tsx +12 -0
  90. package/src/components/icons/svg-icons/FullscreenEnterIcon.tsx +23 -0
  91. package/src/components/icons/svg-icons/FullscreenExitIcon.tsx +23 -0
  92. package/src/components/icons/svg-icons/LoadingIcon.tsx +32 -0
  93. package/src/components/icons/svg-icons/PauseIcon.tsx +23 -0
  94. package/src/components/icons/svg-icons/PlayIcon.tsx +21 -0
  95. package/src/components/icons/svg-icons/PlaybackSpeedIcon.tsx +23 -0
  96. package/src/components/icons/svg-icons/QualityIcon.tsx +21 -0
  97. package/src/components/icons/svg-icons/SettingsIcon.tsx +12 -0
  98. package/src/components/icons/svg-icons/SliderIcon.tsx +21 -0
  99. package/src/components/icons/svg-icons/SubtitleIcon.tsx +21 -0
  100. package/src/components/icons/svg-icons/SubtitleOffIcon.tsx +25 -0
  101. package/src/components/icons/svg-icons/UnPiPIcon.tsx +17 -0
  102. package/src/components/icons/svg-icons/VolumeMutedIcon.tsx +16 -0
  103. package/src/components/icons/svg-icons/VolumeOneIcon.tsx +22 -0
  104. package/src/components/icons/svg-icons/VolumeThreeIcon.tsx +16 -0
  105. package/src/components/icons/svg-icons/VolumeTwoIcon.tsx +16 -0
  106. package/src/components/legacy.tsx +93 -0
  107. package/src/components/media-metadata-display.tsx +100 -0
  108. package/src/components/media-player-audio.tsx +39 -0
  109. package/src/components/media-player-controls.tsx +226 -0
  110. package/src/components/media-player-error.tsx +163 -0
  111. package/src/components/media-player-fullscreen.tsx +109 -0
  112. package/src/components/media-player-hls.tsx +111 -0
  113. package/src/components/media-player-loading.tsx +76 -0
  114. package/src/components/media-player-play.tsx +75 -0
  115. package/src/components/media-player-root.tsx +340 -0
  116. package/src/components/media-player-seek.tsx +168 -0
  117. package/src/components/media-player-time.tsx +99 -0
  118. package/src/components/media-player-tooltip.tsx +58 -0
  119. package/src/components/media-player-video.tsx +39 -0
  120. package/src/components/media-player-volume.tsx +155 -0
  121. package/src/components/media-player.tsx +257 -0
  122. package/src/components/media-suspense.tsx +362 -0
  123. package/src/components/player-settings-form.tsx +163 -0
  124. package/src/components/react-player-wrapper.tsx +651 -0
  125. package/src/components/simple-video-player.tsx +60 -0
  126. package/src/components/ui/enhanced-seek-bar.tsx +235 -0
  127. package/src/components/ui/fullscreen-button.tsx +60 -0
  128. package/src/components/ui/media-resource-preloader.tsx +395 -0
  129. package/src/components/ui/play-button.tsx +107 -0
  130. package/src/components/ui/seek-bar.tsx +161 -0
  131. package/src/components/ui/time-display.tsx +40 -0
  132. package/src/components/ui/volume-control.tsx +143 -0
  133. package/src/components/unified/base-media-player.tsx +246 -0
  134. package/src/components/unified/media-player.tsx +75 -0
  135. package/src/components/variants/minimal/AccessibleMinimalPlayer.tsx +561 -0
  136. package/src/components/variants/minimal/EnhancedMinimalMediaPlayer.tsx +552 -0
  137. package/src/components/variants/minimal/MinimalControls.tsx +142 -0
  138. package/src/components/variants/minimal/MinimalLoading.tsx +32 -0
  139. package/src/components/variants/minimal/MinimalMediaPlayer.tsx +315 -0
  140. package/src/components/variants/minimal/MinimalOverlay.tsx +64 -0
  141. package/src/components/variants/minimal/MinimalPlayButton.tsx +65 -0
  142. package/src/components/variants/minimal/MinimalSeekBar.tsx +150 -0
  143. package/src/components/variants/minimal/MinimalVolumeControl.tsx +80 -0
  144. package/src/components/variants/minimal/SimpleMinimalPlayer.tsx +210 -0
  145. package/src/components/variants/minimal/components/CenterPlayButton.tsx +22 -0
  146. package/src/components/variants/minimal/components/ControlBar.tsx +146 -0
  147. package/src/components/variants/minimal/components/EnhancedSettingsMenu.tsx +361 -0
  148. package/src/components/variants/minimal/components/PlaybackControls.tsx +51 -0
  149. package/src/components/variants/minimal/components/RightControls.tsx +173 -0
  150. package/src/components/variants/minimal/components/SeekBar.tsx +131 -0
  151. package/src/components/variants/minimal/components/SettingsDropdown.tsx +70 -0
  152. package/src/components/variants/minimal/components/SubtitleDisplay.tsx +21 -0
  153. package/src/components/variants/minimal/components/TimeDisplay.tsx +18 -0
  154. package/src/components/variants/minimal/components/VideoElement.tsx +40 -0
  155. package/src/components/variants/minimal/components/VolumeControl.tsx +217 -0
  156. package/src/components/variants/minimal/index.ts +23 -0
  157. package/src/components/video-player.tsx +100 -0
  158. package/src/context/error-handling.ts +394 -0
  159. package/src/context/media-context.tsx +208 -0
  160. package/src/context/media-provider.tsx +265 -0
  161. package/src/context/media-store.ts +379 -0
  162. package/src/context/persistence.ts +453 -0
  163. package/src/core/events/event-system.ts +442 -0
  164. package/src/core/events/hooks.ts +302 -0
  165. package/src/core/events/index.ts +22 -0
  166. package/src/core/events/middleware.ts +269 -0
  167. package/src/core/index.ts +22 -0
  168. package/src/core/optimization/bundle-optimizer.tsx +308 -0
  169. package/src/core/performance/cicd.ts +96 -0
  170. package/src/core/performance/index.ts +38 -0
  171. package/src/core/performance/media-loading-optimizer.ts +538 -0
  172. package/src/core/performance/performance-budgets.ts +432 -0
  173. package/src/core/performance/performance-monitor.tsx +476 -0
  174. package/src/core/performance/performance-testing.ts +459 -0
  175. package/src/core/plugins/base-plugin.ts +224 -0
  176. package/src/core/plugins/enhanced-plugin-system.ts +411 -0
  177. package/src/core/plugins/examples/analytics-plugin.ts +242 -0
  178. package/src/core/plugins/index.ts +39 -0
  179. package/src/core/plugins/registry.ts +327 -0
  180. package/src/core/plugins/types.ts +159 -0
  181. package/src/core/plugins/utils.ts +316 -0
  182. package/src/core/progressive-loading.tsx +322 -0
  183. package/src/core/providers/enhanced-hls-provider.ts +339 -0
  184. package/src/core/providers/service-provider.tsx +168 -0
  185. package/src/core/utils.tsx +38 -0
  186. package/src/features/media-session/media-session-manager.ts +429 -0
  187. package/src/features/picture-in-picture/pip-manager.ts +429 -0
  188. package/src/features/playlist/playlist-manager.ts +606 -0
  189. package/src/features/subtitles/subtitle-manager.ts +441 -0
  190. package/src/features/subtitles/subtitle-parser.ts +280 -0
  191. package/src/features/thumbnails/thumbnail-generator.ts +519 -0
  192. package/src/hooks/accessibility/index.ts +27 -0
  193. package/src/hooks/accessibility/use-accessibility-preferences.ts +188 -0
  194. package/src/hooks/accessibility/use-focus-management.ts +176 -0
  195. package/src/hooks/accessibility/use-keyboard-shortcuts.ts +144 -0
  196. package/src/hooks/accessibility/use-screen-reader.ts +182 -0
  197. package/src/hooks/core/index.ts +47 -0
  198. package/src/hooks/legacy.ts +27 -0
  199. package/src/hooks/use-enhanced-media-player.ts +468 -0
  200. package/src/hooks/use-intelligent-preloading.ts +358 -0
  201. package/src/hooks/use-keyboard-controls.ts +115 -0
  202. package/src/hooks/use-media-actions.ts +175 -0
  203. package/src/hooks/use-media-metadata.ts +89 -0
  204. package/src/hooks/use-media-optimistic.ts +270 -0
  205. package/src/hooks/use-media-player.ts +312 -0
  206. package/src/hooks/use-media-state.ts +190 -0
  207. package/src/hooks/use-memory-optimization.ts +358 -0
  208. package/src/hooks/use-optimistic-controls.ts +92 -0
  209. package/src/hooks/use-optimized-media.ts +263 -0
  210. package/src/hooks/use-touch-gestures.ts +417 -0
  211. package/src/hooks/useEnhancedSubtitles.ts +258 -0
  212. package/src/hooks/useKeyboardShortcuts.ts +74 -0
  213. package/src/hooks/useMediaControls.ts +52 -0
  214. package/src/hooks/useScreenshot.ts +57 -0
  215. package/src/hooks/useSubtitles.ts +91 -0
  216. package/src/hooks/useVideoPlayer.ts +232 -0
  217. package/src/icons/components/FullscreenIcon.tsx +37 -0
  218. package/src/icons/components/SettingsIcon.tsx +38 -0
  219. package/src/icons/components/animated/LoadingIcon.tsx +43 -0
  220. package/src/icons/components/animated/PlayPauseIcon.tsx +50 -0
  221. package/src/icons/components/media/PauseIcon.tsx +39 -0
  222. package/src/icons/components/media/PlayIcon.tsx +38 -0
  223. package/src/icons/components/volume/VolumeIcon.tsx +39 -0
  224. package/src/icons/components/volume/VolumeOffIcon.tsx +39 -0
  225. package/src/icons/index.ts +56 -0
  226. package/src/icons/provider.tsx +64 -0
  227. package/src/icons/types.ts +40 -0
  228. package/src/index-enhanced.ts +35 -0
  229. package/src/index-legacy.ts +326 -0
  230. package/src/index.css +102 -0
  231. package/src/index.ts +216 -0
  232. package/src/lib/deprecation.ts +51 -0
  233. package/src/lib/format-time.ts +37 -0
  234. package/src/lib/index.ts +3 -0
  235. package/src/lib/utils.ts +6 -0
  236. package/src/styles/globals.css +462 -0
  237. package/src/styles/minimal-player.css +589 -0
  238. package/src/styles/pixel-art.css +46 -0
  239. package/src/styles/videojs.css +100 -0
  240. package/src/test/setup.ts +79 -0
  241. package/src/types/events.ts +47 -0
  242. package/src/types/formats.ts +95 -0
  243. package/src/types/index.ts +190 -0
  244. package/src/types/videojs-plugins.d.ts +14 -0
@@ -0,0 +1,345 @@
1
+ "use client"
2
+
3
+ import React from "react"
4
+ import { useMediaSelector, useMediaDispatch, MediaActionTypes } from "../../context/media-context"
5
+ import { cn } from "../../lib/utils"
6
+
7
+ // Enhanced loading component with skeleton and progress
8
+ export const EnhancedLoading = function EnhancedLoading({
9
+ className,
10
+ showProgress = false,
11
+ message = "Loading..."
12
+ }: {
13
+ className?: string
14
+ showProgress?: boolean
15
+ message?: string
16
+ }) {
17
+ const isLoading = useMediaSelector(state => state.isLoading)
18
+ const [progress, setProgress] = React.useState(0)
19
+
20
+ // Simulate loading progress for better UX
21
+ React.useEffect(() => {
22
+ if (!isLoading) {
23
+ setProgress(0)
24
+ return
25
+ }
26
+
27
+ const interval = setInterval(() => {
28
+ setProgress(prev => {
29
+ if (prev >= 90) return prev
30
+ return prev + Math.random() * 10
31
+ })
32
+ }, 200)
33
+
34
+ return () => clearInterval(interval)
35
+ }, [isLoading])
36
+
37
+ if (!isLoading) return null
38
+
39
+ return (
40
+ <div className={cn(
41
+ "absolute inset-0 z-40 flex items-center justify-center bg-black/50 backdrop-blur-sm",
42
+ className
43
+ )}>
44
+ <div className="flex flex-col items-center gap-4 text-white">
45
+ {/* Spinner */}
46
+ <div className="relative">
47
+ <div className="h-12 w-12 animate-spin rounded-full border-4 border-white/20 border-t-white" />
48
+ {showProgress && (
49
+ <div className="absolute inset-0 flex items-center justify-center">
50
+ <span className="font-medium text-xs">{Math.round(progress)}%</span>
51
+ </div>
52
+ )}
53
+ </div>
54
+
55
+ {/* Message */}
56
+ <div className="text-center">
57
+ <p className="font-medium text-sm">{message}</p>
58
+ {showProgress && (
59
+ <div className="mt-2 h-1 w-48 overflow-hidden rounded-full bg-white/20">
60
+ <div
61
+ className="h-full bg-primary transition-all duration-300 ease-out"
62
+ style={{ width: `${progress}%` }}
63
+ />
64
+ </div>
65
+ )}
66
+ </div>
67
+ </div>
68
+ </div>
69
+ )
70
+ }
71
+
72
+ // Enhanced error component with retry and detailed messages
73
+ export const EnhancedError = function EnhancedError({
74
+ className,
75
+ onRetry,
76
+ showDetails = false
77
+ }: {
78
+ className?: string
79
+ onRetry?: () => void
80
+ showDetails?: boolean
81
+ }) {
82
+ const error = useMediaSelector(state => state.error)
83
+ const dispatch = useMediaDispatch()
84
+ const [showFullError, setShowFullError] = React.useState(false)
85
+
86
+ const handleRetry = React.useCallback(() => {
87
+ dispatch({ type: MediaActionTypes.SET_ERROR, detail: null })
88
+ onRetry?.()
89
+ }, [dispatch, onRetry])
90
+
91
+ const handleDismiss = React.useCallback(() => {
92
+ dispatch({ type: MediaActionTypes.SET_ERROR, detail: null })
93
+ }, [dispatch])
94
+
95
+ if (!error) return null
96
+
97
+ // Parse error types for better user messages
98
+ const getErrorMessage = (error: string) => {
99
+ if (error.includes('network') || error.includes('fetch')) {
100
+ return {
101
+ title: "Network Error",
102
+ message: "Unable to load the video. Please check your internet connection.",
103
+ icon: "🌐"
104
+ }
105
+ }
106
+ if (error.includes('format') || error.includes('codec')) {
107
+ return {
108
+ title: "Format Not Supported",
109
+ message: "This video format is not supported by your browser.",
110
+ icon: "🎥"
111
+ }
112
+ }
113
+ if (error.includes('permission') || error.includes('cors')) {
114
+ return {
115
+ title: "Access Denied",
116
+ message: "Unable to access the video due to permission restrictions.",
117
+ icon: "🔒"
118
+ }
119
+ }
120
+ return {
121
+ title: "Playback Error",
122
+ message: "An error occurred while trying to play the video.",
123
+ icon: "⚠️"
124
+ }
125
+ }
126
+
127
+ const errorInfo = getErrorMessage(error)
128
+
129
+ return (
130
+ <div className={cn(
131
+ "absolute inset-0 z-50 flex items-center justify-center bg-black/80 backdrop-blur-sm",
132
+ className
133
+ )}>
134
+ <div className="mx-4 max-w-md rounded-lg border border-red-500/20 bg-black/90 p-6 text-center">
135
+ {/* Error icon */}
136
+ <div className="mb-4 text-4xl">{errorInfo.icon}</div>
137
+
138
+ {/* Error title */}
139
+ <h3 className="mb-2 font-semibold text-lg text-white">
140
+ {errorInfo.title}
141
+ </h3>
142
+
143
+ {/* Error message */}
144
+ <p className="mb-4 text-sm text-white/80">
145
+ {errorInfo.message}
146
+ </p>
147
+
148
+ {/* Error details (collapsible) */}
149
+ {showDetails && (
150
+ <div className="mb-4">
151
+ <button
152
+ onClick={() => setShowFullError(!showFullError)}
153
+ className="text-white/60 text-xs transition-colors hover:text-white/80"
154
+ >
155
+ {showFullError ? "Hide" : "Show"} technical details
156
+ </button>
157
+ {showFullError && (
158
+ <div className="mt-2 rounded border border-red-500/30 bg-red-900/20 p-3">
159
+ <code className="break-all text-red-300 text-xs">
160
+ {error}
161
+ </code>
162
+ </div>
163
+ )}
164
+ </div>
165
+ )}
166
+
167
+ {/* Action buttons */}
168
+ <div className="flex justify-center gap-3">
169
+ {onRetry && (
170
+ <button
171
+ onClick={handleRetry}
172
+ className="rounded-lg bg-primary px-4 py-2 font-medium text-sm text-white transition-colors hover:bg-primary/80"
173
+ >
174
+ Try Again
175
+ </button>
176
+ )}
177
+ <button
178
+ onClick={handleDismiss}
179
+ className="rounded-lg bg-white/10 px-4 py-2 font-medium text-sm text-white transition-colors hover:bg-white/20"
180
+ >
181
+ Dismiss
182
+ </button>
183
+ </div>
184
+ </div>
185
+ </div>
186
+ )
187
+ }
188
+
189
+ // Error boundary component for React errors
190
+ interface ErrorBoundaryState {
191
+ hasError: boolean
192
+ error?: Error
193
+ }
194
+
195
+ export class MediaPlayerErrorBoundary extends React.Component<
196
+ { children: React.ReactNode; fallback?: React.ComponentType<{ error: Error; retry: () => void }> },
197
+ ErrorBoundaryState
198
+ > {
199
+ constructor(props: any) {
200
+ super(props)
201
+ this.state = { hasError: false }
202
+ }
203
+
204
+ static getDerivedStateFromError(error: Error): ErrorBoundaryState {
205
+ return { hasError: true, error }
206
+ }
207
+
208
+ componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {
209
+ console.error('MediaPlayer Error:', error, errorInfo)
210
+ }
211
+
212
+ retry = () => {
213
+ this.setState({ hasError: false, error: undefined })
214
+ }
215
+
216
+ render() {
217
+ if (this.state.hasError) {
218
+ if (this.props.fallback) {
219
+ const Fallback = this.props.fallback
220
+ return <Fallback error={this.state.error!} retry={this.retry} />
221
+ }
222
+
223
+ return (
224
+ <div className="absolute inset-0 z-50 flex items-center justify-center bg-black/80 backdrop-blur-sm">
225
+ <div className="mx-4 max-w-md rounded-lg border border-red-500/20 bg-black/90 p-6 text-center">
226
+ <div className="mb-4 text-4xl">💥</div>
227
+ <h3 className="mb-2 font-semibold text-lg text-white">
228
+ Something went wrong
229
+ </h3>
230
+ <p className="mb-4 text-sm text-white/80">
231
+ The media player encountered an unexpected error.
232
+ </p>
233
+ <button
234
+ onClick={this.retry}
235
+ className="rounded-lg bg-primary px-4 py-2 font-medium text-sm text-white transition-colors hover:bg-primary/80"
236
+ >
237
+ Reload Player
238
+ </button>
239
+ </div>
240
+ </div>
241
+ )
242
+ }
243
+
244
+ return this.props.children
245
+ }
246
+ }
247
+
248
+ // Connection status indicator
249
+ export const ConnectionStatus = function ConnectionStatus({
250
+ className
251
+ }: {
252
+ className?: string
253
+ }) {
254
+ const [isOnline, setIsOnline] = React.useState(navigator.onLine)
255
+ const [showOfflineMessage, setShowOfflineMessage] = React.useState(false)
256
+
257
+ React.useEffect(() => {
258
+ const handleOnline = () => {
259
+ setIsOnline(true)
260
+ setShowOfflineMessage(false)
261
+ }
262
+
263
+ const handleOffline = () => {
264
+ setIsOnline(false)
265
+ setShowOfflineMessage(true)
266
+ }
267
+
268
+ window.addEventListener('online', handleOnline)
269
+ window.addEventListener('offline', handleOffline)
270
+
271
+ return () => {
272
+ window.removeEventListener('online', handleOnline)
273
+ window.removeEventListener('offline', handleOffline)
274
+ }
275
+ }, [])
276
+
277
+ if (!showOfflineMessage) return null
278
+
279
+ return (
280
+ <div className={cn(
281
+ "absolute top-4 right-4 left-4 z-50 rounded-lg border border-orange-400/30 bg-orange-500/90 p-3 backdrop-blur-sm",
282
+ className
283
+ )}>
284
+ <div className="flex items-center gap-3 text-white">
285
+ <div className="h-2 w-2 animate-pulse rounded-full bg-orange-300" />
286
+ <span className="font-medium text-sm">
287
+ You're offline. Video playback may be affected.
288
+ </span>
289
+ </div>
290
+ </div>
291
+ )
292
+ }
293
+
294
+ // Buffer health indicator
295
+ export const BufferHealthIndicator = function BufferHealthIndicator({
296
+ className
297
+ }: {
298
+ className?: string
299
+ }) {
300
+ const buffered = useMediaSelector(state => state.buffered)
301
+ const currentTime = useMediaSelector(state => state.currentTime)
302
+ const duration = useMediaSelector(state => state.duration)
303
+
304
+ const bufferHealth = React.useMemo(() => {
305
+ if (!buffered || duration === 0) return 0
306
+
307
+ let bufferedAhead = 0
308
+ for (let i = 0; i < buffered.length; i++) {
309
+ const start = buffered.start(i)
310
+ const end = buffered.end(i)
311
+ if (start <= currentTime && end > currentTime) {
312
+ bufferedAhead = end - currentTime
313
+ break
314
+ }
315
+ }
316
+
317
+ return Math.min(100, (bufferedAhead / 30) * 100) // 30 seconds = 100%
318
+ }, [buffered, currentTime, duration])
319
+
320
+ const getHealthColor = (health: number) => {
321
+ if (health > 70) return "bg-green-500"
322
+ if (health > 30) return "bg-yellow-500"
323
+ return "bg-red-500"
324
+ }
325
+
326
+ if (bufferHealth > 80) return null // Don't show when buffer is healthy
327
+
328
+ return (
329
+ <div className={cn(
330
+ "absolute top-4 right-4 z-40 rounded-lg border border-white/20 bg-black/80 p-2 backdrop-blur-sm",
331
+ className
332
+ )}>
333
+ <div className="flex items-center gap-2 text-white text-xs">
334
+ <span>Buffer:</span>
335
+ <div className="h-1 w-16 overflow-hidden rounded-full bg-white/20">
336
+ <div
337
+ className={cn("h-full transition-all duration-300", getHealthColor(bufferHealth))}
338
+ style={{ width: `${bufferHealth}%` }}
339
+ />
340
+ </div>
341
+ <span>{Math.round(bufferHealth)}%</span>
342
+ </div>
343
+ </div>
344
+ )
345
+ }
@@ -0,0 +1,39 @@
1
+ // Enhanced Components with Advanced Features
2
+ export {
3
+ ChaptersPanel,
4
+ PictureInPictureButton,
5
+ PlaybackSpeedSelector,
6
+ QualitySelector,
7
+ SubtitleSelector
8
+ } from "./advanced-features";
9
+
10
+ // Enhanced Control Components
11
+ export {
12
+ EnhancedPlayButton,
13
+ EnhancedSeekBar,
14
+ EnhancedTimeDisplay,
15
+ EnhancedVolumeControl,
16
+ EnhancedBackwardButton,
17
+ EnhancedForwardButton,
18
+ EnhancedControlBar
19
+ } from "./enhanced-controls";
20
+
21
+ // Enhanced Error Handling
22
+ export {
23
+ BufferHealthIndicator,
24
+ ConnectionStatus,
25
+ EnhancedError,
26
+ EnhancedLoading,
27
+ MediaPlayerErrorBoundary
28
+ } from "./error-handling";
29
+
30
+ // Main Enhanced Media Player
31
+ export { EnhancedMediaPlayer } from "./media-player-enhanced";
32
+
33
+ // Enhanced Examples
34
+ export {
35
+ EnhancedControlsExample,
36
+ CustomEnhancedControlsExample,
37
+ SkipButtonsOnlyExample
38
+ } from "../examples/enhanced-controls-example";
39
+ export type { EnhancedControlsExampleProps } from "../examples/enhanced-controls-example";