@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,349 @@
1
+ "use client"
2
+
3
+ import React from "react"
4
+ import { useMediaContext, useMediaSelector, useMediaDispatch, MediaActionTypes } from "../../context/media-context"
5
+ import { cn } from "../../lib/utils"
6
+
7
+ // Enhanced media player with better performance and mobile support
8
+ export interface EnhancedMediaPlayerProps {
9
+ children: React.ReactNode
10
+ className?: string
11
+ autoHide?: boolean
12
+ autoHideDelay?: number
13
+ showControlsOnHover?: boolean
14
+ showControlsOnTouch?: boolean
15
+ enableKeyboardControls?: boolean
16
+ enableTouchGestures?: boolean
17
+ onPlay?: () => void
18
+ onPause?: () => void
19
+ onTimeUpdate?: (time: number) => void
20
+ onVolumeChange?: (volume: number) => void
21
+ onFullscreenChange?: (isFullscreen: boolean) => void
22
+ }
23
+
24
+ // Custom hook for auto-hide controls
25
+ function useAutoHideControls(
26
+ autoHide: boolean,
27
+ delay: number,
28
+ showOnHover: boolean,
29
+ showOnTouch: boolean
30
+ ) {
31
+ const [showControls, setShowControls] = React.useState(true)
32
+ const [isHovering, setIsHovering] = React.useState(false)
33
+ const [isTouching, setIsTouching] = React.useState(false)
34
+ const timeoutRef = React.useRef<NodeJS.Timeout | null>(null)
35
+
36
+ const resetTimeout = React.useCallback(() => {
37
+ if (timeoutRef.current) {
38
+ clearTimeout(timeoutRef.current)
39
+ }
40
+ if (autoHide) {
41
+ timeoutRef.current = setTimeout(() => {
42
+ if (!isHovering && !isTouching) {
43
+ setShowControls(false)
44
+ }
45
+ }, delay)
46
+ }
47
+ }, [autoHide, delay, isHovering, isTouching])
48
+
49
+ const showControlsTemporarily = React.useCallback(() => {
50
+ setShowControls(true)
51
+ resetTimeout()
52
+ }, [resetTimeout])
53
+
54
+ React.useEffect(() => {
55
+ if (autoHide) {
56
+ resetTimeout()
57
+ } else {
58
+ setShowControls(true)
59
+ }
60
+ return () => {
61
+ if (timeoutRef.current) {
62
+ clearTimeout(timeoutRef.current)
63
+ }
64
+ }
65
+ }, [autoHide, resetTimeout])
66
+
67
+ const handleMouseEnter = React.useCallback(() => {
68
+ if (showOnHover) {
69
+ setIsHovering(true)
70
+ setShowControls(true)
71
+ }
72
+ }, [showOnHover])
73
+
74
+ const handleMouseLeave = React.useCallback(() => {
75
+ if (showOnHover) {
76
+ setIsHovering(false)
77
+ resetTimeout()
78
+ }
79
+ }, [showOnHover, resetTimeout])
80
+
81
+ const handleTouchStart = React.useCallback(() => {
82
+ if (showOnTouch) {
83
+ setIsTouching(true)
84
+ showControlsTemporarily()
85
+ }
86
+ }, [showOnTouch, showControlsTemporarily])
87
+
88
+ const handleTouchEnd = React.useCallback(() => {
89
+ if (showOnTouch) {
90
+ setIsTouching(false)
91
+ resetTimeout()
92
+ }
93
+ }, [showOnTouch, resetTimeout])
94
+
95
+ return {
96
+ showControls,
97
+ showControlsTemporarily,
98
+ handleMouseEnter,
99
+ handleMouseLeave,
100
+ handleTouchStart,
101
+ handleTouchEnd
102
+ }
103
+ }
104
+
105
+ // Custom hook for touch gestures
106
+ function useTouchGestures(enabled: boolean) {
107
+ const dispatch = useMediaDispatch()
108
+ const isPlaying = useMediaSelector(state => state.isPlaying)
109
+ const currentTime = useMediaSelector(state => state.currentTime)
110
+ const duration = useMediaSelector(state => state.duration)
111
+ const volume = useMediaSelector(state => state.volume)
112
+
113
+ const [touchStart, setTouchStart] = React.useState<{ x: number; y: number; time: number } | null>(null)
114
+ const [isDoubleTap, setIsDoubleTap] = React.useState(false)
115
+
116
+ const handleTouchStart = React.useCallback((e: React.TouchEvent) => {
117
+ if (!enabled) return
118
+
119
+ const touch = e.touches[0]
120
+ if (!touch) return
121
+
122
+ const now = Date.now()
123
+
124
+ if (touchStart && now - touchStart.time < 300) {
125
+ setIsDoubleTap(true)
126
+ // Double tap to play/pause
127
+ dispatch({
128
+ type: isPlaying ? MediaActionTypes.PAUSE : MediaActionTypes.PLAY
129
+ })
130
+ } else {
131
+ setTouchStart({
132
+ x: touch.clientX,
133
+ y: touch.clientY,
134
+ time: now
135
+ })
136
+ setIsDoubleTap(false)
137
+ }
138
+ }, [enabled, touchStart, isPlaying, dispatch])
139
+
140
+ const handleTouchMove = React.useCallback((e: React.TouchEvent) => {
141
+ if (!enabled || !touchStart || isDoubleTap) return
142
+
143
+ const touch = e.touches[0]
144
+ if (!touch) return
145
+
146
+ const deltaX = touch.clientX - touchStart.x
147
+ const deltaY = touch.clientY - touchStart.y
148
+
149
+ // Horizontal swipe for seeking
150
+ if (Math.abs(deltaX) > Math.abs(deltaY) && Math.abs(deltaX) > 50) {
151
+ const seekAmount = (deltaX / window.innerWidth) * 30 // 30 seconds max
152
+ const newTime = Math.max(0, Math.min(duration, currentTime + seekAmount))
153
+ dispatch({
154
+ type: MediaActionTypes.SEEK,
155
+ detail: newTime
156
+ })
157
+ }
158
+
159
+ // Vertical swipe for volume (right side of screen)
160
+ if (Math.abs(deltaY) > Math.abs(deltaX) && Math.abs(deltaY) > 50 && touchStart.x > window.innerWidth / 2) {
161
+ const volumeChange = -(deltaY / window.innerHeight) * 1 // Full range
162
+ const newVolume = Math.max(0, Math.min(1, volume + volumeChange))
163
+ dispatch({
164
+ type: MediaActionTypes.SET_VOLUME,
165
+ detail: newVolume
166
+ })
167
+ }
168
+ }, [enabled, touchStart, isDoubleTap, duration, currentTime, volume, dispatch])
169
+
170
+ const handleTouchEnd = React.useCallback(() => {
171
+ if (!enabled) return
172
+ // Reset touch state after a delay to allow for double tap detection
173
+ setTimeout(() => {
174
+ setTouchStart(null)
175
+ setIsDoubleTap(false)
176
+ }, 300)
177
+ }, [enabled])
178
+
179
+ return {
180
+ handleTouchStart,
181
+ handleTouchMove,
182
+ handleTouchEnd
183
+ }
184
+ }
185
+
186
+ export const EnhancedMediaPlayer = function EnhancedMediaPlayer({
187
+ children,
188
+ className,
189
+ autoHide = true,
190
+ autoHideDelay = 3000,
191
+ showControlsOnHover = true,
192
+ showControlsOnTouch = true,
193
+ enableKeyboardControls = true,
194
+ enableTouchGestures = true,
195
+ onPlay,
196
+ onPause,
197
+ onTimeUpdate,
198
+ onVolumeChange,
199
+ onFullscreenChange
200
+ }: EnhancedMediaPlayerProps) {
201
+ const context = useMediaContext()
202
+ const dispatch = useMediaDispatch()
203
+
204
+ // State selectors with memoization
205
+ const isPlaying = useMediaSelector(React.useCallback(state => state.isPlaying, []))
206
+ const isFullscreen = useMediaSelector(React.useCallback(state => state.isFullscreen, []))
207
+ const currentTime = useMediaSelector(React.useCallback(state => state.currentTime, []))
208
+ const volume = useMediaSelector(React.useCallback(state => state.volume, []))
209
+ const error = useMediaSelector(React.useCallback(state => state.error, []))
210
+
211
+ // Custom hooks
212
+ const {
213
+ showControls,
214
+ showControlsTemporarily,
215
+ handleMouseEnter,
216
+ handleMouseLeave,
217
+ handleTouchStart: handleControlsTouch,
218
+ handleTouchEnd: handleControlsTouchEnd
219
+ } = useAutoHideControls(autoHide, autoHideDelay, showControlsOnHover, showControlsOnTouch)
220
+
221
+ const {
222
+ handleTouchStart: handleGestureStart,
223
+ handleTouchMove: handleGestureMove,
224
+ handleTouchEnd: handleGestureEnd
225
+ } = useTouchGestures(enableTouchGestures)
226
+
227
+ // Combine touch handlers
228
+ const handleTouchStart = React.useCallback((e: React.TouchEvent) => {
229
+ handleControlsTouch()
230
+ handleGestureStart(e)
231
+ }, [handleControlsTouch, handleGestureStart])
232
+
233
+ const handleTouchEnd = React.useCallback(() => {
234
+ handleControlsTouchEnd()
235
+ handleGestureEnd()
236
+ }, [handleControlsTouchEnd, handleGestureEnd])
237
+
238
+ // Event handlers with memoization
239
+ const handleClick = React.useCallback(() => {
240
+ showControlsTemporarily()
241
+ }, [showControlsTemporarily])
242
+
243
+ // Keyboard controls
244
+ React.useEffect(() => {
245
+ if (!enableKeyboardControls) return
246
+
247
+ const handleKeyDown = (e: KeyboardEvent) => {
248
+ if (e.target instanceof HTMLInputElement || e.target instanceof HTMLTextAreaElement) {
249
+ return
250
+ }
251
+
252
+ switch (e.code) {
253
+ case 'Space':
254
+ case 'KeyK':
255
+ e.preventDefault()
256
+ dispatch({
257
+ type: isPlaying ? MediaActionTypes.PAUSE : MediaActionTypes.PLAY
258
+ })
259
+ break
260
+ case 'KeyF':
261
+ e.preventDefault()
262
+ dispatch({
263
+ type: isFullscreen ? MediaActionTypes.EXIT_FULLSCREEN : MediaActionTypes.ENTER_FULLSCREEN
264
+ })
265
+ break
266
+ case 'KeyM':
267
+ e.preventDefault()
268
+ dispatch({ type: MediaActionTypes.TOGGLE_MUTE })
269
+ break
270
+ case 'ArrowLeft':
271
+ e.preventDefault()
272
+ dispatch({
273
+ type: MediaActionTypes.SEEK,
274
+ detail: Math.max(0, currentTime - 10)
275
+ })
276
+ break
277
+ case 'ArrowRight':
278
+ e.preventDefault()
279
+ dispatch({
280
+ type: MediaActionTypes.SEEK,
281
+ detail: currentTime + 10
282
+ })
283
+ break
284
+ case 'ArrowUp':
285
+ e.preventDefault()
286
+ dispatch({
287
+ type: MediaActionTypes.SET_VOLUME,
288
+ detail: Math.min(1, volume + 0.1)
289
+ })
290
+ break
291
+ case 'ArrowDown':
292
+ e.preventDefault()
293
+ dispatch({
294
+ type: MediaActionTypes.SET_VOLUME,
295
+ detail: Math.max(0, volume - 0.1)
296
+ })
297
+ break
298
+ }
299
+ }
300
+
301
+ document.addEventListener('keydown', handleKeyDown)
302
+ return () => document.removeEventListener('keydown', handleKeyDown)
303
+ }, [enableKeyboardControls, dispatch, isPlaying, isFullscreen, currentTime, volume])
304
+
305
+ // Event callbacks
306
+ React.useEffect(() => {
307
+ if (isPlaying) onPlay?.()
308
+ else onPause?.()
309
+ }, [isPlaying, onPlay, onPause])
310
+
311
+ React.useEffect(() => {
312
+ onTimeUpdate?.(currentTime)
313
+ }, [currentTime, onTimeUpdate])
314
+
315
+ React.useEffect(() => {
316
+ onVolumeChange?.(volume)
317
+ }, [volume, onVolumeChange])
318
+
319
+ React.useEffect(() => {
320
+ onFullscreenChange?.(isFullscreen)
321
+ }, [isFullscreen, onFullscreenChange])
322
+
323
+ return (
324
+ <div
325
+ ref={context.rootRef}
326
+ className={cn(
327
+ "relative isolate flex flex-col overflow-hidden rounded-lg bg-black outline-none",
328
+ "focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
329
+ "data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
330
+ isFullscreen && "fixed inset-0 z-50 rounded-none",
331
+ className
332
+ )}
333
+ data-state={isFullscreen ? "fullscreen" : "inline"}
334
+ data-disabled={error ? "" : undefined}
335
+ data-controls-visible={showControls ? "" : undefined}
336
+ tabIndex={0}
337
+ onMouseEnter={handleMouseEnter}
338
+ onMouseLeave={handleMouseLeave}
339
+ onTouchStart={handleTouchStart}
340
+ onTouchMove={handleGestureMove}
341
+ onTouchEnd={handleTouchEnd}
342
+ onClick={handleClick}
343
+ >
344
+ {children}
345
+ </div>
346
+ )
347
+ }
348
+
349
+ EnhancedMediaPlayer.displayName = "EnhancedMediaPlayer"
@@ -0,0 +1,55 @@
1
+ "use client"
2
+
3
+ import React from "react"
4
+ import { MediaPlayerRoot } from "../media-player-root"
5
+ import { MediaPlayerVideo } from "../media-player-video"
6
+ import { MediaPlayerControls, MediaPlayerControlsOverlay } from "../media-player-controls"
7
+ import { MediaPlayerPlay } from "../media-player-play"
8
+ import { MediaPlayerSeek } from "../media-player-seek"
9
+ import { MediaPlayerVolume } from "../media-player-volume"
10
+ import { MediaPlayerTime } from "../media-player-time"
11
+ import { MediaPlayerFullscreen } from "../media-player-fullscreen"
12
+ import { MediaPlayerLoading } from "../media-player-loading"
13
+ import { MediaPlayerError } from "../media-player-error"
14
+
15
+ export interface BasicVideoPlayerProps {
16
+ src: string
17
+ poster?: string
18
+ className?: string
19
+ }
20
+
21
+ export function BasicVideoPlayer({ src, poster, className }: BasicVideoPlayerProps) {
22
+ return (
23
+ <MediaPlayerRoot className={className}>
24
+ <MediaPlayerVideo
25
+ src={src}
26
+ poster={poster}
27
+ crossOrigin="anonymous"
28
+ playsInline
29
+ />
30
+
31
+ <MediaPlayerLoading />
32
+ <MediaPlayerError />
33
+
34
+ <MediaPlayerControlsOverlay />
35
+ <MediaPlayerControls>
36
+ <div className="flex items-center gap-2">
37
+ <MediaPlayerPlay />
38
+ <MediaPlayerVolume />
39
+ <MediaPlayerTime variant="current" />
40
+ </div>
41
+
42
+ <div className="flex-1 px-2">
43
+ <MediaPlayerSeek />
44
+ </div>
45
+
46
+ <div className="flex items-center gap-2">
47
+ <MediaPlayerTime variant="duration" />
48
+ <MediaPlayerFullscreen />
49
+ </div>
50
+ </MediaPlayerControls>
51
+ </MediaPlayerRoot>
52
+ )
53
+ }
54
+
55
+ BasicVideoPlayer.displayName = "BasicVideoPlayer"
@@ -0,0 +1,63 @@
1
+ "use client"
2
+
3
+ import { MediaPlayer } from "../media-player"
4
+ import { FullscreenButton } from "../ui/fullscreen-button"
5
+ import { PlayButton } from "../ui/play-button"
6
+ import { SeekBar } from "../ui/seek-bar"
7
+ import { TimeDisplay } from "../ui/time-display"
8
+ import { VolumeControl } from "../ui/volume-control"
9
+
10
+ export interface CustomControlsExampleProps {
11
+ src: string
12
+ poster?: string
13
+ className?: string
14
+ }
15
+
16
+ export function CustomControlsExample({ src, poster, className }: CustomControlsExampleProps) {
17
+ return (
18
+ <MediaPlayer src={src} customControls={true} showControls={false} className={className}>
19
+ {({ state, controls }) => (
20
+ <div className="absolute inset-0 flex flex-col justify-end">
21
+ {/* Background gradient */}
22
+ <div className="pointer-events-none absolute inset-0 bg-gradient-to-t from-black/80 via-transparent to-transparent" />
23
+
24
+ {/* Controls container */}
25
+ <div className="relative z-10 space-y-3 p-4">
26
+ {/* Seek bar */}
27
+ <div className="w-full">
28
+ <SeekBar
29
+ currentTime={state.currentTime}
30
+ duration={state.duration}
31
+ onSeek={controls.seek}
32
+ className="w-full"
33
+ />
34
+ </div>
35
+
36
+ {/* Bottom controls */}
37
+ <div className="flex items-center justify-between">
38
+ <div className="flex items-center gap-3">
39
+ <PlayButton isPlaying={state.isPlaying} onToggle={controls.toggle} size="lg" />
40
+ <VolumeControl
41
+ volume={state.volume}
42
+ isMuted={state.isMuted}
43
+ onVolumeChange={controls.setVolume}
44
+ onToggleMute={controls.toggleMute}
45
+ />
46
+ <TimeDisplay currentTime={state.currentTime} duration={state.duration} />
47
+ </div>
48
+
49
+ <div className="flex items-center gap-2">
50
+ <FullscreenButton
51
+ isFullscreen={state.isFullscreen}
52
+ onToggle={controls.toggleFullscreen}
53
+ />
54
+ </div>
55
+ </div>
56
+ </div>
57
+ </div>
58
+ )}
59
+ </MediaPlayer>
60
+ )
61
+ }
62
+
63
+ CustomControlsExample.displayName = "CustomControlsExample"
@@ -0,0 +1,114 @@
1
+ "use client"
2
+
3
+ import React from "react"
4
+ import { MediaProvider } from "../../context/media-provider"
5
+ import { MediaPlayerRoot } from "../media-player-root"
6
+ import { MediaPlayerVideo } from "../media-player-video"
7
+ import {
8
+ EnhancedControlBar,
9
+ EnhancedPlayButton,
10
+ EnhancedSeekBar,
11
+ EnhancedBackwardButton,
12
+ EnhancedForwardButton,
13
+ EnhancedVolumeControl,
14
+ EnhancedTimeDisplay
15
+ } from "../enhanced/enhanced-controls"
16
+
17
+ export interface EnhancedControlsExampleProps {
18
+ src: string
19
+ poster?: string
20
+ className?: string
21
+ }
22
+
23
+ // Complete example with all enhanced controls
24
+ export function EnhancedControlsExample({
25
+ src,
26
+ poster,
27
+ className
28
+ }: EnhancedControlsExampleProps) {
29
+ return (
30
+ <MediaProvider>
31
+ <MediaPlayerRoot className={className}>
32
+ <MediaPlayerVideo src={src} poster={poster} />
33
+
34
+ {/* Complete control bar with all features */}
35
+ <EnhancedControlBar
36
+ className="absolute right-0 bottom-0 left-0"
37
+ showSkipButtons={true}
38
+ showVolumeControl={true}
39
+ showTimeDisplay={true}
40
+ playButtonSize="xl"
41
+ skipButtonSize="md"
42
+ skipTime={10}
43
+ />
44
+ </MediaPlayerRoot>
45
+ </MediaProvider>
46
+ )
47
+ }
48
+
49
+ // Example with individual components for custom layouts
50
+ export function CustomEnhancedControlsExample({
51
+ src,
52
+ poster,
53
+ className
54
+ }: EnhancedControlsExampleProps) {
55
+ return (
56
+ <MediaProvider>
57
+ <MediaPlayerRoot className={className}>
58
+ <MediaPlayerVideo src={src} poster={poster} />
59
+
60
+ <div className="absolute right-0 bottom-0 left-0 bg-gradient-to-t from-black/80 to-transparent p-4">
61
+ {/* Seek bar */}
62
+ <EnhancedSeekBar className="mb-4" />
63
+
64
+ {/* Custom control layout */}
65
+ <div className="flex items-center justify-between">
66
+ {/* Left side controls */}
67
+ <div className="flex items-center gap-3">
68
+ <EnhancedBackwardButton skipTime={15} size="md" />
69
+ <EnhancedPlayButton size="xl" />
70
+ <EnhancedForwardButton skipTime={15} size="md" />
71
+ <EnhancedVolumeControl />
72
+ </div>
73
+
74
+ {/* Right side info */}
75
+ <div className="flex items-center gap-2 font-mono text-sm text-white">
76
+ <EnhancedTimeDisplay variant="current" />
77
+ <span className="text-white/60">/</span>
78
+ <EnhancedTimeDisplay variant="duration" />
79
+ </div>
80
+ </div>
81
+ </div>
82
+ </MediaPlayerRoot>
83
+ </MediaProvider>
84
+ )
85
+ }
86
+
87
+ // Minimal example with just skip buttons
88
+ export function SkipButtonsOnlyExample({
89
+ src,
90
+ poster,
91
+ className
92
+ }: EnhancedControlsExampleProps) {
93
+ return (
94
+ <MediaProvider>
95
+ <MediaPlayerRoot className={className}>
96
+ <MediaPlayerVideo src={src} poster={poster} />
97
+
98
+ <div className="-translate-x-1/2 absolute bottom-4 left-1/2 transform">
99
+ <div className="flex items-center gap-4">
100
+ <EnhancedBackwardButton
101
+ skipTime={10}
102
+ size="lg"
103
+ />
104
+ <EnhancedPlayButton size="xl" />
105
+ <EnhancedForwardButton
106
+ skipTime={10}
107
+ size="lg"
108
+ />
109
+ </div>
110
+ </div>
111
+ </MediaPlayerRoot>
112
+ </MediaProvider>
113
+ )
114
+ }