@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,442 @@
1
+ // Event system types
2
+ export interface MediaPlayerEvent {
3
+ type: string
4
+ timestamp: number
5
+ target?: string
6
+ detail?: any
7
+ bubbles?: boolean
8
+ cancelable?: boolean
9
+ defaultPrevented?: boolean
10
+ }
11
+
12
+ export type EventHandler<T = any> = (event: MediaPlayerEvent & { detail: T }) => void
13
+ export type EventUnsubscriber = () => void
14
+
15
+ export interface EventOptions {
16
+ once?: boolean
17
+ passive?: boolean
18
+ priority?: 'high' | 'normal' | 'low'
19
+ filter?: (event: MediaPlayerEvent) => boolean
20
+ }
21
+
22
+ // Event categories for organization
23
+ export type EventCategory =
24
+ | 'media' // Media playback events
25
+ | 'user' // User interaction events
26
+ | 'system' // System/internal events
27
+ | 'plugin' // Plugin events
28
+ | 'error' // Error events
29
+ | 'performance' // Performance events
30
+
31
+ // Standard media events
32
+ export interface MediaEvents {
33
+ // Playback events
34
+ 'media:loadstart': { src: string }
35
+ 'media:loadeddata': { duration: number }
36
+ 'media:canplay': {}
37
+ 'media:canplaythrough': {}
38
+ 'media:play': { currentTime: number }
39
+ 'media:pause': { currentTime: number }
40
+ 'media:ended': { duration: number }
41
+ 'media:seeking': { currentTime: number, targetTime: number }
42
+ 'media:seeked': { currentTime: number, previousTime: number }
43
+ 'media:timeupdate': { currentTime: number, duration: number }
44
+ 'media:durationchange': { duration: number }
45
+ 'media:volumechange': { volume: number, muted: boolean }
46
+ 'media:ratechange': { playbackRate: number }
47
+
48
+ // Loading events
49
+ 'media:loadedmetadata': { src: string }
50
+ 'media:progress': { buffered: TimeRanges }
51
+ 'media:suspend': {}
52
+ 'media:abort': {}
53
+ 'media:error': { error: Error }
54
+ 'media:stalled': {}
55
+ 'media:waiting': {}
56
+
57
+ // User interaction events
58
+ 'user:click': { x: number, y: number, element: string }
59
+ 'user:hover': { element: string }
60
+ 'user:focus': { element: string }
61
+ 'user:keyboard': { key: string, code: string, altKey: boolean, ctrlKey: boolean, shiftKey: boolean }
62
+ 'user:gesture': { type: string, data: any }
63
+
64
+ // System events
65
+ 'system:ready': {}
66
+ 'system:resize': { width: number, height: number }
67
+ 'system:fullscreen': { isFullscreen: boolean }
68
+ 'system:pip': { isPictureInPicture: boolean }
69
+ 'system:visibility': { isVisible: boolean }
70
+
71
+ // Plugin events
72
+ 'plugin:loaded': { name: string }
73
+ 'plugin:enabled': { name: string }
74
+ 'plugin:disabled': { name: string }
75
+ 'plugin:error': { name: string, error: Error }
76
+
77
+ // Performance events
78
+ 'performance:fps': { fps: number }
79
+ 'performance:memory': { used: number, total: number }
80
+ 'performance:load': { loadTime: number }
81
+ }
82
+
83
+ // Event bus implementation
84
+ export class EventBus {
85
+ private listeners = new Map<string, Array<{
86
+ handler: EventHandler
87
+ options: EventOptions
88
+ id: string
89
+ }>>()
90
+
91
+ private eventQueue: MediaPlayerEvent[] = []
92
+ private isProcessing = false
93
+ private middlewares: Array<(event: MediaPlayerEvent) => MediaPlayerEvent | null> = []
94
+ private eventHistory: MediaPlayerEvent[] = []
95
+ private maxHistorySize = 1000
96
+
97
+ // Subscribe to events
98
+ on<K extends keyof MediaEvents>(
99
+ type: K,
100
+ handler: EventHandler<MediaEvents[K]>,
101
+ options: EventOptions = {}
102
+ ): EventUnsubscriber {
103
+ return this.addEventListener(type, handler as EventHandler, options)
104
+ }
105
+
106
+ // Subscribe to events (one-time)
107
+ once<K extends keyof MediaEvents>(
108
+ type: K,
109
+ handler: EventHandler<MediaEvents[K]>,
110
+ options: EventOptions = {}
111
+ ): EventUnsubscriber {
112
+ return this.addEventListener(type, handler as EventHandler, { ...options, once: true })
113
+ }
114
+
115
+ // Subscribe to events with wildcard support
116
+ addEventListener(
117
+ type: string,
118
+ handler: EventHandler,
119
+ options: EventOptions = {}
120
+ ): EventUnsubscriber {
121
+ const id = this.generateId()
122
+ const listener = { handler, options, id }
123
+
124
+ if (!this.listeners.has(type)) {
125
+ this.listeners.set(type, [])
126
+ }
127
+
128
+ const listeners = this.listeners.get(type)!
129
+
130
+ // Insert based on priority
131
+ const priority = options.priority || 'normal'
132
+ const priorityValue = { high: 2, normal: 1, low: 0 }[priority]
133
+
134
+ let insertIndex = listeners.length
135
+ for (let i = 0; i < listeners.length; i++) {
136
+ const listener = listeners[i]
137
+ if (!listener) continue
138
+ const listenerPriority = listener.options.priority || 'normal'
139
+ if (priorityValue > { high: 2, normal: 1, low: 0 }[listenerPriority]) {
140
+ insertIndex = i
141
+ break
142
+ }
143
+ }
144
+
145
+ listeners.splice(insertIndex, 0, listener)
146
+
147
+ // Return unsubscriber
148
+ return () => {
149
+ const index = listeners.findIndex(l => l.id === id)
150
+ if (index !== -1) {
151
+ listeners.splice(index, 1)
152
+ }
153
+ if (listeners.length === 0) {
154
+ this.listeners.delete(type)
155
+ }
156
+ }
157
+ }
158
+
159
+ // Remove event listener
160
+ removeEventListener(type: string, handler?: EventHandler): void {
161
+ const listeners = this.listeners.get(type)
162
+ if (!listeners) return
163
+
164
+ if (handler) {
165
+ const index = listeners.findIndex(l => l.handler === handler)
166
+ if (index !== -1) {
167
+ listeners.splice(index, 1)
168
+ }
169
+ } else {
170
+ this.listeners.delete(type)
171
+ }
172
+
173
+ if (listeners && listeners.length === 0) {
174
+ this.listeners.delete(type)
175
+ }
176
+ }
177
+
178
+ // Emit events
179
+ emit<K extends keyof MediaEvents>(
180
+ type: K,
181
+ detail?: MediaEvents[K],
182
+ options?: Partial<MediaPlayerEvent>
183
+ ): boolean {
184
+ const event: MediaPlayerEvent = {
185
+ type,
186
+ timestamp: Date.now(),
187
+ detail,
188
+ bubbles: true,
189
+ cancelable: true,
190
+ defaultPrevented: false,
191
+ ...options
192
+ }
193
+
194
+ return this.dispatchEvent(event)
195
+ }
196
+
197
+ // Dispatch event
198
+ dispatchEvent(event: MediaPlayerEvent): boolean {
199
+ // Apply middlewares
200
+ let processedEvent: MediaPlayerEvent | null = event
201
+ for (const middleware of this.middlewares) {
202
+ processedEvent = middleware(processedEvent)
203
+ if (!processedEvent) {
204
+ return false // Event was cancelled by middleware
205
+ }
206
+ }
207
+
208
+ // Add to history
209
+ this.addToHistory(processedEvent)
210
+
211
+ // Queue event for processing
212
+ this.eventQueue.push(processedEvent)
213
+
214
+ if (!this.isProcessing) {
215
+ this.processEventQueue()
216
+ }
217
+
218
+ return !processedEvent.defaultPrevented
219
+ }
220
+
221
+ // Process event queue with React 19 concurrent scheduling
222
+ private processEventQueue(): void {
223
+ if (this.isProcessing) return
224
+
225
+ this.isProcessing = true
226
+
227
+ // Use scheduler for non-blocking event processing
228
+ const schedule = (typeof window !== 'undefined' && 'scheduler' in window)
229
+ ? (window as any).scheduler.postTask
230
+ : (cb: () => void) => setTimeout(cb, 0)
231
+
232
+ const processNext = () => {
233
+ if (this.eventQueue.length === 0) {
234
+ this.isProcessing = false
235
+ return
236
+ }
237
+
238
+ const batchSize = Math.min(this.eventQueue.length, 5) // Process max 5 events per frame
239
+ const events = this.eventQueue.splice(0, batchSize)
240
+
241
+ // Process events in parallel using Promise.all
242
+ Promise.all(events.map(event => this.processEvent(event).catch(console.error)))
243
+ .then(() => {
244
+ // Schedule next batch in next frame
245
+ schedule(processNext)
246
+ })
247
+ .catch(() => {
248
+ this.isProcessing = false
249
+ })
250
+ }
251
+
252
+ schedule(processNext)
253
+ }
254
+
255
+ // Process individual event
256
+ private async processEvent(event: MediaPlayerEvent): Promise<void> {
257
+ const { type } = event
258
+
259
+ // Get exact matches
260
+ const exactListeners = this.listeners.get(type) || []
261
+
262
+ // Get wildcard matches
263
+ const wildcardListeners: typeof exactListeners = []
264
+ for (const [pattern, listeners] of this.listeners.entries()) {
265
+ if (pattern.includes('*') && this.matchPattern(type, pattern)) {
266
+ wildcardListeners.push(...listeners)
267
+ }
268
+ }
269
+
270
+ // Combine and sort by priority
271
+ const allListeners = [...exactListeners, ...wildcardListeners]
272
+ .sort((a, b) => {
273
+ const priorityA = { high: 2, normal: 1, low: 0 }[a.options.priority || 'normal']
274
+ const priorityB = { high: 2, normal: 1, low: 0 }[b.options.priority || 'normal']
275
+ return priorityB - priorityA
276
+ })
277
+
278
+ // Execute listeners
279
+ const listenersToRemove: string[] = []
280
+
281
+ for (const listener of allListeners) {
282
+ // Apply filter if present
283
+ if (listener.options.filter && !listener.options.filter(event)) {
284
+ continue
285
+ }
286
+
287
+ try {
288
+ // Execute handler
289
+ await Promise.resolve(listener.handler(event as any))
290
+
291
+ // Mark for removal if once
292
+ if (listener.options.once) {
293
+ listenersToRemove.push(listener.id)
294
+ }
295
+
296
+ // Stop propagation if event was cancelled
297
+ if (event.defaultPrevented && !event.bubbles) {
298
+ break
299
+ }
300
+ } catch (error) {
301
+ console.error(`Error in event handler for ${type}:`, error)
302
+
303
+ // Log error instead
304
+ console.error(`Event handler error for ${type}:`, error)
305
+ }
306
+ }
307
+
308
+ // Remove one-time listeners
309
+ for (const id of listenersToRemove) {
310
+ for (const [eventType, listeners] of this.listeners.entries()) {
311
+ const index = listeners.findIndex(l => l.id === id)
312
+ if (index !== -1) {
313
+ listeners.splice(index, 1)
314
+ if (listeners.length === 0) {
315
+ this.listeners.delete(eventType)
316
+ }
317
+ break
318
+ }
319
+ }
320
+ }
321
+ }
322
+
323
+ // Add middleware
324
+ use(middleware: (event: MediaPlayerEvent) => MediaPlayerEvent | null): () => void {
325
+ this.middlewares.push(middleware)
326
+ return () => {
327
+ const index = this.middlewares.indexOf(middleware)
328
+ if (index !== -1) {
329
+ this.middlewares.splice(index, 1)
330
+ }
331
+ }
332
+ }
333
+
334
+ // Event history management
335
+ private addToHistory(event: MediaPlayerEvent): void {
336
+ this.eventHistory.push(event)
337
+ if (this.eventHistory.length > this.maxHistorySize) {
338
+ this.eventHistory.shift()
339
+ }
340
+ }
341
+
342
+ // Get event history
343
+ getHistory(filter?: (event: MediaPlayerEvent) => boolean): MediaPlayerEvent[] {
344
+ return filter ? this.eventHistory.filter(filter) : [...this.eventHistory]
345
+ }
346
+
347
+ // Clear event history
348
+ clearHistory(): void {
349
+ this.eventHistory = []
350
+ }
351
+
352
+ // Pattern matching for wildcards
353
+ private matchPattern(eventType: string, pattern: string): boolean {
354
+ const regex = new RegExp(
355
+ '^' + pattern.replace(/\*/g, '.*').replace(/\?/g, '.') + '$'
356
+ )
357
+ return regex.test(eventType)
358
+ }
359
+
360
+ // Generate unique ID
361
+ private generateId(): string {
362
+ return `event_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`
363
+ }
364
+
365
+ // Get listener count
366
+ getListenerCount(type?: string): number {
367
+ if (type) {
368
+ return this.listeners.get(type)?.length || 0
369
+ }
370
+ return Array.from(this.listeners.values()).reduce((sum, listeners) => sum + listeners.length, 0)
371
+ }
372
+
373
+ // Get all event types
374
+ getEventTypes(): string[] {
375
+ return Array.from(this.listeners.keys())
376
+ }
377
+
378
+ // Clear all listeners
379
+ removeAllListeners(type?: string): void {
380
+ if (type) {
381
+ this.listeners.delete(type)
382
+ } else {
383
+ this.listeners.clear()
384
+ }
385
+ }
386
+
387
+ // Destroy event bus
388
+ destroy(): void {
389
+ this.listeners.clear()
390
+ this.eventQueue = []
391
+ this.middlewares = []
392
+ this.eventHistory = []
393
+ this.isProcessing = false
394
+ }
395
+ }
396
+
397
+ // Default event bus instance
398
+ export const defaultEventBus = new EventBus()
399
+
400
+ // Event delegation helper
401
+ export class EventDelegator {
402
+ private eventBus: EventBus
403
+ private element: HTMLElement
404
+ private delegatedEvents = new Set<string>()
405
+
406
+ constructor(eventBus: EventBus, element: HTMLElement) {
407
+ this.eventBus = eventBus
408
+ this.element = element
409
+ }
410
+
411
+ // Delegate DOM events to event bus
412
+ delegate(domEvent: string, mediaEvent?: string): void {
413
+ if (this.delegatedEvents.has(domEvent)) return
414
+
415
+ const handler = (e: Event) => {
416
+ this.eventBus.emit(mediaEvent || `dom:${domEvent}` as any, {
417
+ originalEvent: e,
418
+ target: (e.target as HTMLElement)?.tagName.toLowerCase(),
419
+ currentTarget: (e.currentTarget as HTMLElement)?.tagName.toLowerCase()
420
+ })
421
+ }
422
+
423
+ this.element.addEventListener(domEvent, handler, { passive: true })
424
+ this.delegatedEvents.add(domEvent)
425
+ }
426
+
427
+ // Setup common delegations
428
+ setupCommonDelegations(): void {
429
+ this.delegate('click', 'user:click')
430
+ this.delegate('mouseenter', 'user:hover')
431
+ this.delegate('mouseleave', 'user:hover')
432
+ this.delegate('focus', 'user:focus')
433
+ this.delegate('blur', 'user:focus')
434
+ this.delegate('keydown', 'user:keyboard')
435
+ this.delegate('keyup', 'user:keyboard')
436
+ }
437
+
438
+ destroy(): void {
439
+ this.delegatedEvents.clear()
440
+ }
441
+ }
442
+