@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,476 @@
1
+ import React, { useState, useEffect, useRef, useCallback } from 'react';
2
+ // Import type safely with fallback
3
+ type ReportHandler = (metric: { name: string; value: number }) => void;
4
+
5
+ // Performance metrics types
6
+ export interface PerformanceMetrics {
7
+ // Core Web Vitals
8
+ lcp?: number; // Largest Contentful Paint
9
+ fid?: number; // First Input Delay
10
+ cls?: number; // Cumulative Layout Shift
11
+ fcp?: number; // First Contentful Paint
12
+ ttfb?: number; // Time to First Byte
13
+ inp?: number; // Interaction to Next Paint
14
+
15
+ // Custom metrics
16
+ componentRenderTime: number;
17
+ bundleLoadTime: number;
18
+ mediaLoadTime: number;
19
+ memoryUsage: number;
20
+
21
+ // Performance scores
22
+ performanceScore: number;
23
+ timestamp: number;
24
+ }
25
+
26
+ export interface PerformanceThresholds {
27
+ lcp: { good: number; poor: number };
28
+ fid: { good: number; poor: number };
29
+ cls: { good: number; poor: number };
30
+ renderTime: { good: number; poor: number };
31
+ memoryUsage: { good: number; poor: number };
32
+ }
33
+
34
+ export const defaultThresholds: PerformanceThresholds = {
35
+ lcp: { good: 2500, poor: 4000 },
36
+ fid: { good: 100, poor: 300 },
37
+ cls: { good: 0.1, poor: 0.25 },
38
+ renderTime: { good: 16, poor: 100 }, // Target 60fps = 16.67ms per frame
39
+ memoryUsage: { good: 50 * 1024 * 1024, poor: 100 * 1024 * 1024 } // 50MB good, 100MB poor
40
+ };
41
+
42
+ // Performance monitoring class
43
+ export class PerformanceMonitor {
44
+ private metrics: PerformanceMetrics[] = [];
45
+ private listeners: Set<(metrics: PerformanceMetrics) => void> = new Set();
46
+ private thresholds: PerformanceThresholds;
47
+ private observer?: PerformanceObserver;
48
+ private isMonitoring = false;
49
+
50
+ constructor(thresholds: PerformanceThresholds = defaultThresholds) {
51
+ this.thresholds = thresholds;
52
+ this.initializeWebVitals();
53
+ this.initializePerformanceObserver();
54
+ }
55
+
56
+ private async initializeWebVitals() {
57
+ if (typeof window === 'undefined') return;
58
+
59
+ try {
60
+ // Try to import web-vitals dynamically and handle different versions
61
+ const webVitals = await import('web-vitals').catch(() => null);
62
+
63
+ if (!webVitals) {
64
+ console.warn('web-vitals package not available, Core Web Vitals tracking disabled');
65
+ return;
66
+ }
67
+
68
+ const reportHandler: ReportHandler = (metric) => {
69
+ this.updateMetric(metric.name.toLowerCase() as keyof PerformanceMetrics, metric.value);
70
+ };
71
+
72
+ // Handle different web-vitals versions safely
73
+ const vitalsAny = webVitals as any;
74
+ if (vitalsAny.getCLS) vitalsAny.getCLS(reportHandler);
75
+ if (vitalsAny.getFID) vitalsAny.getFID(reportHandler);
76
+ if (vitalsAny.getFCP) vitalsAny.getFCP(reportHandler);
77
+ if (vitalsAny.getLCP) vitalsAny.getLCP(reportHandler);
78
+ if (vitalsAny.getTTFB) vitalsAny.getTTFB(reportHandler);
79
+ if (vitalsAny.onINP) vitalsAny.onINP(reportHandler);
80
+ } catch (error) {
81
+ console.warn('Web Vitals initialization failed:', error);
82
+ }
83
+ }
84
+
85
+ private initializePerformanceObserver() {
86
+ if (typeof window === 'undefined' || !('PerformanceObserver' in window)) return;
87
+
88
+ try {
89
+ this.observer = new PerformanceObserver((list) => {
90
+ for (const entry of list.getEntries()) {
91
+ this.handlePerformanceEntry(entry);
92
+ }
93
+ });
94
+
95
+ this.observer.observe({ entryTypes: ['measure', 'navigation', 'resource', 'paint'] });
96
+ } catch (error) {
97
+ console.warn('PerformanceObserver not supported:', error);
98
+ }
99
+ }
100
+
101
+ private handlePerformanceEntry(entry: PerformanceEntry) {
102
+ switch (entry.entryType) {
103
+ case 'measure':
104
+ if (entry.name.startsWith('baroiplayer-render')) {
105
+ this.updateMetric('componentRenderTime', entry.duration);
106
+ }
107
+ break;
108
+
109
+ case 'resource':
110
+ if (entry.name.includes('.js') || entry.name.includes('.css')) {
111
+ this.updateMetric('bundleLoadTime', entry.duration);
112
+ }
113
+ break;
114
+
115
+ case 'paint':
116
+ if (entry.name === 'first-contentful-paint') {
117
+ this.updateMetric('fcp', entry.startTime);
118
+ }
119
+ break;
120
+ }
121
+ }
122
+
123
+ private updateMetric(key: keyof PerformanceMetrics, value: number) {
124
+ const currentMetrics = this.getCurrentMetrics();
125
+ const updatedMetrics = {
126
+ ...currentMetrics,
127
+ [key]: value,
128
+ timestamp: Date.now(),
129
+ performanceScore: this.calculatePerformanceScore({ ...currentMetrics, [key]: value })
130
+ };
131
+
132
+ this.metrics.push(updatedMetrics);
133
+
134
+ // Keep only last 100 metrics
135
+ if (this.metrics.length > 100) {
136
+ this.metrics = this.metrics.slice(-100);
137
+ }
138
+
139
+ this.listeners.forEach(listener => listener(updatedMetrics));
140
+ }
141
+
142
+ private getCurrentMetrics(): PerformanceMetrics {
143
+ const latest = this.metrics[this.metrics.length - 1];
144
+ return latest || {
145
+ componentRenderTime: 0,
146
+ bundleLoadTime: 0,
147
+ mediaLoadTime: 0,
148
+ memoryUsage: this.getMemoryUsage(),
149
+ performanceScore: 0,
150
+ timestamp: Date.now()
151
+ };
152
+ }
153
+
154
+ private getMemoryUsage(): number {
155
+ if ('memory' in performance) {
156
+ return (performance as any).memory.usedJSHeapSize || 0;
157
+ }
158
+ return 0;
159
+ }
160
+
161
+ private calculatePerformanceScore(metrics: PerformanceMetrics): number {
162
+ let score = 100;
163
+
164
+ // Penalize based on thresholds
165
+ if (metrics.lcp && metrics.lcp > this.thresholds.lcp.good) {
166
+ score -= metrics.lcp > this.thresholds.lcp.poor ? 30 : 15;
167
+ }
168
+
169
+ if (metrics.fid && metrics.fid > this.thresholds.fid.good) {
170
+ score -= metrics.fid > this.thresholds.fid.poor ? 25 : 10;
171
+ }
172
+
173
+ if (metrics.cls && metrics.cls > this.thresholds.cls.good) {
174
+ score -= metrics.cls > this.thresholds.cls.poor ? 20 : 10;
175
+ }
176
+
177
+ if (metrics.componentRenderTime > this.thresholds.renderTime.good) {
178
+ score -= metrics.componentRenderTime > this.thresholds.renderTime.poor ? 20 : 10;
179
+ }
180
+
181
+ if (metrics.memoryUsage > this.thresholds.memoryUsage.good) {
182
+ score -= metrics.memoryUsage > this.thresholds.memoryUsage.poor ? 15 : 5;
183
+ }
184
+
185
+ return Math.max(0, score);
186
+ }
187
+
188
+ // Public API
189
+ public startMonitoring() {
190
+ this.isMonitoring = true;
191
+ this.startMemoryMonitoring();
192
+ }
193
+
194
+ public stopMonitoring() {
195
+ this.isMonitoring = false;
196
+ if (this.observer) {
197
+ this.observer.disconnect();
198
+ }
199
+ }
200
+
201
+ private startMemoryMonitoring() {
202
+ if (!this.isMonitoring) return;
203
+
204
+ this.updateMetric('memoryUsage', this.getMemoryUsage());
205
+ setTimeout(() => this.startMemoryMonitoring(), 5000); // Check every 5 seconds
206
+ }
207
+
208
+ public measureComponentRender(componentName: string, renderFn: () => any): any {
209
+ const startMark = `baroiplayer-render-${componentName}-start`;
210
+ const endMark = `baroiplayer-render-${componentName}-end`;
211
+ const measureName = `baroiplayer-render-${componentName}`;
212
+
213
+ performance.mark(startMark);
214
+ const result = renderFn();
215
+ performance.mark(endMark);
216
+
217
+ try {
218
+ performance.measure(measureName, startMark, endMark);
219
+ } catch (error) {
220
+ console.warn('Performance measurement failed:', error);
221
+ }
222
+
223
+ return result;
224
+ }
225
+
226
+ public subscribe(listener: (metrics: PerformanceMetrics) => void): () => void {
227
+ this.listeners.add(listener);
228
+ return () => this.listeners.delete(listener);
229
+ }
230
+
231
+ public getLatestMetrics(): PerformanceMetrics | null {
232
+ return this.metrics[this.metrics.length - 1] || null;
233
+ }
234
+
235
+ public getAllMetrics(): PerformanceMetrics[] {
236
+ return [...this.metrics];
237
+ }
238
+
239
+ public getAverageMetrics(count = 10): Partial<PerformanceMetrics> {
240
+ const recentMetrics = this.metrics.slice(-count);
241
+ if (recentMetrics.length === 0) return {};
242
+
243
+ const averages: Partial<PerformanceMetrics> = {};
244
+ const keys: Array<keyof PerformanceMetrics> = [
245
+ 'lcp', 'fid', 'cls', 'fcp', 'ttfb', 'inp',
246
+ 'componentRenderTime', 'bundleLoadTime', 'mediaLoadTime',
247
+ 'memoryUsage', 'performanceScore'
248
+ ];
249
+
250
+ keys.forEach(key => {
251
+ const values = recentMetrics
252
+ .map(m => m[key] as number)
253
+ .filter(v => typeof v === 'number' && !isNaN(v));
254
+
255
+ if (values.length > 0) {
256
+ (averages as any)[key] = values.reduce((sum, v) => sum + v, 0) / values.length;
257
+ }
258
+ });
259
+
260
+ return averages;
261
+ }
262
+
263
+ public getThresholds(): PerformanceThresholds {
264
+ return this.thresholds;
265
+ }
266
+
267
+ public updateThresholds(newThresholds: Partial<PerformanceThresholds>) {
268
+ this.thresholds = { ...this.thresholds, ...newThresholds };
269
+ }
270
+ }
271
+
272
+ // Global performance monitor instance
273
+ export const performanceMonitor = new PerformanceMonitor();
274
+
275
+ // React hook for performance monitoring
276
+ export function usePerformanceMonitor() {
277
+ const [metrics, setMetrics] = useState<PerformanceMetrics | null>(null);
278
+ const [isSupported, setIsSupported] = useState(true);
279
+
280
+ useEffect(() => {
281
+ setIsSupported(typeof window !== 'undefined' && 'performance' in window);
282
+
283
+ if (!isSupported) return;
284
+
285
+ performanceMonitor.startMonitoring();
286
+ const unsubscribe = performanceMonitor.subscribe(setMetrics);
287
+
288
+ return () => {
289
+ unsubscribe();
290
+ performanceMonitor.stopMonitoring();
291
+ };
292
+ }, [isSupported]);
293
+
294
+ const measureRender = useCallback(
295
+ (componentName: string, renderFn: () => any): any => {
296
+ return performanceMonitor.measureComponentRender(componentName, renderFn);
297
+ },
298
+ []
299
+ );
300
+
301
+ return {
302
+ metrics,
303
+ isSupported,
304
+ measureRender,
305
+ averageMetrics: performanceMonitor.getAverageMetrics(),
306
+ allMetrics: performanceMonitor.getAllMetrics(),
307
+ thresholds: performanceMonitor.getThresholds()
308
+ };
309
+ }
310
+
311
+ // HOC for performance monitoring
312
+ export function withPerformanceMonitoring(
313
+ WrappedComponent: React.ComponentType<any>,
314
+ componentName?: string
315
+ ) {
316
+ const displayName = componentName || WrappedComponent.displayName || WrappedComponent.name || 'Component';
317
+
318
+ function PerformanceMonitoredComponent(props: any) {
319
+ const renderRef = useRef(0);
320
+ const { measureRender } = usePerformanceMonitor();
321
+
322
+ return measureRender(`${displayName}-${renderRef.current++}`, () => (
323
+ <WrappedComponent {...props} />
324
+ ));
325
+ }
326
+
327
+ PerformanceMonitoredComponent.displayName = `withPerformanceMonitoring(${displayName})`;
328
+ return PerformanceMonitoredComponent;
329
+ }
330
+
331
+ // Performance regression detector
332
+ export class PerformanceRegressionDetector {
333
+ private baselineMetrics: PerformanceMetrics | null = null;
334
+ private regressionThreshold = 0.2; // 20% degradation threshold
335
+
336
+ setBaseline(metrics: PerformanceMetrics) {
337
+ this.baselineMetrics = metrics;
338
+ }
339
+
340
+ detectRegression(currentMetrics: PerformanceMetrics): Array<{
341
+ metric: keyof PerformanceMetrics;
342
+ baseline: number;
343
+ current: number;
344
+ degradation: number;
345
+ }> {
346
+ if (!this.baselineMetrics) return [];
347
+
348
+ const regressions: Array<{
349
+ metric: keyof PerformanceMetrics;
350
+ baseline: number;
351
+ current: number;
352
+ degradation: number;
353
+ }> = [];
354
+
355
+ const metricsToCheck: Array<keyof PerformanceMetrics> = [
356
+ 'componentRenderTime', 'bundleLoadTime', 'mediaLoadTime', 'memoryUsage'
357
+ ];
358
+
359
+ metricsToCheck.forEach(metric => {
360
+ const baseline = this.baselineMetrics![metric] as number;
361
+ const current = currentMetrics[metric] as number;
362
+
363
+ if (baseline && current && baseline > 0) {
364
+ const degradation = (current - baseline) / baseline;
365
+ if (degradation > this.regressionThreshold) {
366
+ regressions.push({ metric, baseline, current, degradation });
367
+ }
368
+ }
369
+ });
370
+
371
+ return regressions;
372
+ }
373
+
374
+ setRegressionThreshold(threshold: number) {
375
+ this.regressionThreshold = Math.max(0, Math.min(1, threshold));
376
+ }
377
+ }
378
+
379
+ // Development dashboard component
380
+ export interface PerformanceDashboardProps {
381
+ className?: string;
382
+ showAdvanced?: boolean;
383
+ }
384
+
385
+ export function PerformanceDashboard({
386
+ className = '',
387
+ showAdvanced = false
388
+ }: PerformanceDashboardProps) {
389
+ const { metrics, averageMetrics, thresholds, isSupported } = usePerformanceMonitor();
390
+
391
+ if (!isSupported || !metrics) {
392
+ return (
393
+ <div className={`performance-dashboard ${className}`}>
394
+ <p>Performance monitoring not supported in this environment</p>
395
+ </div>
396
+ );
397
+ }
398
+
399
+ const getScoreColor = (score: number) => {
400
+ if (score >= 90) return 'text-green-600';
401
+ if (score >= 70) return 'text-yellow-600';
402
+ return 'text-red-600';
403
+ };
404
+
405
+ const formatBytes = (bytes: number) => {
406
+ return `${(bytes / 1024 / 1024).toFixed(2)} MB`;
407
+ };
408
+
409
+ return (
410
+ <div className={`performance-dashboard rounded-lg bg-white p-4 shadow ${className}`}>
411
+ <h3 className="mb-4 font-semibold text-lg">Performance Dashboard</h3>
412
+
413
+ {/* Performance Score */}
414
+ <div className="mb-4">
415
+ <div className="flex items-center justify-between">
416
+ <span>Performance Score</span>
417
+ <span className={`font-bold ${getScoreColor(metrics.performanceScore)}`}>
418
+ {metrics.performanceScore.toFixed(0)}
419
+ </span>
420
+ </div>
421
+ <div className="mt-1 h-2 w-full rounded-full bg-gray-200">
422
+ <div
423
+ className={`h-2 rounded-full transition-all duration-300 ${
424
+ metrics.performanceScore >= 90 ? 'bg-green-500' :
425
+ metrics.performanceScore >= 70 ? 'bg-yellow-500' : 'bg-red-500'
426
+ }`}
427
+ style={{ width: `${metrics.performanceScore}%` }}
428
+ />
429
+ </div>
430
+ </div>
431
+
432
+ {/* Core Web Vitals */}
433
+ <div className="mb-4 grid grid-cols-2 gap-4">
434
+ <div>
435
+ <h4 className="mb-2 font-medium">Core Web Vitals</h4>
436
+ <div className="space-y-1 text-sm">
437
+ {metrics.lcp && (
438
+ <div>LCP: {metrics.lcp.toFixed(0)}ms</div>
439
+ )}
440
+ {metrics.fid && (
441
+ <div>FID: {metrics.fid.toFixed(0)}ms</div>
442
+ )}
443
+ {metrics.cls && (
444
+ <div>CLS: {metrics.cls.toFixed(3)}</div>
445
+ )}
446
+ </div>
447
+ </div>
448
+
449
+ <div>
450
+ <h4 className="mb-2 font-medium">Custom Metrics</h4>
451
+ <div className="space-y-1 text-sm">
452
+ <div>Render: {metrics.componentRenderTime.toFixed(2)}ms</div>
453
+ <div>Memory: {formatBytes(metrics.memoryUsage)}</div>
454
+ {metrics.bundleLoadTime > 0 && (
455
+ <div>Bundle: {metrics.bundleLoadTime.toFixed(0)}ms</div>
456
+ )}
457
+ </div>
458
+ </div>
459
+ </div>
460
+
461
+ {/* Advanced metrics */}
462
+ {showAdvanced && (
463
+ <div>
464
+ <h4 className="mb-2 font-medium">Advanced Metrics</h4>
465
+ <div className="space-y-1 text-sm">
466
+ <div>Average Render Time: {(averageMetrics.componentRenderTime || 0).toFixed(2)}ms</div>
467
+ <div>Average Memory: {formatBytes(averageMetrics.memoryUsage || 0)}</div>
468
+ <div>Average Score: {(averageMetrics.performanceScore || 0).toFixed(0)}</div>
469
+ </div>
470
+ </div>
471
+ )}
472
+ </div>
473
+ );
474
+ }
475
+
476
+ export default PerformanceMonitor;