@therealtinhtute/baroiplayer 1.0.8 → 1.2.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.
- package/LICENSE +2 -2
- package/README.md +15 -15
- package/dist/context/media.js +2 -0
- package/dist/context/media.js.map +1 -0
- package/dist/context/media.mjs +15 -0
- package/dist/context/media.mjs.map +1 -0
- package/dist/context/store.js +2 -0
- package/dist/context/store.js.map +1 -0
- package/dist/context/store.mjs +5 -0
- package/dist/context/store.mjs.map +1 -0
- package/dist/context-BYwDoSRX.js +1172 -0
- package/dist/context-BYwDoSRX.js.map +1 -0
- package/dist/context-eNS62_ac.cjs +23 -0
- package/dist/context-eNS62_ac.cjs.map +1 -0
- package/dist/core-events-B1iM2F46.cjs +2 -0
- package/dist/core-events-B1iM2F46.cjs.map +1 -0
- package/dist/core-events-DunPHKRE.js +484 -0
- package/dist/core-events-DunPHKRE.js.map +1 -0
- package/dist/core-plugins-By-4-kGs.cjs +2 -0
- package/dist/core-plugins-By-4-kGs.cjs.map +1 -0
- package/dist/core-plugins-DSBWcTuX.js +821 -0
- package/dist/core-plugins-DSBWcTuX.js.map +1 -0
- package/dist/core.js +37 -0
- package/dist/core.js.map +1 -0
- package/dist/core.mjs +1233 -0
- package/dist/core.mjs.map +1 -0
- package/dist/enhanced-components-B_l3cist.js +1142 -0
- package/dist/enhanced-components-B_l3cist.js.map +1 -0
- package/dist/enhanced-components-BspFs9OO.cjs +2 -0
- package/dist/enhanced-components-BspFs9OO.cjs.map +1 -0
- package/dist/hooks-BXwI8QG6.cjs +4 -0
- package/dist/hooks-BXwI8QG6.cjs.map +1 -0
- package/dist/hooks-Bpi-jDiO.js +1816 -0
- package/dist/hooks-Bpi-jDiO.js.map +1 -0
- package/dist/index.css +1 -102
- package/dist/index.js +112 -21
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +6273 -16
- package/dist/index.mjs.map +1 -0
- package/dist/minimal-components-C4z900Ro.js +1926 -0
- package/dist/minimal-components-C4z900Ro.js.map +1 -0
- package/dist/minimal-components-v4qBp6jv.cjs +2 -0
- package/dist/minimal-components-v4qBp6jv.cjs.map +1 -0
- package/dist/minimal-components.css +1 -589
- package/dist/mona-loading.gif +0 -0
- package/dist/performance-monitor-C5k6FDXw.js +301 -0
- package/dist/performance-monitor-C5k6FDXw.js.map +1 -0
- package/dist/performance-monitor-lJmuUjQQ.cjs +2 -0
- package/dist/performance-monitor-lJmuUjQQ.cjs.map +1 -0
- package/dist/utils-CFOue_9K.cjs +9 -0
- package/dist/utils-CFOue_9K.cjs.map +1 -0
- package/dist/utils-Dzpl2ArK.js +2844 -0
- package/dist/utils-Dzpl2ArK.js.map +1 -0
- package/dist/utils.js +2 -0
- package/dist/utils.js.map +1 -0
- package/dist/utils.mjs +11 -0
- package/dist/utils.mjs.map +1 -0
- package/package.json +11 -40
- package/src/adapters/videojs-adapter.tsx +441 -441
- package/src/components/AnimateLoading.tsx +85 -93
- package/src/components/LoadingState.tsx +199 -208
- package/src/components/__tests__/media-player-accessibility.test.tsx +510 -0
- package/src/components/__tests__/media-player-react19.test.tsx +457 -0
- package/src/components/accessibility/keyboard-help-overlay.tsx +201 -207
- package/src/components/basic/index.ts +28 -28
- package/src/components/enhanced/advanced-features.tsx +49 -54
- package/src/components/enhanced/debug-panel.tsx +148 -122
- package/src/components/enhanced/enhanced-controls.tsx +117 -120
- package/src/components/enhanced/enhanced-media-player.tsx +281 -224
- package/src/components/enhanced/error-handling.tsx +50 -57
- package/src/components/enhanced/index.ts +27 -27
- package/src/components/enhanced/media-player-enhanced.tsx +117 -83
- package/src/components/examples/basic-video-player.tsx +35 -40
- package/src/components/examples/enhanced-controls-example.tsx +16 -30
- package/src/components/examples/enhanced-media-player-example.tsx +196 -187
- package/src/components/examples/loading-states-demo.tsx +113 -113
- package/src/components/examples/react-19-demo.tsx +88 -116
- package/src/components/examples/volume-orientation-demo.tsx +77 -85
- package/src/components/icon-demo.tsx +189 -202
- package/src/components/icons/svg-icons/ArrowLeftIcon.tsx +13 -13
- package/src/components/icons/svg-icons/ArrowRightIcon.tsx +13 -13
- package/src/components/icons/svg-icons/AudioIcon.tsx +16 -16
- package/src/components/icons/svg-icons/BackwardIcon.tsx +7 -7
- package/src/components/icons/svg-icons/CameraIcon.tsx +13 -13
- package/src/components/icons/svg-icons/CheckIcon.tsx +13 -13
- package/src/components/icons/svg-icons/EnablePiPIcon.tsx +13 -13
- package/src/components/icons/svg-icons/ForwardIcon.tsx +7 -7
- package/src/components/icons/svg-icons/FullscreenEnterIcon.tsx +18 -18
- package/src/components/icons/svg-icons/FullscreenExitIcon.tsx +18 -18
- package/src/components/icons/svg-icons/LoadingIcon.tsx +27 -27
- package/src/components/icons/svg-icons/PauseIcon.tsx +18 -18
- package/src/components/icons/svg-icons/PlayIcon.tsx +16 -16
- package/src/components/icons/svg-icons/PlaybackSpeedIcon.tsx +18 -18
- package/src/components/icons/svg-icons/QualityIcon.tsx +16 -16
- package/src/components/icons/svg-icons/SettingsIcon.tsx +7 -7
- package/src/components/icons/svg-icons/SliderIcon.tsx +16 -16
- package/src/components/icons/svg-icons/SubtitleIcon.tsx +16 -16
- package/src/components/icons/svg-icons/SubtitleOffIcon.tsx +20 -20
- package/src/components/icons/svg-icons/UnPiPIcon.tsx +13 -13
- package/src/components/icons/svg-icons/VolumeMutedIcon.tsx +11 -11
- package/src/components/icons/svg-icons/VolumeOneIcon.tsx +17 -17
- package/src/components/icons/svg-icons/VolumeThreeIcon.tsx +11 -11
- package/src/components/icons/svg-icons/VolumeTwoIcon.tsx +11 -11
- package/src/components/legacy.tsx +14 -20
- package/src/components/media-metadata-display.tsx +78 -79
- package/src/components/media-player-controls.tsx +37 -40
- package/src/components/media-player-error.tsx +2 -2
- package/src/components/media-player-fullscreen.tsx +2 -2
- package/src/components/media-player-hls.tsx +89 -89
- package/src/components/media-player-play.tsx +2 -2
- package/src/components/media-player-root.tsx +20 -22
- package/src/components/media-player-seek.tsx +1 -1
- package/src/components/media-player-tooltip.tsx +1 -1
- package/src/components/media-player-video.tsx +21 -6
- package/src/components/media-player-volume.tsx +3 -3
- package/src/components/media-player.tsx +209 -174
- package/src/components/media-suspense.tsx +71 -89
- package/src/components/player-settings-form.tsx +143 -148
- package/src/components/react-player-wrapper.tsx +23 -23
- package/src/components/simple-video-player.tsx +53 -51
- package/src/components/ui/blur-poster.tsx +93 -0
- package/src/components/ui/empty-state.tsx +91 -0
- package/src/components/ui/enhanced-seek-bar.tsx +77 -58
- package/src/components/ui/error-state.tsx +124 -0
- package/src/components/ui/fullscreen-button.tsx +71 -50
- package/src/components/ui/loading-skeleton.tsx +107 -0
- package/src/components/ui/media-resource-preloader.tsx +262 -197
- package/src/components/ui/offline-message.tsx +98 -0
- package/src/components/ui/play-button.tsx +79 -87
- package/src/components/ui/seek-bar.tsx +170 -140
- package/src/components/ui/time-display.tsx +33 -12
- package/src/components/ui/volume-control.tsx +91 -44
- package/src/components/unified/base-media-player.tsx +61 -55
- package/src/components/unified/media-player.tsx +3 -3
- package/src/components/variants/minimal/AccessibleMinimalPlayer.tsx +528 -502
- package/src/components/variants/minimal/EnhancedMinimalMediaPlayer.tsx +110 -89
- package/src/components/variants/minimal/MinimalControls.tsx +100 -118
- package/src/components/variants/minimal/MinimalLoading.tsx +19 -23
- package/src/components/variants/minimal/MinimalMediaPlayer.tsx +283 -280
- package/src/components/variants/minimal/MinimalOverlay.tsx +43 -49
- package/src/components/variants/minimal/MinimalPlayButton.tsx +44 -53
- package/src/components/variants/minimal/MinimalSeekBar.tsx +130 -140
- package/src/components/variants/minimal/MinimalVolumeControl.tsx +59 -64
- package/src/components/variants/minimal/SimpleMinimalPlayer.tsx +29 -32
- package/src/components/variants/minimal/components/CenterPlayButton.tsx +1 -1
- package/src/components/variants/minimal/components/ControlBar.tsx +7 -11
- package/src/components/variants/minimal/components/EnhancedSettingsMenu.tsx +381 -330
- package/src/components/variants/minimal/components/PlaybackControls.tsx +6 -11
- package/src/components/variants/minimal/components/RightControls.tsx +8 -17
- package/src/components/variants/minimal/components/SeekBar.tsx +16 -20
- package/src/components/variants/minimal/components/SettingsDropdown.tsx +12 -14
- package/src/components/variants/minimal/components/SubtitleDisplay.tsx +1 -1
- package/src/components/variants/minimal/components/TimeDisplay.tsx +2 -5
- package/src/components/variants/minimal/components/VideoElement.tsx +3 -10
- package/src/components/variants/minimal/components/VolumeControl.tsx +42 -39
- package/src/components/video-player.tsx +10 -10
- package/src/context/__tests__/media-store.test.ts +509 -0
- package/src/context/error-handling.ts +106 -102
- package/src/context/media-context.tsx +56 -10
- package/src/context/media-provider.tsx +16 -17
- package/src/context/media-store.ts +68 -60
- package/src/context/persistence.ts +74 -65
- package/src/core/events/event-system.ts +422 -416
- package/src/core/events/hooks.ts +275 -252
- package/src/core/events/index.ts +14 -14
- package/src/core/events/middleware.ts +269 -252
- package/src/core/index.ts +8 -8
- package/src/core/optimization/bundle-optimizer.tsx +76 -72
- package/src/core/performance/cicd.ts +91 -89
- package/src/core/performance/index.ts +22 -22
- package/src/core/performance/media-loading-optimizer.ts +518 -512
- package/src/core/performance/performance-budgets.ts +414 -409
- package/src/core/performance/performance-monitor.tsx +451 -439
- package/src/core/performance/performance-testing.ts +439 -437
- package/src/core/plugins/__tests__/registry.test.ts +595 -0
- package/src/core/plugins/base-plugin.ts +197 -196
- package/src/core/plugins/enhanced-plugin-system.ts +157 -139
- package/src/core/plugins/examples/analytics-plugin.ts +229 -230
- package/src/core/plugins/index.ts +26 -26
- package/src/core/plugins/registry.ts +544 -325
- package/src/core/plugins/types.ts +115 -105
- package/src/core/plugins/utils.ts +292 -291
- package/src/core/progressive-loading.tsx +297 -288
- package/src/core/providers/enhanced-hls-provider.ts +98 -99
- package/src/core/providers/lazy-provider.tsx +14 -0
- package/src/core/providers/service-provider.tsx +104 -108
- package/src/core/utils.tsx +22 -26
- package/src/features/media-session/media-session-manager.ts +391 -409
- package/src/features/picture-in-picture/pip-manager.ts +364 -365
- package/src/features/playlist/playlist-manager.ts +605 -585
- package/src/features/subtitles/subtitle-manager.ts +424 -430
- package/src/features/subtitles/subtitle-parser.ts +277 -273
- package/src/features/thumbnails/thumbnail-generator.ts +511 -502
- package/src/hooks/__tests__/currentTime-fix.test.ts +149 -0
- package/src/hooks/__tests__/use-media-player.test.ts +712 -0
- package/src/hooks/__tests__/use-media-state.test.tsx +316 -0
- package/src/hooks/accessibility/index.ts +20 -20
- package/src/hooks/accessibility/use-accessibility-preferences.ts +177 -175
- package/src/hooks/accessibility/use-focus-management.ts +170 -163
- package/src/hooks/accessibility/use-keyboard-shortcuts.ts +132 -124
- package/src/hooks/accessibility/use-screen-reader.ts +191 -161
- package/src/hooks/core/index.ts +30 -30
- package/src/hooks/legacy.ts +3 -9
- package/src/hooks/use-buffer-health.ts +218 -0
- package/src/hooks/use-enhanced-media-player.ts +171 -81
- package/src/hooks/use-focus-trap.tsx +162 -0
- package/src/hooks/use-intelligent-preloading.ts +256 -232
- package/src/hooks/use-keyboard-controls.ts +80 -80
- package/src/hooks/use-keyboard-shortcuts.ts +255 -0
- package/src/hooks/use-media-actions.ts +81 -72
- package/src/hooks/use-media-metadata.ts +75 -73
- package/src/hooks/use-media-optimistic.ts +145 -151
- package/src/hooks/use-media-player.ts +193 -160
- package/src/hooks/use-media-state.ts +63 -59
- package/src/hooks/use-memory-optimization.ts +121 -119
- package/src/hooks/use-network-status.ts +124 -0
- package/src/hooks/use-optimistic-controls.ts +91 -88
- package/src/hooks/use-optimized-media.ts +76 -56
- package/src/hooks/use-smart-preload.ts +229 -0
- package/src/hooks/use-touch-gestures.ts +427 -383
- package/src/hooks/useEnhancedSubtitles.ts +245 -245
- package/src/hooks/useKeyboardShortcuts.ts +84 -52
- package/src/hooks/useMediaControls.ts +22 -22
- package/src/hooks/useScreenshot.ts +51 -47
- package/src/hooks/useSubtitles.ts +53 -53
- package/src/hooks/useVideoPlayer.ts +107 -61
- package/src/icons/components/FullscreenIcon.tsx +34 -35
- package/src/icons/components/SettingsIcon.tsx +35 -36
- package/src/icons/components/animated/LoadingIcon.tsx +25 -41
- package/src/icons/components/animated/PlayPauseIcon.tsx +38 -46
- package/src/icons/components/media/PauseIcon.tsx +36 -37
- package/src/icons/components/media/PlayIcon.tsx +35 -36
- package/src/icons/components/volume/VolumeIcon.tsx +36 -37
- package/src/icons/components/volume/VolumeOffIcon.tsx +36 -37
- package/src/icons/index.ts +38 -38
- package/src/icons/provider.tsx +40 -46
- package/src/icons/types.ts +51 -31
- package/src/index-enhanced.ts +10 -10
- package/src/index-legacy.ts +4 -7
- package/src/index.css +80 -80
- package/src/index.ts +8 -23
- package/src/lib/__tests__/async-utils.test.ts +291 -0
- package/src/lib/async-utils.ts +194 -0
- package/src/lib/deprecation.ts +4 -4
- package/src/lib/index.ts +3 -2
- package/src/lib/utils.ts +3 -3
- package/src/styles/globals.css +3 -3
- package/src/styles/minimal-player.css +606 -574
- package/src/styles/pixel-art.css +23 -28
- package/src/styles/videojs.css +43 -43
- package/src/test/accessibility-utils.ts +208 -0
- package/src/test/browser-simulation.ts +235 -0
- package/src/test/media-mocks.ts +169 -0
- package/src/test/performance-utils.ts +192 -0
- package/src/test/setup.ts +256 -41
- package/src/types/events.ts +30 -30
- package/src/types/formats.ts +56 -72
- package/src/types/index.ts +16 -38
- package/src/types/videojs-plugins.d.ts +6 -6
- package/dist/index.d.ts +0 -1425
- package/dist/package.json +0 -62
- package/dist/src/adapters/videojs-adapter.d.ts +0 -38
- package/dist/src/adapters/videojs-adapter.tsx +0 -470
- package/dist/src/components/AnimateLoading.d.ts +0 -9
- package/dist/src/components/AnimateLoading.tsx +0 -115
- package/dist/src/components/LoadingState.d.ts +0 -33
- package/dist/src/components/LoadingState.tsx +0 -248
- package/dist/src/components/accessibility/keyboard-help-overlay.d.ts +0 -17
- package/dist/src/components/accessibility/keyboard-help-overlay.tsx +0 -213
- package/dist/src/components/audio-player.d.ts +0 -3
- package/dist/src/components/audio-player.tsx +0 -85
- package/dist/src/components/basic/index.d.ts +0 -26
- package/dist/src/components/basic/index.ts +0 -37
- package/dist/src/components/enhanced/advanced-features.d.ts +0 -45
- package/dist/src/components/enhanced/advanced-features.tsx +0 -316
- package/dist/src/components/enhanced/debug-panel.d.ts +0 -70
- package/dist/src/components/enhanced/debug-panel.tsx +0 -422
- package/dist/src/components/enhanced/enhanced-controls.d.ts +0 -50
- package/dist/src/components/enhanced/enhanced-controls.tsx +0 -600
- package/dist/src/components/enhanced/enhanced-media-player.d.ts +0 -26
- package/dist/src/components/enhanced/enhanced-media-player.tsx +0 -509
- package/dist/src/components/enhanced/error-handling.d.ts +0 -36
- package/dist/src/components/enhanced/error-handling.tsx +0 -345
- package/dist/src/components/enhanced/index.d.ts +0 -7
- package/dist/src/components/enhanced/index.ts +0 -39
- package/dist/src/components/enhanced/media-player-enhanced.d.ts +0 -21
- package/dist/src/components/enhanced/media-player-enhanced.tsx +0 -349
- package/dist/src/components/examples/basic-video-player.d.ts +0 -10
- package/dist/src/components/examples/basic-video-player.tsx +0 -55
- package/dist/src/components/examples/custom-controls-example.d.ts +0 -10
- package/dist/src/components/examples/custom-controls-example.tsx +0 -63
- package/dist/src/components/examples/enhanced-controls-example.d.ts +0 -9
- package/dist/src/components/examples/enhanced-controls-example.tsx +0 -114
- package/dist/src/components/examples/enhanced-media-player-example.d.ts +0 -9
- package/dist/src/components/examples/enhanced-media-player-example.tsx +0 -293
- package/dist/src/components/examples/loading-states-demo.d.ts +0 -2
- package/dist/src/components/examples/loading-states-demo.tsx +0 -142
- package/dist/src/components/examples/react-19-demo.d.ts +0 -10
- package/dist/src/components/examples/react-19-demo.tsx +0 -381
- package/dist/src/components/examples/volume-orientation-demo.d.ts +0 -2
- package/dist/src/components/examples/volume-orientation-demo.tsx +0 -114
- package/dist/src/components/icon-demo.d.ts +0 -2
- package/dist/src/components/icon-demo.tsx +0 -209
- package/dist/src/components/icons/index.d.ts +0 -36
- package/dist/src/components/icons/index.tsx +0 -166
- package/dist/src/components/icons/svg-icons/ArrowLeftIcon.d.ts +0 -4
- package/dist/src/components/icons/svg-icons/ArrowLeftIcon.tsx +0 -18
- package/dist/src/components/icons/svg-icons/ArrowRightIcon.d.ts +0 -4
- package/dist/src/components/icons/svg-icons/ArrowRightIcon.tsx +0 -18
- package/dist/src/components/icons/svg-icons/AudioIcon.d.ts +0 -4
- package/dist/src/components/icons/svg-icons/AudioIcon.tsx +0 -22
- package/dist/src/components/icons/svg-icons/BackwardIcon.d.ts +0 -4
- package/dist/src/components/icons/svg-icons/BackwardIcon.tsx +0 -12
- package/dist/src/components/icons/svg-icons/CameraIcon.d.ts +0 -4
- package/dist/src/components/icons/svg-icons/CameraIcon.tsx +0 -19
- package/dist/src/components/icons/svg-icons/CheckIcon.d.ts +0 -4
- package/dist/src/components/icons/svg-icons/CheckIcon.tsx +0 -19
- package/dist/src/components/icons/svg-icons/EnablePiPIcon.d.ts +0 -4
- package/dist/src/components/icons/svg-icons/EnablePiPIcon.tsx +0 -17
- package/dist/src/components/icons/svg-icons/ForwardIcon.d.ts +0 -4
- package/dist/src/components/icons/svg-icons/ForwardIcon.tsx +0 -12
- package/dist/src/components/icons/svg-icons/FullscreenEnterIcon.d.ts +0 -4
- package/dist/src/components/icons/svg-icons/FullscreenEnterIcon.tsx +0 -23
- package/dist/src/components/icons/svg-icons/FullscreenExitIcon.d.ts +0 -4
- package/dist/src/components/icons/svg-icons/FullscreenExitIcon.tsx +0 -23
- package/dist/src/components/icons/svg-icons/LoadingIcon.d.ts +0 -4
- package/dist/src/components/icons/svg-icons/LoadingIcon.tsx +0 -32
- package/dist/src/components/icons/svg-icons/PauseIcon.d.ts +0 -4
- package/dist/src/components/icons/svg-icons/PauseIcon.tsx +0 -23
- package/dist/src/components/icons/svg-icons/PlayIcon.d.ts +0 -4
- package/dist/src/components/icons/svg-icons/PlayIcon.tsx +0 -21
- package/dist/src/components/icons/svg-icons/PlaybackSpeedIcon.d.ts +0 -4
- package/dist/src/components/icons/svg-icons/PlaybackSpeedIcon.tsx +0 -23
- package/dist/src/components/icons/svg-icons/QualityIcon.d.ts +0 -4
- package/dist/src/components/icons/svg-icons/QualityIcon.tsx +0 -21
- package/dist/src/components/icons/svg-icons/SettingsIcon.d.ts +0 -4
- package/dist/src/components/icons/svg-icons/SettingsIcon.tsx +0 -12
- package/dist/src/components/icons/svg-icons/SliderIcon.d.ts +0 -4
- package/dist/src/components/icons/svg-icons/SliderIcon.tsx +0 -21
- package/dist/src/components/icons/svg-icons/SubtitleIcon.d.ts +0 -4
- package/dist/src/components/icons/svg-icons/SubtitleIcon.tsx +0 -21
- package/dist/src/components/icons/svg-icons/SubtitleOffIcon.d.ts +0 -4
- package/dist/src/components/icons/svg-icons/SubtitleOffIcon.tsx +0 -25
- package/dist/src/components/icons/svg-icons/UnPiPIcon.d.ts +0 -4
- package/dist/src/components/icons/svg-icons/UnPiPIcon.tsx +0 -17
- package/dist/src/components/icons/svg-icons/VolumeMutedIcon.d.ts +0 -4
- package/dist/src/components/icons/svg-icons/VolumeMutedIcon.tsx +0 -16
- package/dist/src/components/icons/svg-icons/VolumeOneIcon.d.ts +0 -4
- package/dist/src/components/icons/svg-icons/VolumeOneIcon.tsx +0 -22
- package/dist/src/components/icons/svg-icons/VolumeThreeIcon.d.ts +0 -4
- package/dist/src/components/icons/svg-icons/VolumeThreeIcon.tsx +0 -16
- package/dist/src/components/icons/svg-icons/VolumeTwoIcon.d.ts +0 -4
- package/dist/src/components/icons/svg-icons/VolumeTwoIcon.tsx +0 -16
- package/dist/src/components/legacy.d.ts +0 -13
- package/dist/src/components/legacy.tsx +0 -93
- package/dist/src/components/media-metadata-display.d.ts +0 -11
- package/dist/src/components/media-metadata-display.tsx +0 -100
- package/dist/src/components/media-player-audio.d.ts +0 -9
- package/dist/src/components/media-player-audio.tsx +0 -39
- package/dist/src/components/media-player-controls.d.ts +0 -23
- package/dist/src/components/media-player-controls.tsx +0 -226
- package/dist/src/components/media-player-error.d.ts +0 -16
- package/dist/src/components/media-player-error.tsx +0 -163
- package/dist/src/components/media-player-fullscreen.d.ts +0 -12
- package/dist/src/components/media-player-fullscreen.tsx +0 -109
- package/dist/src/components/media-player-hls.d.ts +0 -23
- package/dist/src/components/media-player-hls.tsx +0 -111
- package/dist/src/components/media-player-loading.d.ts +0 -12
- package/dist/src/components/media-player-loading.tsx +0 -76
- package/dist/src/components/media-player-play.d.ts +0 -11
- package/dist/src/components/media-player-play.tsx +0 -75
- package/dist/src/components/media-player-root.d.ts +0 -28
- package/dist/src/components/media-player-root.tsx +0 -340
- package/dist/src/components/media-player-seek.d.ts +0 -15
- package/dist/src/components/media-player-seek.tsx +0 -168
- package/dist/src/components/media-player-time.d.ts +0 -12
- package/dist/src/components/media-player-time.tsx +0 -99
- package/dist/src/components/media-player-tooltip.d.ts +0 -13
- package/dist/src/components/media-player-tooltip.tsx +0 -58
- package/dist/src/components/media-player-video.d.ts +0 -9
- package/dist/src/components/media-player-video.tsx +0 -39
- package/dist/src/components/media-player-volume.d.ts +0 -13
- package/dist/src/components/media-player-volume.tsx +0 -155
- package/dist/src/components/media-player.d.ts +0 -3
- package/dist/src/components/media-player.tsx +0 -257
- package/dist/src/components/media-suspense.d.ts +0 -78
- package/dist/src/components/media-suspense.tsx +0 -362
- package/dist/src/components/player-settings-form.d.ts +0 -8
- package/dist/src/components/player-settings-form.tsx +0 -163
- package/dist/src/components/react-player-wrapper.d.ts +0 -64
- package/dist/src/components/react-player-wrapper.tsx +0 -651
- package/dist/src/components/simple-video-player.d.ts +0 -9
- package/dist/src/components/simple-video-player.tsx +0 -60
- package/dist/src/components/ui/button.tsx +0 -49
- package/dist/src/components/ui/dropdown-menu.tsx +0 -137
- package/dist/src/components/ui/enhanced-seek-bar.d.ts +0 -3
- package/dist/src/components/ui/enhanced-seek-bar.tsx +0 -235
- package/dist/src/components/ui/fullscreen-button.d.ts +0 -3
- package/dist/src/components/ui/fullscreen-button.tsx +0 -60
- package/dist/src/components/ui/icons.tsx +0 -174
- package/dist/src/components/ui/media-resource-preloader.d.ts +0 -21
- package/dist/src/components/ui/media-resource-preloader.tsx +0 -393
- package/dist/src/components/ui/play-button.d.ts +0 -3
- package/dist/src/components/ui/play-button.tsx +0 -107
- package/dist/src/components/ui/seek-bar.d.ts +0 -3
- package/dist/src/components/ui/seek-bar.tsx +0 -161
- package/dist/src/components/ui/slider.tsx +0 -55
- package/dist/src/components/ui/time-display.d.ts +0 -3
- package/dist/src/components/ui/time-display.tsx +0 -40
- package/dist/src/components/ui/tooltip.tsx +0 -131
- package/dist/src/components/ui/volume-control.d.ts +0 -3
- package/dist/src/components/ui/volume-control.tsx +0 -143
- package/dist/src/components/unified/base-media-player.d.ts +0 -18
- package/dist/src/components/unified/base-media-player.tsx +0 -246
- package/dist/src/components/unified/media-player.d.ts +0 -37
- package/dist/src/components/unified/media-player.tsx +0 -75
- package/dist/src/components/variants/minimal/AccessibleMinimalPlayer.d.ts +0 -42
- package/dist/src/components/variants/minimal/AccessibleMinimalPlayer.tsx +0 -561
- package/dist/src/components/variants/minimal/EnhancedMinimalMediaPlayer.d.ts +0 -44
- package/dist/src/components/variants/minimal/EnhancedMinimalMediaPlayer.tsx +0 -552
- package/dist/src/components/variants/minimal/MinimalControls.d.ts +0 -19
- package/dist/src/components/variants/minimal/MinimalControls.tsx +0 -142
- package/dist/src/components/variants/minimal/MinimalLoading.d.ts +0 -10
- package/dist/src/components/variants/minimal/MinimalLoading.tsx +0 -32
- package/dist/src/components/variants/minimal/MinimalMediaPlayer.d.ts +0 -38
- package/dist/src/components/variants/minimal/MinimalMediaPlayer.tsx +0 -315
- package/dist/src/components/variants/minimal/MinimalOverlay.d.ts +0 -11
- package/dist/src/components/variants/minimal/MinimalOverlay.tsx +0 -64
- package/dist/src/components/variants/minimal/MinimalPlayButton.d.ts +0 -9
- package/dist/src/components/variants/minimal/MinimalPlayButton.tsx +0 -65
- package/dist/src/components/variants/minimal/MinimalSeekBar.d.ts +0 -7
- package/dist/src/components/variants/minimal/MinimalSeekBar.tsx +0 -150
- package/dist/src/components/variants/minimal/MinimalVolumeControl.d.ts +0 -7
- package/dist/src/components/variants/minimal/MinimalVolumeControl.tsx +0 -80
- package/dist/src/components/variants/minimal/SimpleMinimalPlayer.d.ts +0 -22
- package/dist/src/components/variants/minimal/SimpleMinimalPlayer.tsx +0 -209
- package/dist/src/components/variants/minimal/components/CenterPlayButton.d.ts +0 -7
- package/dist/src/components/variants/minimal/components/CenterPlayButton.tsx +0 -22
- package/dist/src/components/variants/minimal/components/ControlBar.d.ts +0 -43
- package/dist/src/components/variants/minimal/components/ControlBar.tsx +0 -146
- package/dist/src/components/variants/minimal/components/EnhancedSettingsMenu.d.ts +0 -24
- package/dist/src/components/variants/minimal/components/EnhancedSettingsMenu.tsx +0 -361
- package/dist/src/components/variants/minimal/components/PlaybackControls.d.ts +0 -9
- package/dist/src/components/variants/minimal/components/PlaybackControls.tsx +0 -51
- package/dist/src/components/variants/minimal/components/RightControls.d.ts +0 -25
- package/dist/src/components/variants/minimal/components/RightControls.tsx +0 -173
- package/dist/src/components/variants/minimal/components/SeekBar.d.ts +0 -11
- package/dist/src/components/variants/minimal/components/SeekBar.tsx +0 -131
- package/dist/src/components/variants/minimal/components/SettingsDropdown.d.ts +0 -9
- package/dist/src/components/variants/minimal/components/SettingsDropdown.tsx +0 -70
- package/dist/src/components/variants/minimal/components/SubtitleDisplay.d.ts +0 -7
- package/dist/src/components/variants/minimal/components/SubtitleDisplay.tsx +0 -21
- package/dist/src/components/variants/minimal/components/TimeDisplay.d.ts +0 -7
- package/dist/src/components/variants/minimal/components/TimeDisplay.tsx +0 -18
- package/dist/src/components/variants/minimal/components/VideoElement.d.ts +0 -13
- package/dist/src/components/variants/minimal/components/VideoElement.tsx +0 -40
- package/dist/src/components/variants/minimal/components/VolumeControl.d.ts +0 -13
- package/dist/src/components/variants/minimal/components/VolumeControl.tsx +0 -217
- package/dist/src/components/variants/minimal/index.d.ts +0 -17
- package/dist/src/components/variants/minimal/index.ts +0 -23
- package/dist/src/components/video-player.d.ts +0 -3
- package/dist/src/components/video-player.tsx +0 -100
- package/dist/src/context/error-handling.d.ts +0 -72
- package/dist/src/context/error-handling.ts +0 -394
- package/dist/src/context/media-context.d.ts +0 -104
- package/dist/src/context/media-context.tsx +0 -208
- package/dist/src/context/media-provider.d.ts +0 -26
- package/dist/src/context/media-provider.tsx +0 -265
- package/dist/src/context/media-store.d.ts +0 -33
- package/dist/src/context/media-store.ts +0 -379
- package/dist/src/context/persistence.d.ts +0 -83
- package/dist/src/context/persistence.ts +0 -453
- package/dist/src/core/events/event-system.d.ts +0 -170
- package/dist/src/core/events/event-system.ts +0 -442
- package/dist/src/core/events/hooks.d.ts +0 -33
- package/dist/src/core/events/hooks.ts +0 -302
- package/dist/src/core/events/index.d.ts +0 -6
- package/dist/src/core/events/index.ts +0 -22
- package/dist/src/core/events/middleware.d.ts +0 -39
- package/dist/src/core/events/middleware.ts +0 -269
- package/dist/src/core/index.d.ts +0 -8
- package/dist/src/core/index.ts +0 -22
- package/dist/src/core/optimization/bundle-optimizer.d.ts +0 -44
- package/dist/src/core/optimization/bundle-optimizer.tsx +0 -308
- package/dist/src/core/performance/cicd.d.ts +0 -8
- package/dist/src/core/performance/cicd.ts +0 -96
- package/dist/src/core/performance/index.d.ts +0 -10
- package/dist/src/core/performance/index.ts +0 -38
- package/dist/src/core/performance/media-loading-optimizer.d.ts +0 -105
- package/dist/src/core/performance/media-loading-optimizer.ts +0 -538
- package/dist/src/core/performance/performance-budgets.d.ts +0 -68
- package/dist/src/core/performance/performance-budgets.ts +0 -432
- package/dist/src/core/performance/performance-monitor.d.ts +0 -95
- package/dist/src/core/performance/performance-monitor.tsx +0 -476
- package/dist/src/core/performance/performance-testing.d.ts +0 -69
- package/dist/src/core/performance/performance-testing.ts +0 -459
- package/dist/src/core/plugins/base-plugin.d.ts +0 -52
- package/dist/src/core/plugins/base-plugin.ts +0 -224
- package/dist/src/core/plugins/enhanced-plugin-system.d.ts +0 -160
- package/dist/src/core/plugins/enhanced-plugin-system.ts +0 -417
- package/dist/src/core/plugins/examples/analytics-plugin.d.ts +0 -30
- package/dist/src/core/plugins/examples/analytics-plugin.ts +0 -242
- package/dist/src/core/plugins/index.d.ts +0 -8
- package/dist/src/core/plugins/index.ts +0 -39
- package/dist/src/core/plugins/registry.d.ts +0 -31
- package/dist/src/core/plugins/registry.ts +0 -327
- package/dist/src/core/plugins/types.d.ts +0 -101
- package/dist/src/core/plugins/types.ts +0 -159
- package/dist/src/core/plugins/utils.d.ts +0 -38
- package/dist/src/core/plugins/utils.ts +0 -316
- package/dist/src/core/progressive-loading.d.ts +0 -88
- package/dist/src/core/progressive-loading.tsx +0 -322
- package/dist/src/core/providers/enhanced-hls-provider.d.ts +0 -50
- package/dist/src/core/providers/enhanced-hls-provider.ts +0 -308
- package/dist/src/core/providers/service-provider.d.ts +0 -49
- package/dist/src/core/providers/service-provider.tsx +0 -168
- package/dist/src/core/utils.d.ts +0 -25
- package/dist/src/core/utils.tsx +0 -38
- package/dist/src/features/media-session/media-session-manager.d.ts +0 -132
- package/dist/src/features/media-session/media-session-manager.ts +0 -429
- package/dist/src/features/picture-in-picture/pip-manager.d.ts +0 -94
- package/dist/src/features/picture-in-picture/pip-manager.ts +0 -429
- package/dist/src/features/playlist/playlist-manager.d.ts +0 -208
- package/dist/src/features/playlist/playlist-manager.ts +0 -606
- package/dist/src/features/subtitles/subtitle-manager.d.ts +0 -136
- package/dist/src/features/subtitles/subtitle-manager.ts +0 -441
- package/dist/src/features/subtitles/subtitle-parser.d.ts +0 -60
- package/dist/src/features/subtitles/subtitle-parser.ts +0 -280
- package/dist/src/features/thumbnails/thumbnail-generator.d.ts +0 -136
- package/dist/src/features/thumbnails/thumbnail-generator.ts +0 -519
- package/dist/src/hooks/accessibility/index.d.ts +0 -5
- package/dist/src/hooks/accessibility/index.ts +0 -27
- package/dist/src/hooks/accessibility/use-accessibility-preferences.d.ts +0 -14
- package/dist/src/hooks/accessibility/use-accessibility-preferences.ts +0 -188
- package/dist/src/hooks/accessibility/use-focus-management.d.ts +0 -31
- package/dist/src/hooks/accessibility/use-focus-management.ts +0 -176
- package/dist/src/hooks/accessibility/use-keyboard-shortcuts.d.ts +0 -38
- package/dist/src/hooks/accessibility/use-keyboard-shortcuts.ts +0 -144
- package/dist/src/hooks/accessibility/use-screen-reader.d.ts +0 -22
- package/dist/src/hooks/accessibility/use-screen-reader.ts +0 -182
- package/dist/src/hooks/core/index.d.ts +0 -18
- package/dist/src/hooks/core/index.ts +0 -47
- package/dist/src/hooks/legacy.d.ts +0 -18
- package/dist/src/hooks/legacy.ts +0 -27
- package/dist/src/hooks/use-enhanced-media-player.d.ts +0 -88
- package/dist/src/hooks/use-enhanced-media-player.ts +0 -485
- package/dist/src/hooks/use-intelligent-preloading.d.ts +0 -66
- package/dist/src/hooks/use-intelligent-preloading.ts +0 -363
- package/dist/src/hooks/use-keyboard-controls.d.ts +0 -13
- package/dist/src/hooks/use-keyboard-controls.ts +0 -115
- package/dist/src/hooks/use-media-actions.d.ts +0 -62
- package/dist/src/hooks/use-media-actions.ts +0 -175
- package/dist/src/hooks/use-media-metadata.d.ts +0 -11
- package/dist/src/hooks/use-media-metadata.ts +0 -89
- package/dist/src/hooks/use-media-optimistic.d.ts +0 -36
- package/dist/src/hooks/use-media-optimistic.ts +0 -270
- package/dist/src/hooks/use-media-player.d.ts +0 -31
- package/dist/src/hooks/use-media-player.ts +0 -310
- package/dist/src/hooks/use-media-state.d.ts +0 -17
- package/dist/src/hooks/use-media-state.ts +0 -190
- package/dist/src/hooks/use-memory-optimization.d.ts +0 -40
- package/dist/src/hooks/use-memory-optimization.ts +0 -358
- package/dist/src/hooks/use-mobile.ts +0 -125
- package/dist/src/hooks/use-optimistic-controls.d.ts +0 -22
- package/dist/src/hooks/use-optimistic-controls.ts +0 -92
- package/dist/src/hooks/use-optimized-media.d.ts +0 -46
- package/dist/src/hooks/use-optimized-media.ts +0 -263
- package/dist/src/hooks/use-touch-gestures.d.ts +0 -47
- package/dist/src/hooks/use-touch-gestures.ts +0 -417
- package/dist/src/hooks/useEnhancedSubtitles.d.ts +0 -39
- package/dist/src/hooks/useEnhancedSubtitles.ts +0 -258
- package/dist/src/hooks/useKeyboardShortcuts.d.ts +0 -10
- package/dist/src/hooks/useKeyboardShortcuts.ts +0 -74
- package/dist/src/hooks/useMediaControls.d.ts +0 -9
- package/dist/src/hooks/useMediaControls.ts +0 -52
- package/dist/src/hooks/useScreenshot.d.ts +0 -4
- package/dist/src/hooks/useScreenshot.ts +0 -57
- package/dist/src/hooks/useSubtitles.d.ts +0 -8
- package/dist/src/hooks/useSubtitles.ts +0 -91
- package/dist/src/hooks/useVideoPlayer.d.ts +0 -32
- package/dist/src/hooks/useVideoPlayer.ts +0 -232
- package/dist/src/icons/components/FullscreenIcon.d.ts +0 -3
- package/dist/src/icons/components/FullscreenIcon.tsx +0 -37
- package/dist/src/icons/components/SettingsIcon.d.ts +0 -3
- package/dist/src/icons/components/SettingsIcon.tsx +0 -38
- package/dist/src/icons/components/animated/LoadingIcon.d.ts +0 -3
- package/dist/src/icons/components/animated/LoadingIcon.tsx +0 -43
- package/dist/src/icons/components/animated/PlayPauseIcon.d.ts +0 -7
- package/dist/src/icons/components/animated/PlayPauseIcon.tsx +0 -50
- package/dist/src/icons/components/media/PauseIcon.d.ts +0 -3
- package/dist/src/icons/components/media/PauseIcon.tsx +0 -39
- package/dist/src/icons/components/media/PlayIcon.d.ts +0 -3
- package/dist/src/icons/components/media/PlayIcon.tsx +0 -38
- package/dist/src/icons/components/volume/VolumeIcon.d.ts +0 -3
- package/dist/src/icons/components/volume/VolumeIcon.tsx +0 -39
- package/dist/src/icons/components/volume/VolumeOffIcon.d.ts +0 -3
- package/dist/src/icons/components/volume/VolumeOffIcon.tsx +0 -39
- package/dist/src/icons/index.d.ts +0 -28
- package/dist/src/icons/index.ts +0 -56
- package/dist/src/icons/provider.d.ts +0 -13
- package/dist/src/icons/provider.tsx +0 -64
- package/dist/src/icons/types.d.ts +0 -18
- package/dist/src/icons/types.ts +0 -40
- package/dist/src/index-enhanced.d.ts +0 -13
- package/dist/src/index-enhanced.ts +0 -35
- package/dist/src/index-legacy.d.ts +0 -81
- package/dist/src/index-legacy.ts +0 -327
- package/dist/src/index.css +0 -102
- package/dist/src/index.d.ts +0 -38
- package/dist/src/index.minimal.d.ts +0 -2
- package/dist/src/index.minimal.ts +0 -4
- package/dist/src/index.ts +0 -216
- package/dist/src/lib/deprecation.d.ts +0 -7
- package/dist/src/lib/deprecation.ts +0 -51
- package/dist/src/lib/format-time.d.ts +0 -9
- package/dist/src/lib/format-time.ts +0 -37
- package/dist/src/lib/index.d.ts +0 -3
- package/dist/src/lib/index.ts +0 -3
- package/dist/src/lib/utils.d.ts +0 -3
- package/dist/src/lib/utils.ts +0 -6
- package/dist/src/styles/globals.css +0 -462
- package/dist/src/styles/minimal-player.css +0 -589
- package/dist/src/styles/pixel-art.css +0 -46
- package/dist/src/styles/videojs.css +0 -100
- package/dist/src/test/setup.d.ts +0 -2
- package/dist/src/test/setup.ts +0 -79
- package/dist/src/types/events.d.ts +0 -41
- package/dist/src/types/events.ts +0 -47
- package/dist/src/types/formats.d.ts +0 -45
- package/dist/src/types/formats.ts +0 -95
- package/dist/src/types/index.d.ts +0 -128
- package/dist/src/types/index.ts +0 -225
- package/dist/src/types/videojs-plugins.d.ts +0 -14
- package/dist/styles/globals.css +0 -462
- package/dist/styles/minimal-player.css +0 -589
- package/dist/styles/pixel-art.css +0 -46
- package/dist/styles/videojs.css +0 -100
- package/src/adapters/videojs-adapter.d.ts +0 -38
- package/src/adapters/videojs-adapter.d.ts.map +0 -1
- package/src/components/AnimateLoading.d.ts +0 -9
- package/src/components/AnimateLoading.d.ts.map +0 -1
- package/src/components/LoadingState.d.ts +0 -33
- package/src/components/LoadingState.d.ts.map +0 -1
- package/src/components/accessibility/keyboard-help-overlay.d.ts +0 -17
- package/src/components/accessibility/keyboard-help-overlay.d.ts.map +0 -1
- package/src/components/audio-player.d.ts +0 -3
- package/src/components/audio-player.d.ts.map +0 -1
- package/src/components/basic/index.d.ts +0 -26
- package/src/components/basic/index.d.ts.map +0 -1
- package/src/components/enhanced/advanced-features.d.ts +0 -45
- package/src/components/enhanced/advanced-features.d.ts.map +0 -1
- package/src/components/enhanced/debug-panel.d.ts +0 -70
- package/src/components/enhanced/debug-panel.d.ts.map +0 -1
- package/src/components/enhanced/enhanced-controls.d.ts +0 -50
- package/src/components/enhanced/enhanced-controls.d.ts.map +0 -1
- package/src/components/enhanced/enhanced-media-player.d.ts +0 -26
- package/src/components/enhanced/enhanced-media-player.d.ts.map +0 -1
- package/src/components/enhanced/error-handling.d.ts +0 -36
- package/src/components/enhanced/error-handling.d.ts.map +0 -1
- package/src/components/enhanced/index.d.ts +0 -7
- package/src/components/enhanced/index.d.ts.map +0 -1
- package/src/components/enhanced/media-player-enhanced.d.ts +0 -21
- package/src/components/enhanced/media-player-enhanced.d.ts.map +0 -1
- package/src/components/examples/basic-video-player.d.ts +0 -10
- package/src/components/examples/basic-video-player.d.ts.map +0 -1
- package/src/components/examples/custom-controls-example.d.ts +0 -10
- package/src/components/examples/custom-controls-example.d.ts.map +0 -1
- package/src/components/examples/enhanced-controls-example.d.ts +0 -9
- package/src/components/examples/enhanced-controls-example.d.ts.map +0 -1
- package/src/components/examples/enhanced-media-player-example.d.ts +0 -9
- package/src/components/examples/enhanced-media-player-example.d.ts.map +0 -1
- package/src/components/examples/loading-states-demo.d.ts +0 -2
- package/src/components/examples/loading-states-demo.d.ts.map +0 -1
- package/src/components/examples/react-19-demo.d.ts +0 -10
- package/src/components/examples/react-19-demo.d.ts.map +0 -1
- package/src/components/examples/volume-orientation-demo.d.ts +0 -2
- package/src/components/examples/volume-orientation-demo.d.ts.map +0 -1
- package/src/components/icon-demo.d.ts +0 -2
- package/src/components/icon-demo.d.ts.map +0 -1
- package/src/components/icons/index.d.ts +0 -36
- package/src/components/icons/index.d.ts.map +0 -1
- package/src/components/icons/svg-icons/ArrowLeftIcon.d.ts +0 -4
- package/src/components/icons/svg-icons/ArrowLeftIcon.d.ts.map +0 -1
- package/src/components/icons/svg-icons/ArrowRightIcon.d.ts +0 -4
- package/src/components/icons/svg-icons/ArrowRightIcon.d.ts.map +0 -1
- package/src/components/icons/svg-icons/AudioIcon.d.ts +0 -4
- package/src/components/icons/svg-icons/AudioIcon.d.ts.map +0 -1
- package/src/components/icons/svg-icons/BackwardIcon.d.ts +0 -4
- package/src/components/icons/svg-icons/BackwardIcon.d.ts.map +0 -1
- package/src/components/icons/svg-icons/CameraIcon.d.ts +0 -4
- package/src/components/icons/svg-icons/CameraIcon.d.ts.map +0 -1
- package/src/components/icons/svg-icons/CheckIcon.d.ts +0 -4
- package/src/components/icons/svg-icons/CheckIcon.d.ts.map +0 -1
- package/src/components/icons/svg-icons/EnablePiPIcon.d.ts +0 -4
- package/src/components/icons/svg-icons/EnablePiPIcon.d.ts.map +0 -1
- package/src/components/icons/svg-icons/ForwardIcon.d.ts +0 -4
- package/src/components/icons/svg-icons/ForwardIcon.d.ts.map +0 -1
- package/src/components/icons/svg-icons/FullscreenEnterIcon.d.ts +0 -4
- package/src/components/icons/svg-icons/FullscreenEnterIcon.d.ts.map +0 -1
- package/src/components/icons/svg-icons/FullscreenExitIcon.d.ts +0 -4
- package/src/components/icons/svg-icons/FullscreenExitIcon.d.ts.map +0 -1
- package/src/components/icons/svg-icons/LoadingIcon.d.ts +0 -4
- package/src/components/icons/svg-icons/LoadingIcon.d.ts.map +0 -1
- package/src/components/icons/svg-icons/PauseIcon.d.ts +0 -4
- package/src/components/icons/svg-icons/PauseIcon.d.ts.map +0 -1
- package/src/components/icons/svg-icons/PlayIcon.d.ts +0 -4
- package/src/components/icons/svg-icons/PlayIcon.d.ts.map +0 -1
- package/src/components/icons/svg-icons/PlaybackSpeedIcon.d.ts +0 -4
- package/src/components/icons/svg-icons/PlaybackSpeedIcon.d.ts.map +0 -1
- package/src/components/icons/svg-icons/QualityIcon.d.ts +0 -4
- package/src/components/icons/svg-icons/QualityIcon.d.ts.map +0 -1
- package/src/components/icons/svg-icons/SettingsIcon.d.ts +0 -4
- package/src/components/icons/svg-icons/SettingsIcon.d.ts.map +0 -1
- package/src/components/icons/svg-icons/SliderIcon.d.ts +0 -4
- package/src/components/icons/svg-icons/SliderIcon.d.ts.map +0 -1
- package/src/components/icons/svg-icons/SubtitleIcon.d.ts +0 -4
- package/src/components/icons/svg-icons/SubtitleIcon.d.ts.map +0 -1
- package/src/components/icons/svg-icons/SubtitleOffIcon.d.ts +0 -4
- package/src/components/icons/svg-icons/SubtitleOffIcon.d.ts.map +0 -1
- package/src/components/icons/svg-icons/UnPiPIcon.d.ts +0 -4
- package/src/components/icons/svg-icons/UnPiPIcon.d.ts.map +0 -1
- package/src/components/icons/svg-icons/VolumeMutedIcon.d.ts +0 -4
- package/src/components/icons/svg-icons/VolumeMutedIcon.d.ts.map +0 -1
- package/src/components/icons/svg-icons/VolumeOneIcon.d.ts +0 -4
- package/src/components/icons/svg-icons/VolumeOneIcon.d.ts.map +0 -1
- package/src/components/icons/svg-icons/VolumeThreeIcon.d.ts +0 -4
- package/src/components/icons/svg-icons/VolumeThreeIcon.d.ts.map +0 -1
- package/src/components/icons/svg-icons/VolumeTwoIcon.d.ts +0 -4
- package/src/components/icons/svg-icons/VolumeTwoIcon.d.ts.map +0 -1
- package/src/components/legacy.d.ts +0 -13
- package/src/components/legacy.d.ts.map +0 -1
- package/src/components/media-metadata-display.d.ts +0 -11
- package/src/components/media-metadata-display.d.ts.map +0 -1
- package/src/components/media-player-audio.d.ts +0 -9
- package/src/components/media-player-audio.d.ts.map +0 -1
- package/src/components/media-player-controls.d.ts +0 -23
- package/src/components/media-player-controls.d.ts.map +0 -1
- package/src/components/media-player-error.d.ts +0 -16
- package/src/components/media-player-error.d.ts.map +0 -1
- package/src/components/media-player-fullscreen.d.ts +0 -12
- package/src/components/media-player-fullscreen.d.ts.map +0 -1
- package/src/components/media-player-hls.d.ts +0 -23
- package/src/components/media-player-hls.d.ts.map +0 -1
- package/src/components/media-player-loading.d.ts +0 -12
- package/src/components/media-player-loading.d.ts.map +0 -1
- package/src/components/media-player-play.d.ts +0 -11
- package/src/components/media-player-play.d.ts.map +0 -1
- package/src/components/media-player-root.d.ts +0 -28
- package/src/components/media-player-root.d.ts.map +0 -1
- package/src/components/media-player-seek.d.ts +0 -15
- package/src/components/media-player-seek.d.ts.map +0 -1
- package/src/components/media-player-time.d.ts +0 -12
- package/src/components/media-player-time.d.ts.map +0 -1
- package/src/components/media-player-tooltip.d.ts +0 -13
- package/src/components/media-player-tooltip.d.ts.map +0 -1
- package/src/components/media-player-video.d.ts +0 -9
- package/src/components/media-player-video.d.ts.map +0 -1
- package/src/components/media-player-volume.d.ts +0 -13
- package/src/components/media-player-volume.d.ts.map +0 -1
- package/src/components/media-player.d.ts +0 -3
- package/src/components/media-player.d.ts.map +0 -1
- package/src/components/media-suspense.d.ts +0 -78
- package/src/components/media-suspense.d.ts.map +0 -1
- package/src/components/player-settings-form.d.ts +0 -8
- package/src/components/player-settings-form.d.ts.map +0 -1
- package/src/components/react-player-wrapper.d.ts +0 -64
- package/src/components/react-player-wrapper.d.ts.map +0 -1
- package/src/components/simple-video-player.d.ts +0 -9
- package/src/components/simple-video-player.d.ts.map +0 -1
- package/src/components/ui/button.tsx +0 -49
- package/src/components/ui/dropdown-menu.tsx +0 -137
- package/src/components/ui/enhanced-seek-bar.d.ts +0 -3
- package/src/components/ui/enhanced-seek-bar.d.ts.map +0 -1
- package/src/components/ui/fullscreen-button.d.ts +0 -3
- package/src/components/ui/fullscreen-button.d.ts.map +0 -1
- package/src/components/ui/icons.tsx +0 -174
- package/src/components/ui/media-resource-preloader.d.ts +0 -21
- package/src/components/ui/media-resource-preloader.d.ts.map +0 -1
- package/src/components/ui/play-button.d.ts +0 -3
- package/src/components/ui/play-button.d.ts.map +0 -1
- package/src/components/ui/seek-bar.d.ts +0 -3
- package/src/components/ui/seek-bar.d.ts.map +0 -1
- package/src/components/ui/slider.tsx +0 -55
- package/src/components/ui/time-display.d.ts +0 -3
- package/src/components/ui/time-display.d.ts.map +0 -1
- package/src/components/ui/tooltip.tsx +0 -131
- package/src/components/ui/volume-control.d.ts +0 -3
- package/src/components/ui/volume-control.d.ts.map +0 -1
- package/src/components/unified/base-media-player.d.ts +0 -18
- package/src/components/unified/base-media-player.d.ts.map +0 -1
- package/src/components/unified/media-player.d.ts +0 -37
- package/src/components/unified/media-player.d.ts.map +0 -1
- package/src/components/variants/minimal/AccessibleMinimalPlayer.d.ts +0 -42
- package/src/components/variants/minimal/AccessibleMinimalPlayer.d.ts.map +0 -1
- package/src/components/variants/minimal/EnhancedMinimalMediaPlayer.d.ts +0 -44
- package/src/components/variants/minimal/EnhancedMinimalMediaPlayer.d.ts.map +0 -1
- package/src/components/variants/minimal/MinimalControls.d.ts +0 -19
- package/src/components/variants/minimal/MinimalControls.d.ts.map +0 -1
- package/src/components/variants/minimal/MinimalLoading.d.ts +0 -10
- package/src/components/variants/minimal/MinimalLoading.d.ts.map +0 -1
- package/src/components/variants/minimal/MinimalMediaPlayer.d.ts +0 -38
- package/src/components/variants/minimal/MinimalMediaPlayer.d.ts.map +0 -1
- package/src/components/variants/minimal/MinimalOverlay.d.ts +0 -11
- package/src/components/variants/minimal/MinimalOverlay.d.ts.map +0 -1
- package/src/components/variants/minimal/MinimalPlayButton.d.ts +0 -9
- package/src/components/variants/minimal/MinimalPlayButton.d.ts.map +0 -1
- package/src/components/variants/minimal/MinimalSeekBar.d.ts +0 -7
- package/src/components/variants/minimal/MinimalSeekBar.d.ts.map +0 -1
- package/src/components/variants/minimal/MinimalVolumeControl.d.ts +0 -7
- package/src/components/variants/minimal/MinimalVolumeControl.d.ts.map +0 -1
- package/src/components/variants/minimal/SimpleMinimalPlayer.d.ts +0 -22
- package/src/components/variants/minimal/SimpleMinimalPlayer.d.ts.map +0 -1
- package/src/components/variants/minimal/components/CenterPlayButton.d.ts +0 -7
- package/src/components/variants/minimal/components/CenterPlayButton.d.ts.map +0 -1
- package/src/components/variants/minimal/components/ControlBar.d.ts +0 -43
- package/src/components/variants/minimal/components/ControlBar.d.ts.map +0 -1
- package/src/components/variants/minimal/components/EnhancedSettingsMenu.d.ts +0 -24
- package/src/components/variants/minimal/components/EnhancedSettingsMenu.d.ts.map +0 -1
- package/src/components/variants/minimal/components/PlaybackControls.d.ts +0 -9
- package/src/components/variants/minimal/components/PlaybackControls.d.ts.map +0 -1
- package/src/components/variants/minimal/components/RightControls.d.ts +0 -25
- package/src/components/variants/minimal/components/RightControls.d.ts.map +0 -1
- package/src/components/variants/minimal/components/SeekBar.d.ts +0 -11
- package/src/components/variants/minimal/components/SeekBar.d.ts.map +0 -1
- package/src/components/variants/minimal/components/SettingsDropdown.d.ts +0 -9
- package/src/components/variants/minimal/components/SettingsDropdown.d.ts.map +0 -1
- package/src/components/variants/minimal/components/SubtitleDisplay.d.ts +0 -7
- package/src/components/variants/minimal/components/SubtitleDisplay.d.ts.map +0 -1
- package/src/components/variants/minimal/components/TimeDisplay.d.ts +0 -7
- package/src/components/variants/minimal/components/TimeDisplay.d.ts.map +0 -1
- package/src/components/variants/minimal/components/VideoElement.d.ts +0 -13
- package/src/components/variants/minimal/components/VideoElement.d.ts.map +0 -1
- package/src/components/variants/minimal/components/VolumeControl.d.ts +0 -13
- package/src/components/variants/minimal/components/VolumeControl.d.ts.map +0 -1
- package/src/components/variants/minimal/index.d.ts +0 -17
- package/src/components/variants/minimal/index.d.ts.map +0 -1
- package/src/components/video-player.d.ts +0 -3
- package/src/components/video-player.d.ts.map +0 -1
- package/src/context/error-handling.d.ts +0 -72
- package/src/context/error-handling.d.ts.map +0 -1
- package/src/context/media-context.d.ts +0 -104
- package/src/context/media-context.d.ts.map +0 -1
- package/src/context/media-provider.d.ts +0 -26
- package/src/context/media-provider.d.ts.map +0 -1
- package/src/context/media-store.d.ts +0 -33
- package/src/context/media-store.d.ts.map +0 -1
- package/src/context/persistence.d.ts +0 -83
- package/src/context/persistence.d.ts.map +0 -1
- package/src/core/events/event-system.d.ts +0 -170
- package/src/core/events/event-system.d.ts.map +0 -1
- package/src/core/events/hooks.d.ts +0 -33
- package/src/core/events/hooks.d.ts.map +0 -1
- package/src/core/events/index.d.ts +0 -6
- package/src/core/events/index.d.ts.map +0 -1
- package/src/core/events/middleware.d.ts +0 -39
- package/src/core/events/middleware.d.ts.map +0 -1
- package/src/core/index.d.ts +0 -8
- package/src/core/index.d.ts.map +0 -1
- package/src/core/optimization/bundle-optimizer.d.ts +0 -44
- package/src/core/optimization/bundle-optimizer.d.ts.map +0 -1
- package/src/core/performance/cicd.d.ts +0 -8
- package/src/core/performance/cicd.d.ts.map +0 -1
- package/src/core/performance/index.d.ts +0 -10
- package/src/core/performance/index.d.ts.map +0 -1
- package/src/core/performance/media-loading-optimizer.d.ts +0 -105
- package/src/core/performance/media-loading-optimizer.d.ts.map +0 -1
- package/src/core/performance/performance-budgets.d.ts +0 -68
- package/src/core/performance/performance-budgets.d.ts.map +0 -1
- package/src/core/performance/performance-monitor.d.ts +0 -95
- package/src/core/performance/performance-monitor.d.ts.map +0 -1
- package/src/core/performance/performance-testing.d.ts +0 -69
- package/src/core/performance/performance-testing.d.ts.map +0 -1
- package/src/core/plugins/base-plugin.d.ts +0 -52
- package/src/core/plugins/base-plugin.d.ts.map +0 -1
- package/src/core/plugins/enhanced-plugin-system.d.ts +0 -160
- package/src/core/plugins/enhanced-plugin-system.d.ts.map +0 -1
- package/src/core/plugins/examples/analytics-plugin.d.ts +0 -30
- package/src/core/plugins/examples/analytics-plugin.d.ts.map +0 -1
- package/src/core/plugins/index.d.ts +0 -8
- package/src/core/plugins/index.d.ts.map +0 -1
- package/src/core/plugins/registry.d.ts +0 -31
- package/src/core/plugins/registry.d.ts.map +0 -1
- package/src/core/plugins/types.d.ts +0 -101
- package/src/core/plugins/types.d.ts.map +0 -1
- package/src/core/plugins/utils.d.ts +0 -38
- package/src/core/plugins/utils.d.ts.map +0 -1
- package/src/core/progressive-loading.d.ts +0 -88
- package/src/core/progressive-loading.d.ts.map +0 -1
- package/src/core/providers/enhanced-hls-provider.d.ts +0 -50
- package/src/core/providers/enhanced-hls-provider.d.ts.map +0 -1
- package/src/core/providers/service-provider.d.ts +0 -49
- package/src/core/providers/service-provider.d.ts.map +0 -1
- package/src/core/utils.d.ts +0 -25
- package/src/core/utils.d.ts.map +0 -1
- package/src/features/media-session/media-session-manager.d.ts +0 -132
- package/src/features/media-session/media-session-manager.d.ts.map +0 -1
- package/src/features/picture-in-picture/pip-manager.d.ts +0 -94
- package/src/features/picture-in-picture/pip-manager.d.ts.map +0 -1
- package/src/features/playlist/playlist-manager.d.ts +0 -208
- package/src/features/playlist/playlist-manager.d.ts.map +0 -1
- package/src/features/subtitles/subtitle-manager.d.ts +0 -136
- package/src/features/subtitles/subtitle-manager.d.ts.map +0 -1
- package/src/features/subtitles/subtitle-parser.d.ts +0 -60
- package/src/features/subtitles/subtitle-parser.d.ts.map +0 -1
- package/src/features/thumbnails/thumbnail-generator.d.ts +0 -136
- package/src/features/thumbnails/thumbnail-generator.d.ts.map +0 -1
- package/src/hooks/accessibility/index.d.ts +0 -5
- package/src/hooks/accessibility/index.d.ts.map +0 -1
- package/src/hooks/accessibility/use-accessibility-preferences.d.ts +0 -14
- package/src/hooks/accessibility/use-accessibility-preferences.d.ts.map +0 -1
- package/src/hooks/accessibility/use-focus-management.d.ts +0 -31
- package/src/hooks/accessibility/use-focus-management.d.ts.map +0 -1
- package/src/hooks/accessibility/use-keyboard-shortcuts.d.ts +0 -38
- package/src/hooks/accessibility/use-keyboard-shortcuts.d.ts.map +0 -1
- package/src/hooks/accessibility/use-screen-reader.d.ts +0 -22
- package/src/hooks/accessibility/use-screen-reader.d.ts.map +0 -1
- package/src/hooks/core/index.d.ts +0 -18
- package/src/hooks/core/index.d.ts.map +0 -1
- package/src/hooks/legacy.d.ts +0 -18
- package/src/hooks/legacy.d.ts.map +0 -1
- package/src/hooks/use-enhanced-media-player.d.ts +0 -88
- package/src/hooks/use-enhanced-media-player.d.ts.map +0 -1
- package/src/hooks/use-intelligent-preloading.d.ts +0 -66
- package/src/hooks/use-intelligent-preloading.d.ts.map +0 -1
- package/src/hooks/use-keyboard-controls.d.ts +0 -13
- package/src/hooks/use-keyboard-controls.d.ts.map +0 -1
- package/src/hooks/use-media-actions.d.ts +0 -62
- package/src/hooks/use-media-actions.d.ts.map +0 -1
- package/src/hooks/use-media-metadata.d.ts +0 -11
- package/src/hooks/use-media-metadata.d.ts.map +0 -1
- package/src/hooks/use-media-optimistic.d.ts +0 -36
- package/src/hooks/use-media-optimistic.d.ts.map +0 -1
- package/src/hooks/use-media-player.d.ts +0 -31
- package/src/hooks/use-media-player.d.ts.map +0 -1
- package/src/hooks/use-media-state.d.ts +0 -17
- package/src/hooks/use-media-state.d.ts.map +0 -1
- package/src/hooks/use-memory-optimization.d.ts +0 -40
- package/src/hooks/use-memory-optimization.d.ts.map +0 -1
- package/src/hooks/use-mobile.ts +0 -125
- package/src/hooks/use-optimistic-controls.d.ts +0 -22
- package/src/hooks/use-optimistic-controls.d.ts.map +0 -1
- package/src/hooks/use-optimized-media.d.ts +0 -46
- package/src/hooks/use-optimized-media.d.ts.map +0 -1
- package/src/hooks/use-touch-gestures.d.ts +0 -47
- package/src/hooks/use-touch-gestures.d.ts.map +0 -1
- package/src/hooks/useEnhancedSubtitles.d.ts +0 -39
- package/src/hooks/useEnhancedSubtitles.d.ts.map +0 -1
- package/src/hooks/useKeyboardShortcuts.d.ts +0 -10
- package/src/hooks/useKeyboardShortcuts.d.ts.map +0 -1
- package/src/hooks/useMediaControls.d.ts +0 -9
- package/src/hooks/useMediaControls.d.ts.map +0 -1
- package/src/hooks/useScreenshot.d.ts +0 -4
- package/src/hooks/useScreenshot.d.ts.map +0 -1
- package/src/hooks/useSubtitles.d.ts +0 -8
- package/src/hooks/useSubtitles.d.ts.map +0 -1
- package/src/hooks/useVideoPlayer.d.ts +0 -32
- package/src/hooks/useVideoPlayer.d.ts.map +0 -1
- package/src/icons/components/FullscreenIcon.d.ts +0 -3
- package/src/icons/components/FullscreenIcon.d.ts.map +0 -1
- package/src/icons/components/SettingsIcon.d.ts +0 -3
- package/src/icons/components/SettingsIcon.d.ts.map +0 -1
- package/src/icons/components/animated/LoadingIcon.d.ts +0 -3
- package/src/icons/components/animated/LoadingIcon.d.ts.map +0 -1
- package/src/icons/components/animated/PlayPauseIcon.d.ts +0 -7
- package/src/icons/components/animated/PlayPauseIcon.d.ts.map +0 -1
- package/src/icons/components/media/PauseIcon.d.ts +0 -3
- package/src/icons/components/media/PauseIcon.d.ts.map +0 -1
- package/src/icons/components/media/PlayIcon.d.ts +0 -3
- package/src/icons/components/media/PlayIcon.d.ts.map +0 -1
- package/src/icons/components/volume/VolumeIcon.d.ts +0 -3
- package/src/icons/components/volume/VolumeIcon.d.ts.map +0 -1
- package/src/icons/components/volume/VolumeOffIcon.d.ts +0 -3
- package/src/icons/components/volume/VolumeOffIcon.d.ts.map +0 -1
- package/src/icons/index.d.ts +0 -28
- package/src/icons/index.d.ts.map +0 -1
- package/src/icons/provider.d.ts +0 -13
- package/src/icons/provider.d.ts.map +0 -1
- package/src/icons/types.d.ts +0 -18
- package/src/icons/types.d.ts.map +0 -1
- package/src/index-enhanced.d.ts +0 -13
- package/src/index-enhanced.d.ts.map +0 -1
- package/src/index-legacy.d.ts +0 -81
- package/src/index-legacy.d.ts.map +0 -1
- package/src/index.d.ts +0 -38
- package/src/index.d.ts.map +0 -1
- package/src/index.minimal.d.ts +0 -2
- package/src/index.minimal.d.ts.map +0 -1
- package/src/index.minimal.ts +0 -4
- package/src/lib/deprecation.d.ts +0 -7
- package/src/lib/deprecation.d.ts.map +0 -1
- package/src/lib/format-time.d.ts +0 -9
- package/src/lib/format-time.d.ts.map +0 -1
- package/src/lib/index.d.ts +0 -3
- package/src/lib/index.d.ts.map +0 -1
- package/src/lib/utils.d.ts +0 -3
- package/src/lib/utils.d.ts.map +0 -1
- package/src/test/setup.d.ts +0 -2
- package/src/test/setup.d.ts.map +0 -1
- package/src/types/events.d.ts +0 -41
- package/src/types/events.d.ts.map +0 -1
- package/src/types/formats.d.ts +0 -45
- package/src/types/formats.d.ts.map +0 -1
- package/src/types/index.d.ts +0 -128
- package/src/types/index.d.ts.map +0 -1
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
"use strict";const s=require("react"),A=require("./context-eNS62_ac.cjs"),le=require("./utils-CFOue_9K.cjs");function be(e){const t=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(e){for(const n in e)if(n!=="default"){const a=Object.getOwnPropertyDescriptor(e,n);Object.defineProperty(t,n,a.get?a:{enumerable:!0,get:()=>e[n]})}}return t.default=e,Object.freeze(t)}const j=be(s);function $(e,t){return((n,a=!1)=>{const m={type:e,detail:n,optimistic:a,timestamp:Date.now()};return a?t.dispatchOptimistic(m):(t.dispatch(m),Promise.resolve())})}function de(e){const[t,n]=s.useState(e.getActionState());return s.useEffect(()=>e.subscribe(()=>{const m=e.getActionState();n(l=>JSON.stringify(l)!==JSON.stringify(m)?m:l)}),[e]),t}function me(e){const t=s.useMemo(()=>({play:$(A.MediaActionTypes.PLAY,e),pause:$(A.MediaActionTypes.PAUSE,e),seek:$(A.MediaActionTypes.SEEK,e),setVolume:$(A.MediaActionTypes.SET_VOLUME,e),mute:$(A.MediaActionTypes.MUTE,e),unmute:$(A.MediaActionTypes.UNMUTE,e),toggleMute:$(A.MediaActionTypes.TOGGLE_MUTE,e),setDuration:$(A.MediaActionTypes.SET_DURATION,e),setCurrentTime:$(A.MediaActionTypes.SET_CURRENT_TIME,e),setBuffered:$(A.MediaActionTypes.SET_BUFFERED,e),setLoading:$(A.MediaActionTypes.SET_LOADING,e),setError:$(A.MediaActionTypes.SET_ERROR,e),enterFullscreen:$(A.MediaActionTypes.ENTER_FULLSCREEN,e),exitFullscreen:$(A.MediaActionTypes.EXIT_FULLSCREEN,e),enterPiP:$(A.MediaActionTypes.ENTER_PIP,e),exitPiP:$(A.MediaActionTypes.EXIT_PIP,e),setPlaybackRate:$(A.MediaActionTypes.SET_PLAYBACK_RATE,e),setSubtitleTrack:$(A.MediaActionTypes.SET_SUBTITLE_TRACK,e),setRendition:$(A.MediaActionTypes.SET_RENDITION,e),toggleSubtitles:$(A.MediaActionTypes.TOGGLE_SUBTITLES,e),previewTime:$(A.MediaActionTypes.PREVIEW_TIME,e),clearPreview:$(A.MediaActionTypes.CLEAR_PREVIEW,e)}),[e]),n=de(e),a=s.useMemo(()=>({togglePlayPause:async l=>{l?await t.pause(!0):await t.play(!0)},seekWithPreview:async l=>{await t.previewTime(l,!0),await t.seek(l,!0)},adjustVolume:async(l,i)=>{const d=Math.max(0,Math.min(1,i+l));await t.setVolume(d,!0)},toggleFullscreenOptimistic:async l=>{l?await t.exitFullscreen(!0):await t.enterFullscreen(!0)}}),[t]),m=s.useCallback(async()=>{const{lastAction:l}=n;l&&n.error&&await e.dispatchOptimistic({...l,retryCount:(l.retryCount||0)+1})},[e,n]);return{...t,...a,actionState:n,retryLastAction:m,isLoading:n.pending,hasError:!!n.error,errorMessage:n.error,retryCount:n.retryCount}}function ye(e,t){if(!t.optimistic)return e;switch(t.type){case"PLAY":return{...e,isPlaying:!0,error:null};case"PAUSE":return{...e,isPlaying:!1};case"SEEK":return{...e,currentTime:t.detail};case"SET_VOLUME":return{...e,volume:Math.max(0,Math.min(1,t.detail))};case"MUTE":return{...e,isMuted:!0};case"UNMUTE":return{...e,isMuted:!1};case"TOGGLE_MUTE":return{...e,isMuted:!e.isMuted};case"ENTER_FULLSCREEN":return{...e,isFullscreen:!0};case"EXIT_FULLSCREEN":return{...e,isFullscreen:!1};case"SET_PLAYBACK_RATE":return{...e,playbackRate:t.detail};case"TOGGLE_SUBTITLES":return{...e,subtitlesShowing:!e.subtitlesShowing};case"PREVIEW_TIME":return{...e,previewTime:t.detail};case"CLEAR_PREVIEW":return{...e,previewTime:null,previewImage:null,previewCoords:null};default:return e}}function we(e){const t=s.useSyncExternalStore(e.subscribe,e.getState,e.getState),[n,a]=s.useOptimistic(t,ye),m=s.useCallback(async d=>{d.optimistic&&a(d),await e.dispatchOptimistic(d)},[e,a]),l=s.useMemo(()=>({togglePlayPause:async()=>{const d={type:n.isPlaying?"PAUSE":"PLAY",optimistic:!0,timestamp:Date.now()};await m(d)},setVolumeOptimistic:async d=>{const E={type:"SET_VOLUME",detail:Math.max(0,Math.min(1,d)),optimistic:!0,timestamp:Date.now()};await m(E)},seekOptimistic:async d=>{const E={type:"SEEK",detail:d,optimistic:!0,timestamp:Date.now()};await m(E)},toggleMuteOptimistic:async()=>{const d={type:"TOGGLE_MUTE",optimistic:!0,timestamp:Date.now()};await m(d)},toggleFullscreenOptimistic:async()=>{const d={type:n.isFullscreen?"EXIT_FULLSCREEN":"ENTER_FULLSCREEN",optimistic:!0,timestamp:Date.now()};await m(d)},setPlaybackRateOptimistic:async d=>{const E={type:"SET_PLAYBACK_RATE",detail:d,optimistic:!0,timestamp:Date.now()};await m(E)},toggleSubtitlesOptimistic:async()=>{const d={type:"TOGGLE_SUBTITLES",optimistic:!0,timestamp:Date.now()};await m(d)}}),[n,m]),i=s.useMemo(()=>({isPlaying:n.isPlaying,currentTime:n.currentTime,volume:n.volume,isMuted:n.isMuted,isFullscreen:n.isFullscreen,playbackRate:n.playbackRate,subtitlesShowing:n.subtitlesShowing,previewTime:n.previewTime,progress:n.duration>0?n.currentTime/n.duration:0,formattedTime:se(n.currentTime),formattedDuration:se(n.duration),canPlay:!n.isLoading&&!n.error,hasError:!!n.error,isBuffering:n.isLoading}),[n]);return{state:n,actualState:t,...i,...l,dispatchOptimistic:m}}function se(e){if(!e||!isFinite(e))return"0:00";const t=Math.floor(e/60),n=Math.floor(e%60),a=Math.floor(t/60);return a>0?`${a}:${String(t%60).padStart(2,"0")}:${String(n).padStart(2,"0")}`:`${t}:${String(n).padStart(2,"0")}`}function ae(e,t){if(!Number.isFinite(t))return console.warn(`Attempted to set non-finite currentTime: ${t}`),!1;if(t<0)return console.warn(`Attempted to set negative currentTime: ${t}`),!1;try{return e.currentTime=t,!0}catch(n){return console.error(`Failed to set currentTime to ${t}:`,n),!1}}function Ee(e){const t=s.useRef(null),n=s.useRef(null),[a,m]=s.useTransition(),[l,i]=s.useTransition();s.useRef(0);const d=s.useRef(0),E=s.useRef(0);s.useRef(void 0);const M=s.useRef(0),L=A.useMediaStore(),y="getOptimisticState"in L,r=A.useMediaSelector(w=>w.isPlaying),v=A.useMediaSelector(w=>w.currentTime),f=A.useMediaSelector(w=>w.duration),o=A.useMediaSelector(w=>w.volume),p=A.useMediaSelector(w=>w.isMuted),P=A.useMediaSelector(w=>w.isLoading),h=A.useMediaSelector(w=>w.isBuffering),c=A.useMediaSelector(w=>w.error),T=A.useMediaSelector(w=>w.buffered),g=A.useMediaSelector(w=>w.isFullscreen),S=L,k=we(S),b=me(S),[B,F]=s.useState({frameRate:0,averageRenderTime:0,droppedFrames:0,bufferHealth:0}),[I,D]=s.useOptimistic(o,(w,U)=>Math.max(0,Math.min(1,U)));s.useOptimistic(v,(w,U)=>Math.max(0,Math.min(f||0,U))),s.useEffect(()=>{const w=t.current;if(!w)return;const U={volume:e.volume,muted:e.muted,autoplay:e.autoPlay,loop:e.loop,preload:e.preload,crossOrigin:e.crossOrigin};Object.entries(U).forEach(([G,W])=>{W!==void 0&&(w[G]=W)}),w.setAttribute("preload",e.preloadStrategy==="eager"?"auto":"metadata"),e.bufferingStrategy==="aggressive"&&w.setAttribute("buffered","auto"),w instanceof HTMLVideoElement&&(w.style.willChange="transform",w.style.transform="translateZ(0)")},[e.volume,e.muted,e.autoPlay,e.loop,e.preload,e.crossOrigin,e.preloadStrategy,e.bufferingStrategy]);const C=s.useCallback(()=>{const w=t.current;if(!w)return;const U=performance.now();if(e.enableTimeUpdateThrottling!==!1){if(U-M.current<(e.timeUpdateThrottleMs||100))return;M.current=U}m(()=>{y&&b&&b.setCurrentTime(w.currentTime)})},[e.enableTimeUpdateThrottling,e.timeUpdateThrottleMs,y,b]),R=s.useCallback(()=>{m(()=>{y&&b&&b.play(!0)}),e.onPlay?.()},[y,b,e.onPlay]),V=s.useCallback(()=>{m(()=>{y&&b&&b.pause(!0)}),e.onPause?.()},[y,b,e.onPause]),N=s.useCallback(()=>{const w=t.current;w&&m(()=>{y&&b&&(b.setVolume(w.volume,!0),w.muted?b.mute(!0):b.unmute(!0))})},[y,b]),x=s.useCallback(()=>{i(()=>{})},[]),Q=s.useCallback(()=>{},[]),u=s.useCallback(()=>{const w=t.current;w&&m(()=>{y&&b&&b.setBuffered(w.buffered)})},[y,b]),_=s.useCallback(()=>{const w=performance.now();if(w-E.current>0&&(d.current++,d.current>=60)){const G=Math.round(d.current*1e3/(w-E.current));F(W=>({...W,frameRate:G,droppedFrames:Math.max(0,60-G)})),d.current=0,E.current=w}},[]);s.useEffect(()=>{const w=t.current;if(!w)return;const U=[{event:"timeupdate",handler:C,passive:!0},{event:"play",handler:R},{event:"pause",handler:V},{event:"volumechange",handler:N},{event:"seeking",handler:x},{event:"seeked",handler:Q},{event:"progress",handler:u,passive:!0},{event:"loadedmetadata",handler:()=>_()},{event:"loadeddata",handler:()=>_()}];U.forEach(({event:Z,handler:J,passive:ee})=>{const te=ee?{passive:!0}:{};w.addEventListener(Z,J,te)});let G;const W=()=>{_(),G=requestAnimationFrame(W)};return e.enablePerformanceMonitoring&&W(),()=>{U.forEach(({event:Z,handler:J})=>{w.removeEventListener(Z,J)}),G&&cancelAnimationFrame(G)}},[C,R,V,N,x,Q,u,_,e.enablePerformanceMonitoring]);const z=s.useMemo(()=>{const w=async()=>{const O=t.current;if(O)if(y&&b)await b.play(!0);else try{await O.play()}catch(H){console.error("Failed to play media:",H)}},U=()=>{const O=t.current;O&&(y&&b?b.pause(!0):O.pause())},G=()=>{r?U():w()},W=O=>{const H=t.current;if(!H)return;const q=Number.isFinite(f)&&f>0?f:Number.isFinite(H.duration)?H.duration:0;if(q===0){console.warn("Cannot seek: duration is not available");return}const Y=Math.max(0,Math.min(O,q));if(!Number.isFinite(Y)){console.warn(`Computed non-finite seek time: ${Y}`);return}y&&b?i(()=>{b.seek(Y,!0)}):ae(H,Y)},Z=O=>{const H=t.current;if(!H)return;const q=Math.max(0,Math.min(1,O));y&&b?(D(q),m(()=>{b.setVolume(q,!0)})):H.volume=q},J=()=>{const O=t.current;O&&(y&&b?b.toggleMute(!0):O.muted=!O.muted)},ee=async()=>{const O=n.current;if(!(!O||!document.fullscreenEnabled))try{await O.requestFullscreen(),y&&b&&b.enterFullscreen(!0)}catch(H){console.error("Failed to enter fullscreen:",H)}},te=async()=>{if(document.fullscreenElement)try{await document.exitFullscreen(),y&&b&&b.exitFullscreen(!0)}catch(O){console.error("Failed to exit fullscreen:",O)}};return{play:w,pause:U,toggle:G,seek:W,setCurrentTime:O=>{const H=t.current;if(!H)return;const q=Number.isFinite(f)&&f>0?f:Number.isFinite(H.duration)?H.duration:0;if(q===0){console.warn("Cannot set currentTime: duration is not available");return}const Y=Math.max(0,Math.min(O,q));if(!Number.isFinite(Y)){console.warn(`Computed non-finite currentTime: ${Y}`);return}ae(H,Y)},setVolume:Z,mute:()=>{const O=t.current;O&&(y&&b?b.mute(!0):O.muted=!0)},unmute:()=>{const O=t.current;O&&(y&&b?b.unmute(!0):O.muted=!1)},toggleMute:J,enterFullscreen:ee,exitFullscreen:te,toggleFullscreen:async()=>{g?await te():await ee()}}},[r,g,f,y,b,m,i,D]),X=s.useMemo(()=>({isPlaying:k?.isPlaying??r,currentTime:k?.currentTime??v,duration:k?.actualState?.duration??f,volume:k?.volume??I,isMuted:k?.isMuted??p,isLoading:k?.isBuffering??P,isBuffering:k?.isBuffering??h,error:k?.actualState?.error??c,buffered:k?.actualState?.buffered??T,isFullscreen:k?.isFullscreen??g,progress:f>0?v/f:0,isTransitioning:a||l,canPlay:!P&&!h&&!c}),[k,r,v,f,I,p,P,h,c,T,g,a,l]);return{mediaRef:t,containerRef:n,state:X,actualState:k?.actualState,controls:z,performanceMetrics:B,isTransitioning:a||l,actions:k,actionState:k,optimisticState:k,isEnhanced:y}}function fe({enabled:e=!0,state:t,controls:n,seekStep:a=10,volumeStep:m=.1}){const l=i=>{if(!e)return;const d=i.target;if(!(d.tagName==="INPUT"||d.tagName==="TEXTAREA"||d.contentEditable==="true"))switch(i.code){case"Space":case"KeyK":i.preventDefault(),n.toggle();break;case"KeyM":i.preventDefault(),n.toggleMute();break;case"KeyF":i.preventDefault(),n.toggleFullscreen();break;case"ArrowLeft":i.preventDefault(),n.seek(Math.max(0,t.currentTime-a));break;case"ArrowRight":i.preventDefault(),n.seek(Math.min(t.duration,t.currentTime+a));break;case"ArrowUp":i.preventDefault(),n.setVolume(Math.min(1,t.volume+m));break;case"ArrowDown":i.preventDefault(),n.setVolume(Math.max(0,t.volume-m));break;case"Digit0":case"Digit1":case"Digit2":case"Digit3":case"Digit4":case"Digit5":case"Digit6":case"Digit7":case"Digit8":case"Digit9":i.preventDefault();const M=parseInt(i.code.replace("Digit",""),10)/10;n.seek(t.duration*M);break;case"Home":i.preventDefault(),n.seek(0);break;case"End":i.preventDefault(),n.seek(t.duration);break}};return s.useEffect(()=>{if(e)return document.addEventListener("keydown",l),()=>{document.removeEventListener("keydown",l)}},[e,l]),{handleKeyDown:l}}const Se=Object.freeze(Object.defineProperty({__proto__:null,useKeyboardControls:fe},Symbol.toStringTag,{value:"Module"}));function ke(e={}){const{maxMemoryUsage:t=100,cleanupInterval:n=3e4,enableGC:a=!0,monitorMemory:m=!0}=e;s.useRef(void 0);const l=s.useRef(new Set),i=s.useRef(new Map),d=s.useRef(new Set),E=s.useRef(new Set),M=s.useCallback(()=>{if(typeof window>"u"||!("memory"in performance))return{used:0,total:0,limit:0};const h=performance.memory;return{used:h.usedJSHeapSize,total:h.totalJSHeapSize,limit:h.jsHeapSizeLimit}},[]),[L,y]=s.useState({used:0,total:0,limit:0,usage:0,isHighUsage:!1}),r=s.useCallback(()=>{d.current.forEach(h=>{clearTimeout(h)}),d.current.clear(),E.current.forEach(h=>{cancelAnimationFrame(h)}),E.current.clear(),l.current.forEach(h=>{h.disconnect()}),l.current.clear(),i.current.forEach((h,c)=>{h.forEach(({event:T,handler:g})=>{c.removeEventListener(T,g)})}),i.current.clear(),typeof window<"u"&&"gc"in window&&window.gc()},[]),v=s.useCallback((h,c)=>{const T=globalThis.setInterval(h,c);return d.current.add(T),()=>{globalThis.clearInterval(T),d.current.delete(T)}},[]);s.useEffect(()=>{if(!m)return;const h=()=>{const c=M(),T=c.used/1024/1024,g=T>t;y({...c,usage:T,isHighUsage:g}),g&&a&&r()};return h(),v(h,n)},[m,M,t,a,n,r]);const f=s.useCallback((h,c,T,g)=>(h.addEventListener(c,T,g),i.current.has(h)||i.current.set(h,[]),i.current.get(h).push({event:c,handler:T}),()=>{h.removeEventListener(c,T);const S=i.current.get(h);if(S){const k=S.findIndex(b=>b.event===c&&b.handler===T);k>-1&&S.splice(k,1),S.length===0&&i.current.delete(h)}}),[]),o=s.useCallback((h,c)=>{const T=globalThis.setTimeout(h,c);return d.current.add(T),()=>{globalThis.clearTimeout(T),d.current.delete(T)}},[]),p=s.useCallback(h=>{const c=globalThis.requestAnimationFrame(h);return E.current.add(c),()=>{globalThis.cancelAnimationFrame(c),E.current.delete(c)}},[]),P=s.useCallback(h=>(l.current.add(h),()=>{h.disconnect(),l.current.delete(h)}),[]);return s.useEffect(()=>()=>{r()},[r]),{memoryStats:L,getMemoryUsage:M,performCleanup:r,addEventListener:f,setInterval:v,setTimeout:o,requestAnimationFrame:p,addObserver:P,formatBytes:h=>{if(h===0)return"0 Bytes";const c=1024,T=["Bytes","KB","MB","GB"],g=Math.floor(Math.log(h)/Math.log(c));return parseFloat((h/Math.pow(c,g)).toFixed(2))+" "+T[g]}}}function he(){const[e,t]=s.useState({isPlaying:!1,currentTime:0,duration:0,volume:1,isMuted:!1,isLoading:!1,isFullscreen:!1,error:null,buffered:null}),n=r=>{t(v=>({...v,...r}))};return{state:e,updateState:n,setPlaying:r=>{n({isPlaying:r})},setCurrentTime:r=>{n({currentTime:r})},setDuration:r=>{n({duration:r})},setVolume:r=>{n({volume:Math.max(0,Math.min(1,r))})},setMuted:r=>{n({isMuted:r})},setLoading:r=>{n({isLoading:r})},setFullscreen:r=>{n({isFullscreen:r})},setError:r=>{n({error:r})},setBuffered:r=>{n({buffered:r})}}}function Me(e,t){if(!Number.isFinite(t))return console.warn(`Attempted to set non-finite currentTime: ${t}`),!1;if(t<0)return console.warn(`Attempted to set negative currentTime: ${t}`),!1;try{return e.currentTime=t,!0}catch(n){return console.error(`Failed to set currentTime to ${t}:`,n),!1}}function pe(e){const t=s.useRef(null),n=s.useRef(null),{state:a,setPlaying:m,setCurrentTime:l,setDuration:i,setVolume:d,setMuted:E,setLoading:M,setFullscreen:L,setError:y,setBuffered:r}=he();s.useEffect(()=>{const u=t.current;u&&(e.volume!==void 0&&(u.volume=e.volume,d(e.volume)),e.muted!==void 0&&(u.muted=e.muted,E(e.muted)),e.autoPlay!==void 0&&(u.autoplay=e.autoPlay),e.loop!==void 0&&(u.loop=e.loop),e.preload!==void 0&&(u.preload=e.preload),e.crossOrigin!==void 0&&(u.crossOrigin=e.crossOrigin))},[e,d,E]);const v=s.useCallback(()=>{m(!0),e.onPlay?.()},[m,e]),f=s.useCallback(()=>{m(!1),e.onPause?.()},[m,e]),o=s.useCallback(()=>{const u=t.current;u&&(l(u.currentTime),e.onTimeUpdate?.(u.currentTime))},[l,e]),p=s.useCallback(()=>{const u=t.current;u&&(i(u.duration),e.onDurationChange?.(u.duration))},[i,e]),P=s.useCallback(()=>{const u=t.current;u&&(d(u.volume),E(u.muted),e.onVolumeChange?.(u.volume))},[d,E,e]),h=s.useCallback(()=>{M(!0),y(null),e.onLoadStart?.()},[M,y,e]),c=s.useCallback(()=>{M(!1),e.onLoadedData?.()},[M,e]),T=s.useCallback(()=>{const u=t.current;if(!u)return;const _=u.error?.message||"An error occurred while loading the media";y(_),M(!1),e.onError?.(_)},[y,M,e]),g=s.useCallback(()=>{m(!1),e.onEnded?.()},[m,e]),S=s.useCallback(()=>{const u=t.current;u&&r(u.buffered)},[r]);s.useEffect(()=>{const u=t.current;if(u)return u.addEventListener("play",v),u.addEventListener("pause",f),u.addEventListener("timeupdate",o),u.addEventListener("durationchange",p),u.addEventListener("volumechange",P),u.addEventListener("loadstart",h),u.addEventListener("loadeddata",c),u.addEventListener("error",T),u.addEventListener("ended",g),u.addEventListener("progress",S),()=>{u.removeEventListener("play",v),u.removeEventListener("pause",f),u.removeEventListener("timeupdate",o),u.removeEventListener("durationchange",p),u.removeEventListener("volumechange",P),u.removeEventListener("loadstart",h),u.removeEventListener("loadeddata",c),u.removeEventListener("error",T),u.removeEventListener("ended",g),u.removeEventListener("progress",S)}},[v,f,o,p,P,h,c,T,g,S]);const k=s.useCallback(async()=>{const u=t.current;if(u)try{await u.play()}catch(_){console.error("Failed to play media:",_),y("Failed to play media")}},[y]),b=s.useCallback(()=>{const u=t.current;u&&u.pause()},[]),B=s.useCallback(()=>{a.isPlaying?b():k()},[a.isPlaying,b,k]),F=s.useCallback(u=>{const _=t.current;if(!_)return;const z=Number.isFinite(_.duration)?_.duration:0;if(z===0){console.warn("Cannot seek: duration is not available");return}const X=Math.max(0,Math.min(u,z));Me(_,X)},[]),I=s.useCallback(u=>{const _=t.current;if(!_)return;const z=Math.max(0,Math.min(1,u));_.volume=z},[]),D=s.useCallback(()=>{const u=t.current;u&&(u.muted=!0)},[]),C=s.useCallback(()=>{const u=t.current;u&&(u.muted=!1)},[]),R=s.useCallback(()=>{const u=t.current;u&&(u.muted=!u.muted)},[]),V=s.useCallback(async()=>{const u=n.current;if(!(!u||!document.fullscreenEnabled))try{await u.requestFullscreen(),L(!0)}catch(_){console.error("Failed to enter fullscreen:",_)}},[L]),N=s.useCallback(async()=>{if(document.fullscreenElement)try{await document.exitFullscreen(),L(!1)}catch(u){console.error("Failed to exit fullscreen:",u)}},[L]),x=s.useCallback(()=>{document.fullscreenElement?N():V()},[N,V]);return s.useEffect(()=>{const u=()=>{L(!!document.fullscreenElement)};return document.addEventListener("fullscreenchange",u),()=>{document.removeEventListener("fullscreenchange",u)}},[L]),{state:a,controls:{play:k,pause:b,toggle:B,seek:F,setCurrentTime:F,setVolume:I,mute:D,unmute:C,toggleMute:R,enterFullscreen:V,exitFullscreen:N,toggleFullscreen:x},mediaRef:t,containerRef:n}}const K={mobile:768,desktop:1280};function ie(){if(typeof window>"u")return"unknown";const e=window.navigator.userAgent.toLowerCase();return/iphone|ipad|ipod/.test(e)?"ios":/android/.test(e)?"android":/windows|mac|linux/.test(e)?"desktop":"unknown"}function oe(){return typeof window>"u"?!1:"ontouchstart"in window||navigator.maxTouchPoints>0||navigator.msMaxTouchPoints>0}function ce(){return typeof window>"u"?!1:"vibrate"in navigator||"vibration"in navigator||"ondevicemotion"in window}function ne(){const[e,t]=j.useState(()=>{if(typeof window>"u")return{isMobile:!1,isTablet:!1,isDesktop:!0,isTouchDevice:!1,platform:"unknown",supportsHaptics:!1,screenSize:{width:1920,height:1080},orientation:"landscape"};const n=window.innerWidth,a=window.innerHeight;return{isMobile:n<K.mobile,isTablet:n>=K.mobile&&n<K.desktop,isDesktop:n>=K.desktop,isTouchDevice:oe(),platform:ie(),supportsHaptics:ce(),screenSize:{width:n,height:a},orientation:n>a?"landscape":"portrait"}});return j.useEffect(()=>{const n=()=>{const i=window.innerWidth,d=window.innerHeight;t({isMobile:i<K.mobile,isTablet:i>=K.mobile&&i<K.desktop,isDesktop:i>=K.desktop,isTouchDevice:oe(),platform:ie(),supportsHaptics:ce(),screenSize:{width:i,height:d},orientation:i>d?"landscape":"portrait"})};window.addEventListener("resize",n),window.addEventListener("orientationchange",n);const a=window.matchMedia(`(max-width: ${K.mobile-1}px)`),m=window.matchMedia(`(min-width: ${K.mobile}px) and (max-width: ${K.desktop-1}px)`),l=window.matchMedia(`(min-width: ${K.desktop}px)`);return a.addEventListener("change",n),m.addEventListener("change",n),l.addEventListener("change",n),()=>{window.removeEventListener("resize",n),window.removeEventListener("orientationchange",n),a.removeEventListener("change",n),m.removeEventListener("change",n),l.removeEventListener("change",n)}},[]),e}function Le(){const{platform:e,isMobile:t}=ne();j.useEffect(()=>{if(t){if(e==="ios"){const n=a=>{a.touches.length>1&&a.preventDefault()};return document.addEventListener("touchstart",n,{passive:!1}),document.body.style.webkitOverflowScrolling="touch",()=>{document.removeEventListener("touchstart",n)}}e==="android"&&(document.body.style.touchAction="manipulation"),document.documentElement.style.setProperty("--webkit-transform","translateZ(0)"),document.documentElement.style.setProperty("--transform","translateZ(0)")}},[e,t])}function Ce(){const{supportsHaptics:e}=ne();return{triggerHaptic:j.useCallback((n="light")=>{if(!e)return;const m={light:[10],medium:[20],heavy:[30],success:[10,10,10],warning:[20,20],error:[50,20,50]}[n];"vibrate"in navigator&&navigator.vibrate(m)},[e]),supportsHaptics:e}}const Pe={enabledGestures:["tap","double-tap","long-press","swipe-left","swipe-right","swipe-up","swipe-down","pinch-in","pinch-out"],tapThreshold:200,doubleTapThreshold:300,longPressThreshold:500,swipeThreshold:50,swipeVelocityThreshold:.5,pinchThreshold:.1,rotationThreshold:15,enableHapticFeedback:!0};function ge(e,t,n={}){const a={...Pe,...n},{isTouchDevice:m}=ne(),{triggerHaptic:l}=Ce(),i=j.useRef({isTracking:!1,touches:[],startTouches:[]}),d=f=>({id:f.identifier,x:f.clientX,y:f.clientY,timestamp:Date.now()}),E=(f,o)=>Math.sqrt(Math.pow(o.x-f.x,2)+Math.pow(o.y-f.y,2)),M=(f,o)=>{const p=Math.max(o.timestamp-f.timestamp,1);return{x:(o.x-f.x)/p,y:(o.y-f.y)/p}},L=(f,o,p,P={})=>({type:f,startPoint:{x:o.x,y:o.y},currentPoint:{x:p.x,y:p.y},duration:p.timestamp-o.timestamp,target:e.current,preventDefault:()=>{},...P}),y=j.useCallback(f=>{if(!a.enabledGestures.length)return;const o=Array.from(f.touches).map(d),p=i.current;p.isTracking=!0,p.touches=o,p.startTouches=[...o],p.longPressTimer&&clearTimeout(p.longPressTimer),o.length===1&&a.enabledGestures.includes("long-press")&&(p.longPressTimer=setTimeout(()=>{if(p.touches.length===1&&o[0]){const P=L("long-press",o[0],o[0]);t(P),a.enableHapticFeedback&&l("heavy")}},a.longPressThreshold)),o.length===2&&o[0]&&o[1]&&(p.initialDistance=E(o[0],o[1]),p.initialScale=1,p.lastScale=1)},[a,t,l]),r=j.useCallback(f=>{const o=i.current;if(!o.isTracking)return;const p=Array.from(f.touches).map(d);if(o.touches=p,p.length===2&&o.initialDistance&&p[0]&&p[1]){const P=E(p[0],p[1]),h=P/o.initialDistance;if(Math.abs(h-(o.lastScale||1))>a.pinchThreshold){const T=h>(o.lastScale||1)?"pinch-out":"pinch-in";if(a.enabledGestures.includes(T)){const g={x:(p[0].x+p[1].x)/2,y:(p[0].y+p[1].y)/2,timestamp:Date.now()},S={x:((o.startTouches[0]?.x??0)+(o.startTouches[1]?.x??0))/2,y:((o.startTouches[0]?.y??0)+(o.startTouches[1]?.y??0))/2,timestamp:o.startTouches[0]?.timestamp??Date.now()},k=L(T,S,g,{scale:h,distance:P});t(k),o.lastScale=h}}}if(o.longPressTimer&&p.length===1&&o.startTouches[0]&&p[0]){const P=o.startTouches[0],h=p[0];E(P,h)>a.swipeThreshold&&(clearTimeout(o.longPressTimer),o.longPressTimer=void 0)}},[a,t]),v=j.useCallback(f=>{const o=i.current;if(!o.isTracking)return;const p=Array.from(f.changedTouches).map(d),P=Date.now();if(o.longPressTimer&&(clearTimeout(o.longPressTimer),o.longPressTimer=void 0),o.startTouches.length===1&&p.length===1&&o.startTouches[0]&&p[0]){const h=o.startTouches[0],c=p[0],T=E(h,c),g=c.timestamp-h.timestamp;if(T>a.swipeThreshold){const S=M(h,c),k=Math.abs(S.x),b=Math.abs(S.y);if(k>a.swipeVelocityThreshold||b>a.swipeVelocityThreshold){let B;if(k>b?B=S.x>0?"swipe-right":"swipe-left":B=S.y>0?"swipe-down":"swipe-up",a.enabledGestures.includes(B)){const F=L(B,h,c,{velocity:S,distance:T});t(F),a.enableHapticFeedback&&l("light")}}}else if(g<a.tapThreshold&&T<a.swipeThreshold)if(o.lastTap&&P-o.lastTap.timestamp<a.doubleTapThreshold&&E({...o.lastTap.point},c)<a.swipeThreshold){if(a.enabledGestures.includes("double-tap")){const S=L("double-tap",h,c);t(S),a.enableHapticFeedback&&l("medium")}o.lastTap=void 0}else{if(a.enabledGestures.includes("tap")){const S=L("tap",h,c);t(S),a.enableHapticFeedback&&l("light")}o.lastTap={timestamp:P,point:{x:c.x,y:c.y}}}}f.touches.length===0&&(o.isTracking=!1,o.touches=[],o.startTouches=[],o.initialDistance=void 0,o.initialScale=void 0,o.lastScale=void 0)},[a,t,l]);return j.useEffect(()=>{const f=e.current;if(!(!f||!m))return f.addEventListener("touchstart",y,{passive:!1}),f.addEventListener("touchmove",r,{passive:!1}),f.addEventListener("touchend",v,{passive:!1}),f.addEventListener("touchcancel",v,{passive:!1}),()=>{f.removeEventListener("touchstart",y),f.removeEventListener("touchmove",r),f.removeEventListener("touchend",v),f.removeEventListener("touchcancel",v)}},[y,r,v,m]),{isGestureEnabled:m&&a.enabledGestures.length>0}}function Fe(e,t){const n=j.useCallback(m=>{const{type:l,distance:i,scale:d}=m;switch(l){case"double-tap":t.onPlayPause?.();break;case"swipe-left":const E=Math.min((i||0)/10,30);t.onSeek?.("backward",E);break;case"swipe-right":const M=Math.min((i||0)/10,30);t.onSeek?.("forward",M);break;case"swipe-up":if(m.startPoint.x>(e.current?.clientWidth||0)/2){const L=Math.min((i||0)/100,.2);t.onVolumeChange?.("up",L)}break;case"swipe-down":if(m.startPoint.x>(e.current?.clientWidth||0)/2){const L=Math.min((i||0)/100,.2);t.onVolumeChange?.("down",L)}break;case"pinch-out":t.onZoom?.(d||1);break;case"pinch-in":t.onZoom?.(d||1);break;case"long-press":t.onToggleFullscreen?.();break}},[t,e]);return ge(e,n,{enabledGestures:["tap","double-tap","long-press","swipe-left","swipe-right","swipe-up","swipe-down","pinch-in","pinch-out"],enableHapticFeedback:!0,swipeThreshold:30,swipeVelocityThreshold:.3})}function ve({subtitleSrc:e,subtitleTracks:t=[],defaultFontSize:n="medium",onLoadError:a}={}){const[m,l]=s.useState(!1),[i,d]=s.useState([]),[E,M]=s.useState(""),[L,y]=s.useState(null),[r,v]=s.useState(n),[f,o]=s.useState(null),[p,P]=s.useState(!1),h={small:"text-sm",medium:"text-base",large:"text-lg"},c=!!(e||t&&t.length>0),T=D=>{const C=D.split(":"),R=C[2]?parseFloat(C[2]):0,V=C[1]?parseInt(C[1],10)*60:0;return(C[0]?parseInt(C[0],10)*3600:0)+V+R},g=D=>{const[C,R]=D.split(","),V=(C||"").split(":"),N=R?parseInt(R,10)/1e3:0,x=V[2]?parseInt(V[2],10):0,Q=V[1]?parseInt(V[1],10)*60:0;return(V[0]?parseInt(V[0],10)*3600:0)+Q+x+N},S=async D=>{P(!0),o(null);try{const C=await fetch(D);if(!C.ok)throw new Error(`Failed to load subtitles: ${C.status} ${C.statusText}`);const R=await C.text(),V=[],N=R.split(`
|
|
2
|
+
`);let x=0;const Q=R.includes("WEBVTT")||D.endsWith(".vtt"),u=D.endsWith(".srt")||/^\d+$/.test(N[0]?.trim()||"");if(Q)for(;x<N.length;){if(N[x]?.includes("-->")){const[_,z]=(N[x]||"").split("-->").map(G=>G.trim()),X=T(_||""),w=T(z||"");x++;let U="";for(;x<N.length&&N[x]?.trim()!=="";)U+=(U?" ":"")+N[x]?.trim(),x++;U&&V.push({start:X,end:w,text:U})}x++}else if(u)for(;x<N.length;){if(/^\d+$/.test(N[x]?.trim()||"")&&(x++,N[x]?.includes("-->"))){const[_,z]=(N[x]||"").split("-->").map(G=>G.trim()),X=g(_||""),w=g(z||"");x++;let U="";for(;x<N.length&&N[x]?.trim()!=="";)U+=(U?" ":"")+N[x]?.trim(),x++;U&&V.push({start:X,end:w,text:U})}x++}else throw new Error("Unsupported subtitle format. Only VTT and SRT are supported.");if(V.length===0)throw new Error("No subtitle cues found in file");d(V),P(!1)}catch(C){const R=C instanceof Error?C:new Error("Failed to load subtitles");console.error("Failed to load subtitles:",R),o(R),P(!1),d([]),a?.(R)}},k=D=>!m||i.length===0?"":i.find(R=>D>=R.start&&D<=R.end)?.text||"",b=()=>{l(D=>{const C=!D;if(C&&!f){if(i.length===0&&!p){const R=e||t[0]?.src;R&&(S(R),t[0]&&y(t[0].id))}}else C||M("");return C})},B=D=>{if(!D){l(!1),y(null),M("");return}const C=t.find(R=>R.id===D);C?.src&&(y(D),S(C.src),l(!0))},F=D=>{v(D)},I={fontSize:h[r],className:`${h[r]} font-medium`};return s.useEffect(()=>{m||M("")},[m]),s.useEffect(()=>{},[]),{subtitlesEnabled:m,currentSubtitle:E,subtitleCues:i,currentTrackId:L,fontSize:r,loadError:f,isLoading:p,hasSubtitles:c,toggleSubtitles:b,selectSubtitleTrack:B,changeSubtitleFontSize:F,setCurrentSubtitle:M,getCurrentSubtitle:k,getSubtitleStyles:I,availableTracks:t}}const De=Object.freeze(Object.defineProperty({__proto__:null,useEnhancedSubtitles:ve},Symbol.toStringTag,{value:"Module"}));function ue(e,t){if(!Number.isFinite(t))return console.warn(`Attempted to set non-finite currentTime: ${t}`),!1;if(t<0)return console.warn(`Attempted to set negative currentTime: ${t}`),!1;try{return e.currentTime=t,!0}catch(n){return console.error(`Failed to set currentTime to ${t}:`,n),!1}}function Re({videoControls:e,toggleSubtitles:t,takeScreenshot:n,duration:a}){const m=l=>{const i=document.querySelector("video");if(i)switch(l.key.toLowerCase()){case" ":case"k":l.preventDefault(),e.togglePlay();break;case"j":l.preventDefault(),e.seekBackward();break;case"l":l.preventDefault(),e.seekForward();break;case"arrowleft":l.preventDefault();const d=Number.isFinite(i.currentTime)?i.currentTime:0,E=Math.max(0,d-5);ue(i,E);break;case"arrowright":l.preventDefault();const M=Number.isFinite(a)&&a>0?a:Number.isFinite(i.duration)?i.duration:0;if(M===0){console.warn("Cannot seek: duration is not available");break}const L=Number.isFinite(i.currentTime)?i.currentTime:0,y=Math.min(M,L+5);ue(i,y);break;case"arrowup":l.preventDefault(),i.volume=Math.min(1,i.volume+.1);break;case"arrowdown":l.preventDefault(),i.volume=Math.max(0,i.volume-.1);break;case"m":l.preventDefault(),e.toggleMute();break;case"f":l.preventDefault(),e.toggleFullscreen();break;case"c":l.preventDefault(),t();break;case"s":l.preventDefault(),n(l.ctrlKey||l.metaKey);break}};s.useEffect(()=>(document.addEventListener("keydown",m),()=>document.removeEventListener("keydown",m)),[m])}function Ae(e,t){const[n,a]=s.useState(!0),[m,l]=s.useState(!1),i=s.useRef(null),d=()=>{a(!0),i.current&&clearTimeout(i.current),e&&!t&&(i.current=setTimeout(()=>{a(!1)},3e3))},E=()=>{d()},M=()=>{a(!0)},L=()=>{e&&a(!1)};return s.useEffect(()=>(d(),()=>{i.current&&clearTimeout(i.current)}),[d]),{controlsVisible:n,showVolumeSlider:m,setShowVolumeSlider:l,handleMouseMove:E,handleMouseEnter:M,handleMouseLeave:L}}function xe(e){return{takeScreenshot:(n=!1)=>{if(!e.current)return;const a=e.current,m=document.createElement("canvas");m.width=a.videoWidth,m.height=a.videoHeight;const l=m.getContext("2d");if(l)try{l.drawImage(a,0,0),m.toBlob(i=>{if(!i){console.error("Failed to create blob from canvas");return}if(n)if(navigator.clipboard&&window.ClipboardItem){const d=new ClipboardItem({"image/png":i});navigator.clipboard.write([d]).catch(E=>{console.error("Failed to copy to clipboard:",E)})}else console.warn("Clipboard API not supported");else{const d=URL.createObjectURL(i),E=document.createElement("a");E.href=d,E.download=`screenshot-${Date.now()}.png`,E.click(),URL.revokeObjectURL(d)}},"image/png")}catch(i){i instanceof Error&&i.message.includes("tainted")?(console.error("Canvas is tainted - video source may not have proper CORS headers. Try setting crossOrigin='anonymous' on the video element."),alert("Screenshot failed: The video source doesn't allow screenshots due to CORS policy. Please ensure the video server includes proper CORS headers or set crossOrigin='anonymous' on the video player.")):(console.error("Screenshot failed:",i),alert("Screenshot failed: "+(i instanceof Error?i.message:"Unknown error")))}}}}function re(e,t){if(!Number.isFinite(t))return console.warn(`Attempted to set non-finite currentTime: ${t}`),!1;if(t<0)return console.warn(`Attempted to set negative currentTime: ${t}`),!1;try{return e.currentTime=t,!0}catch(n){return console.error(`Failed to set currentTime to ${t}:`,n),!1}}function Oe(e){const t=s.useRef(null),[n,a]=s.useState({isPlaying:!1,currentTime:0,duration:0,volume:1,isMuted:!1,isFullscreen:!1,isLoading:!0,isSeeking:!1,isBuffering:!1,bufferedRanges:[]});return s.useEffect(()=>{const r=t.current;if(!r)return;const v=()=>{a(F=>({...F,currentTime:r.currentTime}))},f=()=>{a(F=>({...F,duration:r.duration}))},o=()=>{a(F=>({...F,isPlaying:!0,isBuffering:!1}))},p=()=>{a(F=>({...F,isPlaying:!1}))},P=()=>{a(F=>({...F,volume:r.volume,isMuted:r.muted}))},h=()=>{a(F=>({...F,isLoading:!0}))},c=()=>{a(F=>({...F,isLoading:!1}))},T=()=>{a(F=>({...F,isSeeking:!0}))},g=()=>{a(F=>({...F,isSeeking:!1}))},S=()=>{a(F=>({...F,isBuffering:!0}))},k=()=>{a(F=>({...F,isBuffering:!1,isLoading:!1}))},b=()=>{a(F=>({...F,isLoading:!1,isBuffering:!1}))},B=()=>{if(!r.buffered||r.buffered.length===0||r.duration===0){a(I=>({...I,bufferedRanges:[]}));return}const F=[];for(let I=0;I<r.buffered.length;I++){const D=r.buffered.start(I),C=r.buffered.end(I);F.push({start:D,end:C,percentage:(C-D)/r.duration*100})}a(I=>({...I,bufferedRanges:F}))};return r.addEventListener("timeupdate",v),r.addEventListener("loadedmetadata",f),r.addEventListener("play",o),r.addEventListener("pause",p),r.addEventListener("volumechange",P),r.addEventListener("loadstart",h),r.addEventListener("loadeddata",c),r.addEventListener("seeking",T),r.addEventListener("seeked",g),r.addEventListener("waiting",S),r.addEventListener("playing",k),r.addEventListener("canplay",b),r.addEventListener("progress",B),()=>{r.removeEventListener("timeupdate",v),r.removeEventListener("loadedmetadata",f),r.removeEventListener("play",o),r.removeEventListener("pause",p),r.removeEventListener("volumechange",P),r.removeEventListener("loadstart",h),r.removeEventListener("loadeddata",c),r.removeEventListener("seeking",T),r.removeEventListener("seeked",g),r.removeEventListener("waiting",S),r.removeEventListener("playing",k),r.removeEventListener("canplay",b),r.removeEventListener("progress",B)}},[]),{videoRef:t,state:n,controls:{togglePlay:()=>{const r=t.current;r&&(n.isPlaying?r.pause():r.play())},seekForward:(r=10)=>{const v=t.current;if(!v)return;const f=Number.isFinite(v.duration)?v.duration:Number.isFinite(n.duration)?n.duration:0;if(f===0){console.warn("Cannot seek forward: duration is not available");return}const o=Number.isFinite(v.currentTime)?v.currentTime:0,p=Math.min(f,o+r);re(v,p)},seekBackward:(r=10)=>{const v=t.current;if(!v)return;const f=Number.isFinite(v.currentTime)?v.currentTime:0,o=Math.max(0,f-r);re(v,o)},toggleMute:()=>{const r=t.current;r&&(r.muted=!n.isMuted)},setVolume:r=>{const v=t.current;v&&(v.volume=r,r>0&&n.isMuted&&(v.muted=!1))},toggleFullscreen:()=>{const r=e.current;r&&(n.isFullscreen?document.exitFullscreen&&document.exitFullscreen():r.requestFullscreen&&r.requestFullscreen(),a(v=>({...v,isFullscreen:!v.isFullscreen})))},seekTo:r=>{const v=t.current;if(!v)return;const f=Number.isFinite(v.duration)?v.duration:Number.isFinite(n.duration)?n.duration:0;if(f===0){console.warn("Cannot seek: duration is not available");return}const o=Math.max(0,Math.min(f,r));re(v,o)}}}}const Ie=(e,t={})=>{const{trackUserBehavior:n=!0,adaptToNetwork:a=!0,strategy:m="balanced",maxPreloadItems:l=3,preloadRadius:i=2}=t,d=s.useRef({mouseMovements:0,scrollEvents:0,keyPresses:0,focusEvents:0,timeOnPage:0,engagementScore:0,lastInteraction:Date.now()}),E=s.useRef(null),M=s.useRef(new Set),L=s.useRef([]),y=s.useCallback(()=>{const c=d.current,T=Math.min(c.timeOnPage/6e4,1),g=Math.min((c.mouseMovements+c.scrollEvents+c.keyPresses)/100,1);return(T*.4+g*.6)*100},[]),r=s.useCallback((c,T=1)=>{const g=d.current;g[c]=typeof g[c]=="number"?g[c]+T:Date.now(),g.engagementScore=y(),g.lastInteraction=Date.now()},[y]),v=s.useCallback(()=>{if(!E.current||!a)return{type:"unknown",downlink:10,effectiveType:"4g",saveData:!1};const c=E.current;return{type:c.type,downlink:c.downlink||10,effectiveType:c.effectiveType||"4g",saveData:c.saveData||!1,rtt:c.rtt||100}},[a]),f=s.useCallback((c,T,g=0)=>{if(M.current.has(c.src))return{shouldPreload:!1,priority:"low",reason:"Already preloaded"};const S=Math.abs(T-g);if(S>i)return{shouldPreload:!1,priority:"low",reason:"Outside preload radius"};const k=d.current,b=v(),B=k.engagementScore,F=Date.now()-k.lastInteraction;if(b.saveData)return{shouldPreload:!1,priority:"low",reason:"Data saver mode"};let I=!1,D="medium",C="";switch(m){case"conservative":I=B>70&&b.effectiveType!=="2g"&&S===1,D=I?"medium":"low",C=I?"High engagement and optimal network":"Conservative strategy";break;case"aggressive":I=B>30&&b.effectiveType!=="slow-2g",D=B>70?"high":B>50?"medium":"low",C=I?"Aggressive preloading":"Low engagement";break;case"balanced":default:const R=b.effectiveType==="4g"?1:b.effectiveType==="3g"?.7:.3,V=B*R;I=V>40&&S<=2,D=V>70?"high":V>55?"medium":"low",C=I?`Balanced: score ${V.toFixed(1)}`:"Low adjusted score";break}if(I){const R=c.type;(R==="hls"||R==="m3u8"||R==="application/x-mpegURL")&&(D=D==="low"?"medium":"high"),F<5e3&&(D="high",C+=" + Recent interaction"),(R==="mp4"||R==="webm"||R==="video/mp4"||R==="video/webm")&&(D=D==="low"?"medium":D)}return{shouldPreload:I,priority:D,reason:C}},[m,i,v,y]),o=s.useCallback(async(c,T)=>{try{const g=document.createElement("link");switch(g.rel="preload",g.href=c.src,c.type){case"hls":case"m3u8":case"application/x-mpegURL":g.as="fetch";break;case"mp4":case"webm":case"video/mp4":case"video/webm":g.as="video";break;case"mp3":case"wav":case"ogg":case"audio/mpeg":case"audio/wav":case"audio/ogg":g.as="audio";break;default:g.as="fetch"}g.crossOrigin="anonymous",document.head.appendChild(g),M.current.add(c.src),console.debug(`Preloaded: ${c.src} (${T})`),setTimeout(()=>{document.head.contains(g)&&document.head.removeChild(g)},3e4)}catch(g){console.warn("Failed to preload source:",c.src,g)}},[]),p=s.useCallback(()=>{if(L.current.length===0)return;const T=[...L.current].sort((g,S)=>S.priority-g.priority).slice(0,l);L.current=[],T.forEach(({source:g,priority:S})=>{o(g,S)})},[l,o]),P=s.useCallback((c=0)=>{L.current=[],e.forEach((T,g)=>{const S=f(T,g,c);if(S.shouldPreload){const k=S.priority==="high"?3:S.priority==="medium"?2:1;L.current.push({source:T,priority:k})}}),p()},[e,f,p]);return s.useEffect(()=>{if(!n)return;const c=()=>r("mouseMovements"),T=()=>r("scrollEvents"),g=()=>r("keyPresses"),S=()=>r("focusEvents");document.addEventListener("mousemove",c,{passive:!0}),document.addEventListener("scroll",T,{passive:!0}),document.addEventListener("keydown",g,{passive:!0}),document.addEventListener("focusin",S,{passive:!0});const k=setInterval(()=>{r("timeOnPage",1)},1e3);return()=>{document.removeEventListener("mousemove",c),document.removeEventListener("scroll",T),document.removeEventListener("keydown",g),document.removeEventListener("focusin",S),clearInterval(k)}},[n,r]),s.useEffect(()=>{if(!a||!("connection"in navigator))return;const c=navigator.connection;E.current=c;const T=()=>{P()};return c.addEventListener("change",T),()=>{c.removeEventListener("change",T)}},[a,P]),s.useEffect(()=>{P()},[P]),s.useMemo(()=>({preloadAtIndex:c=>{P(c)},getUserBehavior:()=>({...d.current}),getNetworkConditions:v,clearCache:()=>{M.current.clear()},getStats:()=>({preloadedItems:M.current.size,engagementScore:d.current.engagementScore,queueLength:L.current.length,maxPreloadItems:l})}),[P,v,l])};function Te(e){const[t,n]=s.useState(!1),[a,m]=s.useState([]),[l,i]=s.useState(""),d=y=>{const r=y.split(":"),v=r[2]?parseFloat(r[2]):0,f=r[1]?parseInt(r[1],10)*60:0;return(r[0]?parseInt(r[0],10)*3600:0)+f+v},E=async y=>{try{const v=await(await fetch(y)).text(),f=[],o=v.split(`
|
|
3
|
+
`);let p=0;for(;p<o.length;){if(o[p]?.includes("-->")){const[P,h]=(o[p]||"").split("-->").map(S=>S.trim()),c=d(P||""),T=d(h||"");p++;let g="";for(;p<o.length&&o[p]?.trim()!=="";)g+=(g?" ":"")+o[p]?.trim(),p++;g&&f.push({start:c,end:T,text:g})}p++}m(f)}catch(r){console.error("Failed to load subtitles:",r)}},M=y=>!t||a.length===0?"":a.find(v=>y>=v.start&&y<=v.end)?.text||"",L=()=>{n(y=>{const r=!y;return r&&e&&a.length===0?E(e):r||i(""),r})};return s.useEffect(()=>{t||i("")},[t]),{subtitlesEnabled:t,currentSubtitle:l,toggleSubtitles:L,getCurrentSubtitle:M,setCurrentSubtitle:i}}function Ve(e){return le.showDeprecationWarning("useVideoPlayer","useMediaPlayer (the primary media player hook)"),pe(e)}function Ue(e){return le.showDeprecationWarning("useEnhancedSubtitles","useSubtitles (the current subtitle hook)"),Te(e)}exports.useDeviceInfo=ne;exports.useEnhancedMediaPlayer=Ee;exports.useEnhancedSubtitles=ve;exports.useEnhancedSubtitles$1=Ue;exports.useEnhancedSubtitles$2=De;exports.useIntelligentPreloading=Ie;exports.useKeyboardControls=fe;exports.useKeyboardControls$1=Se;exports.useKeyboardShortcuts=Re;exports.useMediaActionState=de;exports.useMediaActions=me;exports.useMediaControls=Ae;exports.useMediaGestures=Fe;exports.useMediaPlayer=pe;exports.useMediaState=he;exports.useMemoryOptimization=ke;exports.useMobileOptimizations=Le;exports.useScreenshot=xe;exports.useSubtitles=Te;exports.useTouchGestures=ge;exports.useVideoPlayer=Oe;exports.useVideoPlayer$1=Ve;
|
|
4
|
+
//# sourceMappingURL=hooks-BXwI8QG6.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hooks-BXwI8QG6.cjs","sources":["../src/hooks/use-media-actions.ts","../src/hooks/use-media-optimistic.ts","../src/hooks/use-enhanced-media-player.ts","../src/hooks/use-keyboard-controls.ts","../src/hooks/use-memory-optimization.ts","../src/hooks/use-media-state.ts","../src/hooks/use-media-player.ts","../../ui/src/hooks/use-mobile.ts","../src/hooks/use-touch-gestures.ts","../src/hooks/useEnhancedSubtitles.ts","../src/hooks/useKeyboardShortcuts.ts","../src/hooks/useMediaControls.ts","../src/hooks/useScreenshot.ts","../src/hooks/useVideoPlayer.ts","../src/hooks/use-intelligent-preloading.ts","../src/hooks/useSubtitles.ts","../src/hooks/legacy.ts"],"sourcesContent":["\"use client\"\n\nimport React from \"react\"\nimport type { MediaActionType, MediaState } from \"../context/media-context\"\nimport { MediaActionTypes } from \"../context/media-context\"\nimport type {\n\tEnhancedMediaStore,\n\tMediaActionState,\n\tOptimisticMediaAction\n} from \"../context/media-store\"\n\n// Action payload types\nexport interface MediaActionPayloads {\n\t[MediaActionTypes.PLAY]: void\n\t[MediaActionTypes.PAUSE]: void\n\t[MediaActionTypes.SEEK]: number\n\t[MediaActionTypes.SET_VOLUME]: number\n\t[MediaActionTypes.MUTE]: void\n\t[MediaActionTypes.UNMUTE]: void\n\t[MediaActionTypes.TOGGLE_MUTE]: void\n\t[MediaActionTypes.SET_DURATION]: number\n\t[MediaActionTypes.SET_CURRENT_TIME]: number\n\t[MediaActionTypes.SET_BUFFERED]: TimeRanges | null\n\t[MediaActionTypes.SET_LOADING]: boolean\n\t[MediaActionTypes.SET_ERROR]: string | null\n\t[MediaActionTypes.ENTER_FULLSCREEN]: void\n\t[MediaActionTypes.EXIT_FULLSCREEN]: void\n\t[MediaActionTypes.ENTER_PIP]: void\n\t[MediaActionTypes.EXIT_PIP]: void\n\t[MediaActionTypes.SET_PLAYBACK_RATE]: number\n\t[MediaActionTypes.SET_SUBTITLE_TRACK]: TextTrack | null\n\t[MediaActionTypes.SET_RENDITION]: string | null\n\t[MediaActionTypes.TOGGLE_SUBTITLES]: void\n\t[MediaActionTypes.PREVIEW_TIME]: number | null\n\t[MediaActionTypes.CLEAR_PREVIEW]: void\n}\n\n// Enhanced action creator that returns a Promise\ntype OptimisticActionCreator<T extends keyof MediaActionPayloads> =\n\tMediaActionPayloads[T] extends void\n\t\t? (optimistic?: boolean) => Promise<void>\n\t\t: (payload: MediaActionPayloads[T], optimistic?: boolean) => Promise<void>\n\n// Action creator factory\nfunction createOptimisticAction<T extends keyof MediaActionPayloads>(\n\ttype: T,\n\tstore: EnhancedMediaStore\n): OptimisticActionCreator<T> {\n\treturn ((payload?: any, optimistic = false) => {\n\t\tconst action: OptimisticMediaAction = {\n\t\t\ttype,\n\t\t\tdetail: payload,\n\t\t\toptimistic,\n\t\t\ttimestamp: Date.now()\n\t\t}\n\n\t\tif (optimistic) {\n\t\t\treturn store.dispatchOptimistic(action)\n\t\t} else {\n\t\t\tstore.dispatch(action)\n\t\t\treturn Promise.resolve()\n\t\t}\n\t}) as OptimisticActionCreator<T>\n}\n\n// React 19 useActionState integration\nexport function useMediaActionState(store: EnhancedMediaStore) {\n\tconst [actionState, setActionState] = React.useState<MediaActionState>(store.getActionState())\n\n\t// Subscribe to action state changes\n\tReact.useEffect(() => {\n\t\tconst unsubscribe = store.subscribe(() => {\n\t\t\tconst newActionState = store.getActionState()\n\t\t\tsetActionState((current) =>\n\t\t\t\tJSON.stringify(current) !== JSON.stringify(newActionState) ? newActionState : current\n\t\t\t)\n\t\t})\n\t\treturn unsubscribe\n\t}, [store])\n\n\treturn actionState\n}\n\n// Media actions hook with React 19 optimistic updates\nexport function useMediaActions(store: EnhancedMediaStore) {\n\t// Create action creators with optimistic support\n\tconst actions = React.useMemo(\n\t\t() => ({\n\t\t\t// Playback actions\n\t\t\tplay: createOptimisticAction(MediaActionTypes.PLAY, store),\n\t\t\tpause: createOptimisticAction(MediaActionTypes.PAUSE, store),\n\t\t\tseek: createOptimisticAction(MediaActionTypes.SEEK, store),\n\n\t\t\t// Volume actions\n\t\t\tsetVolume: createOptimisticAction(MediaActionTypes.SET_VOLUME, store),\n\t\t\tmute: createOptimisticAction(MediaActionTypes.MUTE, store),\n\t\t\tunmute: createOptimisticAction(MediaActionTypes.UNMUTE, store),\n\t\t\ttoggleMute: createOptimisticAction(MediaActionTypes.TOGGLE_MUTE, store),\n\n\t\t\t// Media state actions\n\t\t\tsetDuration: createOptimisticAction(MediaActionTypes.SET_DURATION, store),\n\t\t\tsetCurrentTime: createOptimisticAction(MediaActionTypes.SET_CURRENT_TIME, store),\n\t\t\tsetBuffered: createOptimisticAction(MediaActionTypes.SET_BUFFERED, store),\n\t\t\tsetLoading: createOptimisticAction(MediaActionTypes.SET_LOADING, store),\n\t\t\tsetError: createOptimisticAction(MediaActionTypes.SET_ERROR, store),\n\n\t\t\t// Display actions\n\t\t\tenterFullscreen: createOptimisticAction(MediaActionTypes.ENTER_FULLSCREEN, store),\n\t\t\texitFullscreen: createOptimisticAction(MediaActionTypes.EXIT_FULLSCREEN, store),\n\t\t\tenterPiP: createOptimisticAction(MediaActionTypes.ENTER_PIP, store),\n\t\t\texitPiP: createOptimisticAction(MediaActionTypes.EXIT_PIP, store),\n\n\t\t\t// Advanced actions\n\t\t\tsetPlaybackRate: createOptimisticAction(MediaActionTypes.SET_PLAYBACK_RATE, store),\n\t\t\tsetSubtitleTrack: createOptimisticAction(MediaActionTypes.SET_SUBTITLE_TRACK, store),\n\t\t\tsetRendition: createOptimisticAction(MediaActionTypes.SET_RENDITION, store),\n\t\t\ttoggleSubtitles: createOptimisticAction(MediaActionTypes.TOGGLE_SUBTITLES, store),\n\n\t\t\t// Preview actions\n\t\t\tpreviewTime: createOptimisticAction(MediaActionTypes.PREVIEW_TIME, store),\n\t\t\tclearPreview: createOptimisticAction(MediaActionTypes.CLEAR_PREVIEW, store)\n\t\t}),\n\t\t[store]\n\t)\n\n\t// Get action state for loading/error handling\n\tconst actionState = useMediaActionState(store)\n\n\t// Convenience methods that commonly use optimistic updates\n\tconst optimisticActions = React.useMemo(\n\t\t() => ({\n\t\t\t// These actions benefit from immediate UI feedback\n\t\t\ttogglePlayPause: async (isPlaying: boolean) => {\n\t\t\t\tif (isPlaying) {\n\t\t\t\t\tawait actions.pause(true) // optimistic\n\t\t\t\t} else {\n\t\t\t\t\tawait actions.play(true) // optimistic\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tseekWithPreview: async (time: number) => {\n\t\t\t\t// Immediate preview update, then actual seek\n\t\t\t\tawait actions.previewTime(time, true)\n\t\t\t\tawait actions.seek(time, true)\n\t\t\t},\n\n\t\t\tadjustVolume: async (delta: number, currentVolume: number) => {\n\t\t\t\tconst newVolume = Math.max(0, Math.min(1, currentVolume + delta))\n\t\t\t\tawait actions.setVolume(newVolume, true)\n\t\t\t},\n\n\t\t\ttoggleFullscreenOptimistic: async (isFullscreen: boolean) => {\n\t\t\t\tif (isFullscreen) {\n\t\t\t\t\tawait actions.exitFullscreen(true)\n\t\t\t\t} else {\n\t\t\t\t\tawait actions.enterFullscreen(true)\n\t\t\t\t}\n\t\t\t}\n\t\t}),\n\t\t[actions]\n\t)\n\n\t// Retry failed action\n\tconst retryLastAction = React.useCallback(async () => {\n\t\tconst { lastAction } = actionState\n\t\tif (lastAction && actionState.error) {\n\t\t\tawait store.dispatchOptimistic({\n\t\t\t\t...lastAction,\n\t\t\t\tretryCount: (lastAction.retryCount || 0) + 1\n\t\t\t})\n\t\t}\n\t}, [store, actionState])\n\n\treturn {\n\t\t...actions,\n\t\t...optimisticActions,\n\t\tactionState,\n\t\tretryLastAction,\n\t\tisLoading: actionState.pending,\n\t\thasError: !!actionState.error,\n\t\terrorMessage: actionState.error,\n\t\tretryCount: actionState.retryCount\n\t}\n}\n","\"use client\"\n\nimport React, { useOptimistic } from \"react\"\nimport type { MediaState } from \"../context/media-context\"\nimport type { EnhancedMediaStore, OptimisticMediaAction } from \"../context/media-store\"\n\n// Optimistic update reducer function\nfunction optimisticMediaReducer(state: MediaState, action: OptimisticMediaAction): MediaState {\n\tif (!action.optimistic) return state\n\n\t// Apply immediate optimistic updates for better UX\n\tswitch (action.type) {\n\t\tcase \"PLAY\":\n\t\t\treturn { ...state, isPlaying: true, error: null }\n\n\t\tcase \"PAUSE\":\n\t\t\treturn { ...state, isPlaying: false }\n\n\t\tcase \"SEEK\":\n\t\t\treturn { ...state, currentTime: action.detail }\n\n\t\tcase \"SET_VOLUME\":\n\t\t\treturn { ...state, volume: Math.max(0, Math.min(1, action.detail)) }\n\n\t\tcase \"MUTE\":\n\t\t\treturn { ...state, isMuted: true }\n\n\t\tcase \"UNMUTE\":\n\t\t\treturn { ...state, isMuted: false }\n\n\t\tcase \"TOGGLE_MUTE\":\n\t\t\treturn { ...state, isMuted: !state.isMuted }\n\n\t\tcase \"ENTER_FULLSCREEN\":\n\t\t\treturn { ...state, isFullscreen: true }\n\n\t\tcase \"EXIT_FULLSCREEN\":\n\t\t\treturn { ...state, isFullscreen: false }\n\n\t\tcase \"SET_PLAYBACK_RATE\":\n\t\t\treturn { ...state, playbackRate: action.detail }\n\n\t\tcase \"TOGGLE_SUBTITLES\":\n\t\t\treturn { ...state, subtitlesShowing: !state.subtitlesShowing }\n\n\t\tcase \"PREVIEW_TIME\":\n\t\t\treturn { ...state, previewTime: action.detail }\n\n\t\tcase \"CLEAR_PREVIEW\":\n\t\t\treturn {\n\t\t\t\t...state,\n\t\t\t\tpreviewTime: null,\n\t\t\t\tpreviewImage: null,\n\t\t\t\tpreviewCoords: null\n\t\t\t}\n\n\t\tdefault:\n\t\t\treturn state\n\t}\n}\n\n// Media optimistic state hook using React 19's useOptimistic\nexport function useMediaOptimistic(store: EnhancedMediaStore) {\n\tconst actualState = React.useSyncExternalStore(store.subscribe, store.getState, store.getState)\n\n\tconst [optimisticState, addOptimistic] = useOptimistic(actualState, optimisticMediaReducer)\n\n\t// Enhanced dispatch that uses optimistic updates\n\tconst dispatchOptimistic = React.useCallback(\n\t\tasync (action: OptimisticMediaAction) => {\n\t\t\t// Add optimistic update immediately\n\t\t\tif (action.optimistic) {\n\t\t\t\taddOptimistic(action)\n\t\t\t}\n\n\t\t\t// Dispatch the actual action\n\t\t\tawait store.dispatchOptimistic(action)\n\t\t},\n\t\t[store, addOptimistic]\n\t)\n\n\t// Quick actions with optimistic updates\n\tconst optimisticActions = React.useMemo(\n\t\t() => ({\n\t\t\t// Play/Pause with immediate feedback\n\t\t\ttogglePlayPause: async () => {\n\t\t\t\tconst action: OptimisticMediaAction = {\n\t\t\t\t\ttype: optimisticState.isPlaying ? \"PAUSE\" : \"PLAY\",\n\t\t\t\t\toptimistic: true,\n\t\t\t\t\ttimestamp: Date.now()\n\t\t\t\t}\n\t\t\t\tawait dispatchOptimistic(action)\n\t\t\t},\n\n\t\t\t// Volume control with immediate slider feedback\n\t\t\tsetVolumeOptimistic: async (volume: number) => {\n\t\t\t\tconst action: OptimisticMediaAction = {\n\t\t\t\t\ttype: \"SET_VOLUME\",\n\t\t\t\t\tdetail: Math.max(0, Math.min(1, volume)),\n\t\t\t\t\toptimistic: true,\n\t\t\t\t\ttimestamp: Date.now()\n\t\t\t\t}\n\t\t\t\tawait dispatchOptimistic(action)\n\t\t\t},\n\n\t\t\t// Seek with immediate scrub feedback\n\t\t\tseekOptimistic: async (time: number) => {\n\t\t\t\tconst action: OptimisticMediaAction = {\n\t\t\t\t\ttype: \"SEEK\",\n\t\t\t\t\tdetail: time,\n\t\t\t\t\toptimistic: true,\n\t\t\t\t\ttimestamp: Date.now()\n\t\t\t\t}\n\t\t\t\tawait dispatchOptimistic(action)\n\t\t\t},\n\n\t\t\t// Mute toggle with immediate icon change\n\t\t\ttoggleMuteOptimistic: async () => {\n\t\t\t\tconst action: OptimisticMediaAction = {\n\t\t\t\t\ttype: \"TOGGLE_MUTE\",\n\t\t\t\t\toptimistic: true,\n\t\t\t\t\ttimestamp: Date.now()\n\t\t\t\t}\n\t\t\t\tawait dispatchOptimistic(action)\n\t\t\t},\n\n\t\t\t// Fullscreen toggle with immediate layout change\n\t\t\ttoggleFullscreenOptimistic: async () => {\n\t\t\t\tconst action: OptimisticMediaAction = {\n\t\t\t\t\ttype: optimisticState.isFullscreen ? \"EXIT_FULLSCREEN\" : \"ENTER_FULLSCREEN\",\n\t\t\t\t\toptimistic: true,\n\t\t\t\t\ttimestamp: Date.now()\n\t\t\t\t}\n\t\t\t\tawait dispatchOptimistic(action)\n\t\t\t},\n\n\t\t\t// Playback rate with immediate feedback\n\t\t\tsetPlaybackRateOptimistic: async (rate: number) => {\n\t\t\t\tconst action: OptimisticMediaAction = {\n\t\t\t\t\ttype: \"SET_PLAYBACK_RATE\",\n\t\t\t\t\tdetail: rate,\n\t\t\t\t\toptimistic: true,\n\t\t\t\t\ttimestamp: Date.now()\n\t\t\t\t}\n\t\t\t\tawait dispatchOptimistic(action)\n\t\t\t},\n\n\t\t\t// Subtitle toggle with immediate visibility change\n\t\t\ttoggleSubtitlesOptimistic: async () => {\n\t\t\t\tconst action: OptimisticMediaAction = {\n\t\t\t\t\ttype: \"TOGGLE_SUBTITLES\",\n\t\t\t\t\toptimistic: true,\n\t\t\t\t\ttimestamp: Date.now()\n\t\t\t\t}\n\t\t\t\tawait dispatchOptimistic(action)\n\t\t\t}\n\t\t}),\n\t\t[optimisticState, dispatchOptimistic]\n\t)\n\n\t// State selectors that return optimistic values\n\tconst selectors = React.useMemo(\n\t\t() => ({\n\t\t\tisPlaying: optimisticState.isPlaying,\n\t\t\tcurrentTime: optimisticState.currentTime,\n\t\t\tvolume: optimisticState.volume,\n\t\t\tisMuted: optimisticState.isMuted,\n\t\t\tisFullscreen: optimisticState.isFullscreen,\n\t\t\tplaybackRate: optimisticState.playbackRate,\n\t\t\tsubtitlesShowing: optimisticState.subtitlesShowing,\n\t\t\tpreviewTime: optimisticState.previewTime,\n\n\t\t\t// Computed values\n\t\t\tprogress:\n\t\t\t\toptimisticState.duration > 0 ? optimisticState.currentTime / optimisticState.duration : 0,\n\n\t\t\tformattedTime: formatTime(optimisticState.currentTime),\n\t\t\tformattedDuration: formatTime(optimisticState.duration),\n\n\t\t\t// State checks\n\t\t\tcanPlay: !optimisticState.isLoading && !optimisticState.error,\n\t\t\thasError: !!optimisticState.error,\n\t\t\tisBuffering: optimisticState.isLoading\n\t\t}),\n\t\t[optimisticState]\n\t)\n\n\treturn {\n\t\tstate: optimisticState,\n\t\tactualState,\n\t\t...selectors,\n\t\t...optimisticActions,\n\t\tdispatchOptimistic\n\t}\n}\n\n// Time formatting utility\nfunction formatTime(seconds: number): string {\n\tif (!seconds || !isFinite(seconds)) return \"0:00\"\n\n\tconst mins = Math.floor(seconds / 60)\n\tconst secs = Math.floor(seconds % 60)\n\tconst hours = Math.floor(mins / 60)\n\n\tif (hours > 0) {\n\t\treturn `${hours}:${String(mins % 60).padStart(2, \"0\")}:${String(secs).padStart(2, \"0\")}`\n\t}\n\n\treturn `${mins}:${String(secs).padStart(2, \"0\")}`\n}\n\n// Hook for components that need to detect optimistic updates\nexport function useOptimisticUpdates(store: EnhancedMediaStore) {\n\tconst [hasOptimisticUpdates, setHasOptimisticUpdates] = React.useState(false)\n\n\tReact.useEffect(() => {\n\t\tconst unsubscribe = store.subscribe(() => {\n\t\t\tconst actualState = store.getState()\n\t\t\tconst optimisticState = store.getOptimisticState()\n\n\t\t\tconst hasUpdates = JSON.stringify(actualState) !== JSON.stringify(optimisticState)\n\t\t\tsetHasOptimisticUpdates(hasUpdates)\n\t\t})\n\n\t\treturn unsubscribe\n\t}, [store])\n\n\treturn hasOptimisticUpdates\n}\n\n// Hook to get both actual and optimistic state for debugging\nexport function useMediaStateComparison(store: EnhancedMediaStore) {\n\tconst actualState = React.useSyncExternalStore(store.subscribe, store.getState, store.getState)\n\n\tconst optimisticState = React.useSyncExternalStore(\n\t\tstore.subscribe,\n\t\tstore.getOptimisticState,\n\t\tstore.getOptimisticState\n\t)\n\n\tconst differences = React.useMemo(() => {\n\t\tconst diffs: any[] = []\n\n\t\tconst stateKeys = Object.keys(actualState) as Array<keyof MediaState>\n\t\tstateKeys.forEach((key) => {\n\t\t\tif (JSON.stringify(actualState[key]) !== JSON.stringify(optimisticState[key])) {\n\t\t\t\tdiffs.push({\n\t\t\t\t\tkey: key as string,\n\t\t\t\t\tactual: actualState[key],\n\t\t\t\t\toptimistic: optimisticState[key]\n\t\t\t\t})\n\t\t\t}\n\t\t})\n\n\t\treturn diffs\n\t}, [actualState, optimisticState])\n\n\treturn {\n\t\tactualState,\n\t\toptimisticState,\n\t\tdifferences,\n\t\thasOptimisticUpdates: differences.length > 0\n\t}\n}\n","\"use client\"\n\nimport React, {\n\tuseCallback,\n\tuseEffect,\n\tuseRef,\n\tuseMemo,\n\tuseTransition,\n\tuseOptimistic,\n\tuseActionState\n} from \"react\"\nimport { useMediaSelector, useMediaStore } from \"../context/media-context\"\nimport type { EnhancedMediaStore } from \"../context/media-store\"\nimport type { MediaPlayerControls, MediaPlayerState } from \"../types/index\"\nimport { useMediaActions } from \"./use-media-actions\"\nimport { useMediaOptimistic } from \"./use-media-optimistic\"\n\ninterface UseEnhancedMediaPlayerOptions {\n\tsrc: string | string[]\n\tautoPlay?: boolean\n\tloop?: boolean\n\tmuted?: boolean\n\tvolume?: number\n\tpreload?: \"none\" | \"metadata\" | \"auto\"\n\tcrossOrigin?: \"anonymous\" | \"use-credentials\"\n\tplaybackRates?: number[]\n\tkeyboardControls?: boolean\n\tshowControls?: boolean\n\tcustomControls?: boolean\n\tenablePerformanceMonitoring?: boolean\n\tbufferingStrategy?: \"aggressive\" | \"conservative\" | \"adaptive\"\n\t// Performance optimizations\n\tenableTimeUpdateThrottling?: boolean\n\ttimeUpdateThrottleMs?: number\n\tenableSeekPreview?: boolean\n\tpreloadStrategy?: \"eager\" | \"lazy\" | \"progressive\"\n\t// Event handlers\n\tonPlay?: () => void\n\tonPause?: () => void\n}\n\n/**\n * Safely sets currentTime on a media element, ensuring the value is finite\n */\nfunction safeSetCurrentTime(media: HTMLVideoElement | HTMLAudioElement, time: number): boolean {\n\tif (!Number.isFinite(time)) {\n\t\tconsole.warn(`Attempted to set non-finite currentTime: ${time}`)\n\t\treturn false\n\t}\n\n\tif (time < 0) {\n\t\tconsole.warn(`Attempted to set negative currentTime: ${time}`)\n\t\treturn false\n\t}\n\n\ttry {\n\t\tmedia.currentTime = time\n\t\treturn true\n\t} catch (error) {\n\t\tconsole.error(`Failed to set currentTime to ${time}:`, error)\n\t\treturn false\n\t}\n}\n\n// Performance-optimized media player hook with React 19 features\nexport function useEnhancedMediaPlayer(options: UseEnhancedMediaPlayerOptions) {\n\tconst mediaRef = useRef<HTMLVideoElement | HTMLAudioElement>(null)\n\tconst containerRef = useRef<HTMLDivElement>(null)\n\n\t// React 19 concurrent features\n\tconst [isPending, startTransition] = useTransition()\n\tconst [isSeeking, startSeekTransition] = useTransition()\n\n\t// Performance monitoring\n\tconst renderStartTime = React.useRef<number>(0)\n\tconst frameCount = React.useRef<number>(0)\n\tconst lastFrameTime = React.useRef<number>(0)\n\n\t// Throttled time update\n\tconst timeUpdateTimeoutRef = useRef<ReturnType<typeof setTimeout> | undefined>(undefined)\n\tconst lastTimeUpdate = useRef<number>(0)\n\n\t// Store integration\n\tconst store = useMediaStore()\n\tconst isEnhanced = \"getOptimisticState\" in store\n\n\t// Select only the state we need to minimize re-renders\n\tconst isPlaying = useMediaSelector((state) => state.isPlaying)\n\tconst currentTime = useMediaSelector((state) => state.currentTime)\n\tconst duration = useMediaSelector((state) => state.duration)\n\tconst volume = useMediaSelector((state) => state.volume)\n\tconst isMuted = useMediaSelector((state) => state.isMuted)\n\tconst isLoading = useMediaSelector((state) => state.isLoading)\n\tconst isBuffering = useMediaSelector((state) => state.isBuffering)\n\tconst error = useMediaSelector((state) => state.error)\n\tconst buffered = useMediaSelector((state) => state.buffered)\n\tconst isFullscreen = useMediaSelector((state) => state.isFullscreen)\n\n\t// Enhanced features - always call hooks unconditionally\n\tconst enhancedStore = store as unknown as EnhancedMediaStore\n\tconst optimisticState = useMediaOptimistic(enhancedStore)\n\tconst actions = useMediaActions(enhancedStore)\n\n\t// Performance state\n\tconst [performanceMetrics, setPerformanceMetrics] = React.useState({\n\t\tframeRate: 0,\n\t\taverageRenderTime: 0,\n\t\tdroppedFrames: 0,\n\t\tbufferHealth: 0\n\t})\n\n\t// Optimistic state updates for immediate UI feedback\n\tconst [optimisticVolume, setOptimisticVolume] = useOptimistic(\n\t\tvolume,\n\t\t(state, newVolume: number) => {\n\t\t\treturn Math.max(0, Math.min(1, newVolume))\n\t\t}\n\t)\n\n\tconst [optimisticTime, setOptimisticTime] = useOptimistic(\n\t\tcurrentTime,\n\t\t(state, newTime: number) => {\n\t\t\treturn Math.max(0, Math.min(duration || 0, newTime))\n\t\t}\n\t)\n\n\t// Initialize media element with performance optimizations\n\tuseEffect(() => {\n\t\tconst media = mediaRef.current\n\t\tif (!media) return\n\n\t\t// Set initial properties\n\t\tconst initProps = {\n\t\t\tvolume: options.volume,\n\t\t\tmuted: options.muted,\n\t\t\tautoplay: options.autoPlay,\n\t\t\tloop: options.loop,\n\t\t\tpreload: options.preload,\n\t\t\tcrossOrigin: options.crossOrigin\n\t\t}\n\n\t\tObject.entries(initProps).forEach(([key, value]) => {\n\t\t\tif (value !== undefined) {\n\t\t\t\t;(media as any)[key] = value\n\t\t\t}\n\t\t})\n\n\t\t// Performance optimizations\n\t\tmedia.setAttribute(\"preload\", options.preloadStrategy === \"eager\" ? \"auto\" : \"metadata\")\n\n\t\tif (options.bufferingStrategy === \"aggressive\") {\n\t\t\tmedia.setAttribute(\"buffered\", \"auto\")\n\t\t}\n\n\t\t// Hardware acceleration\n\t\tif (media instanceof HTMLVideoElement) {\n\t\t\tmedia.style.willChange = \"transform\"\n\t\t\tmedia.style.transform = \"translateZ(0)\"\n\t\t}\n\t}, [\n\t\toptions.volume,\n\t\toptions.muted,\n\t\toptions.autoPlay,\n\t\toptions.loop,\n\t\toptions.preload,\n\t\toptions.crossOrigin,\n\t\toptions.preloadStrategy,\n\t\toptions.bufferingStrategy\n\t])\n\n\t// Optimized event handlers with React 19 patterns\n\tconst handleTimeUpdate = useCallback(() => {\n\t\tconst media = mediaRef.current\n\t\tif (!media) return\n\n\t\tconst now = performance.now()\n\n\t\t// Throttle time updates for performance\n\t\tif (options.enableTimeUpdateThrottling !== false) {\n\t\t\tif (now - lastTimeUpdate.current < (options.timeUpdateThrottleMs || 100)) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tlastTimeUpdate.current = now\n\t\t}\n\n\t\tstartTransition(() => {\n\t\t\tif (isEnhanced && actions) {\n\t\t\t\tactions.setCurrentTime(media.currentTime)\n\t\t\t}\n\t\t})\n\t}, [options.enableTimeUpdateThrottling, options.timeUpdateThrottleMs, isEnhanced, actions])\n\n\tconst handlePlay = useCallback(() => {\n\t\tstartTransition(() => {\n\t\t\tif (isEnhanced && actions) {\n\t\t\t\tactions.play(true) // Optimistic update\n\t\t\t}\n\t\t})\n\t\toptions.onPlay?.()\n\t}, [isEnhanced, actions, options.onPlay])\n\n\tconst handlePause = useCallback(() => {\n\t\tstartTransition(() => {\n\t\t\tif (isEnhanced && actions) {\n\t\t\t\tactions.pause(true) // Optimistic update\n\t\t\t}\n\t\t})\n\t\toptions.onPause?.()\n\t}, [isEnhanced, actions, options.onPause])\n\n\tconst handleVolumeChange = useCallback(() => {\n\t\tconst media = mediaRef.current\n\t\tif (!media) return\n\n\t\tstartTransition(() => {\n\t\t\tif (isEnhanced && actions) {\n\t\t\t\tactions.setVolume(media.volume, true) // Optimistic update\n\t\t\t\tmedia.muted ? actions.mute(true) : actions.unmute(true)\n\t\t\t}\n\t\t})\n\t}, [isEnhanced, actions])\n\n\tconst handleSeeking = useCallback(() => {\n\t\tstartSeekTransition(() => {\n\t\t\t// Seek operations get their own transition\n\t\t})\n\t}, [])\n\n\tconst handleSeeked = useCallback(() => {\n\t\t// Seek completed\n\t}, [])\n\n\tconst handleProgress = useCallback(() => {\n\t\tconst media = mediaRef.current\n\t\tif (!media) return\n\n\t\tstartTransition(() => {\n\t\t\tif (isEnhanced && actions) {\n\t\t\t\tactions.setBuffered(media.buffered)\n\t\t\t}\n\t\t})\n\t}, [isEnhanced, actions])\n\n\t// Performance monitoring\n\tconst measureRenderTime = useCallback(() => {\n\t\tconst now = performance.now()\n\t\tconst deltaTime = now - lastFrameTime.current\n\n\t\tif (deltaTime > 0) {\n\t\t\tframeCount.current++\n\n\t\t\t// Calculate frame rate every second\n\t\t\tif (frameCount.current >= 60) {\n\t\t\t\tconst fps = Math.round((frameCount.current * 1000) / (now - lastFrameTime.current))\n\t\t\t\tsetPerformanceMetrics((prev) => ({\n\t\t\t\t\t...prev,\n\t\t\t\t\tframeRate: fps,\n\t\t\t\t\tdroppedFrames: Math.max(0, 60 - fps)\n\t\t\t\t}))\n\t\t\t\tframeCount.current = 0\n\t\t\t\tlastFrameTime.current = now\n\t\t\t}\n\t\t}\n\t}, [])\n\n\t// Attach event listeners with performance optimization\n\tuseEffect(() => {\n\t\tconst media = mediaRef.current\n\t\tif (!media) return\n\n\t\t// Use passive listeners where possible for better performance\n\t\tconst eventListeners = [\n\t\t\t{ event: \"timeupdate\", handler: handleTimeUpdate, passive: true },\n\t\t\t{ event: \"play\", handler: handlePlay },\n\t\t\t{ event: \"pause\", handler: handlePause },\n\t\t\t{ event: \"volumechange\", handler: handleVolumeChange },\n\t\t\t{ event: \"seeking\", handler: handleSeeking },\n\t\t\t{ event: \"seeked\", handler: handleSeeked },\n\t\t\t{ event: \"progress\", handler: handleProgress, passive: true },\n\t\t\t{ event: \"loadedmetadata\", handler: () => measureRenderTime() },\n\t\t\t{ event: \"loadeddata\", handler: () => measureRenderTime() }\n\t\t]\n\n\t\teventListeners.forEach(({ event, handler, passive }) => {\n\t\t\tconst options = passive ? { passive: true } : {}\n\t\t\tmedia.addEventListener(event, handler, options)\n\t\t})\n\n\t\t// Performance monitoring frame loop\n\t\tlet rafId: number\n\t\tconst performanceLoop = () => {\n\t\t\tmeasureRenderTime()\n\t\t\trafId = requestAnimationFrame(performanceLoop)\n\t\t}\n\n\t\tif (options.enablePerformanceMonitoring) {\n\t\t\tperformanceLoop()\n\t\t}\n\n\t\treturn () => {\n\t\t\teventListeners.forEach(({ event, handler }) => {\n\t\t\t\tmedia.removeEventListener(event, handler)\n\t\t\t})\n\t\t\tif (rafId) {\n\t\t\t\tcancelAnimationFrame(rafId)\n\t\t\t}\n\t\t}\n\t}, [\n\t\thandleTimeUpdate,\n\t\thandlePlay,\n\t\thandlePause,\n\t\thandleVolumeChange,\n\t\thandleSeeking,\n\t\thandleSeeked,\n\t\thandleProgress,\n\t\tmeasureRenderTime,\n\t\toptions.enablePerformanceMonitoring\n\t])\n\n\t// Optimized control functions with React 19 features\n\tconst controls = useMemo(() => {\n\t\tconst play = async () => {\n\t\t\tconst media = mediaRef.current\n\t\t\tif (!media) return\n\n\t\t\tif (isEnhanced && actions) {\n\t\t\t\tawait actions.play(true) // Optimistic\n\t\t\t} else {\n\t\t\t\ttry {\n\t\t\t\t\tawait media.play()\n\t\t\t\t} catch (error) {\n\t\t\t\t\tconsole.error(\"Failed to play media:\", error)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tconst pause = () => {\n\t\t\tconst media = mediaRef.current\n\t\t\tif (!media) return\n\n\t\t\tif (isEnhanced && actions) {\n\t\t\t\tactions.pause(true) // Optimistic\n\t\t\t} else {\n\t\t\t\tmedia.pause()\n\t\t\t}\n\t\t}\n\n\t\tconst toggle = () => {\n\t\t\tif (isPlaying) {\n\t\t\t\tpause()\n\t\t\t} else {\n\t\t\t\tplay()\n\t\t\t}\n\t\t}\n\n\t\tconst seek = (time: number) => {\n\t\t\tconst media = mediaRef.current\n\t\t\tif (!media) return\n\n\t\t\tconst validDuration = Number.isFinite(duration) && duration > 0 ? duration : Number.isFinite(media.duration) ? media.duration : 0\n\t\t\tif (validDuration === 0) {\n\t\t\t\tconsole.warn(\"Cannot seek: duration is not available\")\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tconst clampedTime = Math.max(0, Math.min(time, validDuration))\n\n\t\t\tif (!Number.isFinite(clampedTime)) {\n\t\t\t\tconsole.warn(`Computed non-finite seek time: ${clampedTime}`)\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tif (isEnhanced && actions) {\n\t\t\t\tstartSeekTransition(() => {\n\t\t\t\t\tactions.seek(clampedTime, true) // Optimistic\n\t\t\t\t})\n\t\t\t} else {\n\t\t\t\tsafeSetCurrentTime(media, clampedTime)\n\t\t\t}\n\t\t}\n\n\t\tconst setVolume = (volume: number) => {\n\t\t\tconst media = mediaRef.current\n\t\t\tif (!media) return\n\n\t\t\tconst clampedVolume = Math.max(0, Math.min(1, volume))\n\n\t\t\tif (isEnhanced && actions) {\n\t\t\t\tsetOptimisticVolume(clampedVolume)\n\t\t\t\tstartTransition(() => {\n\t\t\t\t\tactions.setVolume(clampedVolume, true)\n\t\t\t\t})\n\t\t\t} else {\n\t\t\t\tmedia.volume = clampedVolume\n\t\t\t}\n\t\t}\n\n\t\tconst toggleMute = () => {\n\t\t\tconst media = mediaRef.current\n\t\t\tif (!media) return\n\n\t\t\tif (isEnhanced && actions) {\n\t\t\t\tactions.toggleMute(true) // Optimistic\n\t\t\t} else {\n\t\t\t\tmedia.muted = !media.muted\n\t\t\t}\n\t\t}\n\n\t\tconst enterFullscreen = async () => {\n\t\t\tconst container = containerRef.current\n\t\t\tif (!container || !document.fullscreenEnabled) return\n\n\t\t\ttry {\n\t\t\t\tawait container.requestFullscreen()\n\t\t\t\tif (isEnhanced && actions) {\n\t\t\t\t\tactions.enterFullscreen(true)\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error(\"Failed to enter fullscreen:\", error)\n\t\t\t}\n\t\t}\n\n\t\tconst exitFullscreen = async () => {\n\t\t\tif (!document.fullscreenElement) return\n\n\t\t\ttry {\n\t\t\t\tawait document.exitFullscreen()\n\t\t\t\tif (isEnhanced && actions) {\n\t\t\t\t\tactions.exitFullscreen(true)\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error(\"Failed to exit fullscreen:\", error)\n\t\t\t}\n\t\t}\n\n\t\tconst mute = () => {\n\t\t\tconst media = mediaRef.current\n\t\t\tif (!media) return\n\n\t\t\tif (isEnhanced && actions) {\n\t\t\t\tactions.mute(true)\n\t\t\t} else {\n\t\t\t\tmedia.muted = true\n\t\t\t}\n\t\t}\n\n\t\tconst unmute = () => {\n\t\t\tconst media = mediaRef.current\n\t\t\tif (!media) return\n\n\t\t\tif (isEnhanced && actions) {\n\t\t\t\tactions.unmute(true)\n\t\t\t} else {\n\t\t\t\tmedia.muted = false\n\t\t\t}\n\t\t}\n\n\t\tconst toggleFullscreen = async () => {\n\t\t\tif (isFullscreen) {\n\t\t\t\tawait exitFullscreen()\n\t\t\t} else {\n\t\t\t\tawait enterFullscreen()\n\t\t\t}\n\t\t}\n\n\t\tconst setCurrentTime = (time: number) => {\n\t\t\tconst media = mediaRef.current\n\t\t\tif (!media) return\n\n\t\t\tconst validDuration =\n\t\t\t\tNumber.isFinite(duration) && duration > 0\n\t\t\t\t\t? duration\n\t\t\t\t\t: Number.isFinite(media.duration)\n\t\t\t\t\t\t? media.duration\n\t\t\t\t\t\t: 0\n\n\t\t\tif (validDuration === 0) {\n\t\t\t\tconsole.warn(\"Cannot set currentTime: duration is not available\")\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tconst clampedTime = Math.max(0, Math.min(time, validDuration))\n\n\t\t\tif (!Number.isFinite(clampedTime)) {\n\t\t\t\tconsole.warn(`Computed non-finite currentTime: ${clampedTime}`)\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tsafeSetCurrentTime(media, clampedTime)\n\t\t}\n\n\t\treturn {\n\t\t\tplay,\n\t\t\tpause,\n\t\t\ttoggle,\n\t\t\tseek,\n\t\t\tsetCurrentTime,\n\t\t\tsetVolume,\n\t\t\tmute,\n\t\t\tunmute,\n\t\t\ttoggleMute,\n\t\t\tenterFullscreen,\n\t\t\texitFullscreen,\n\t\t\ttoggleFullscreen\n\t\t}\n\t}, [\n\t\tisPlaying,\n\t\tisFullscreen,\n\t\tduration,\n\t\tisEnhanced,\n\t\tactions,\n\t\tstartTransition,\n\t\tstartSeekTransition,\n\t\tsetOptimisticVolume\n\t])\n\n\t// Computed state\n\tconst computedState = useMemo(\n\t\t() => ({\n\t\t\tisPlaying: optimisticState?.isPlaying ?? isPlaying,\n\t\t\tcurrentTime: optimisticState?.currentTime ?? currentTime,\n\t\t\tduration: optimisticState?.actualState?.duration ?? duration,\n\t\t\tvolume: optimisticState?.volume ?? optimisticVolume,\n\t\t\tisMuted: optimisticState?.isMuted ?? isMuted,\n\t\t\tisLoading: optimisticState?.isBuffering ?? isLoading,\n\t\t\tisBuffering: optimisticState?.isBuffering ?? isBuffering,\n\t\t\terror: optimisticState?.actualState?.error ?? error,\n\t\t\tbuffered: optimisticState?.actualState?.buffered ?? buffered,\n\t\t\tisFullscreen: optimisticState?.isFullscreen ?? isFullscreen,\n\t\t\tprogress: duration > 0 ? currentTime / duration : 0,\n\t\t\tisTransitioning: isPending || isSeeking,\n\t\t\tcanPlay: !isLoading && !isBuffering && !error\n\t\t}),\n\t\t[\n\t\t\toptimisticState,\n\t\t\tisPlaying,\n\t\t\tcurrentTime,\n\t\t\tduration,\n\t\t\toptimisticVolume,\n\t\t\tisMuted,\n\t\t\tisLoading,\n\t\t\tisBuffering,\n\t\t\terror,\n\t\t\tbuffered,\n\t\t\tisFullscreen,\n\t\t\tisPending,\n\t\t\tisSeeking\n\t\t]\n\t)\n\n\treturn {\n\t\t// Refs\n\t\tmediaRef,\n\t\tcontainerRef,\n\n\t\t// State\n\t\tstate: computedState,\n\t\tactualState: optimisticState?.actualState,\n\n\t\t// Controls\n\t\tcontrols,\n\n\t\t// Performance metrics\n\t\tperformanceMetrics,\n\t\tisTransitioning: isPending || isSeeking,\n\n\t\t// Enhanced features\n\t\tactions: optimisticState,\n\t\tactionState: optimisticState,\n\n\t\t// Optimistic features\n\t\toptimisticState,\n\t\tisEnhanced\n\t}\n}\n","\"use client\"\n\nimport { useCallback, useEffect } from \"react\"\nimport type { MediaPlayerControls, MediaPlayerState } from \"../types/index\"\n\ninterface UseKeyboardControlsOptions {\n\tenabled?: boolean\n\tstate: MediaPlayerState\n\tcontrols: MediaPlayerControls\n\tseekStep?: number // seconds to seek forward/backward\n\tvolumeStep?: number // volume step (0-1)\n}\n\nexport function useKeyboardControls({\n\tenabled = true,\n\tstate,\n\tcontrols,\n\tseekStep = 10,\n\tvolumeStep = 0.1\n}: UseKeyboardControlsOptions) {\n\tconst handleKeyDown = (event: KeyboardEvent) => {\n\t\tif (!enabled) return\n\n\t\t// Don't handle keyboard events if user is typing in an input\n\t\tconst target = event.target as HTMLElement\n\t\tif (\n\t\t\ttarget.tagName === \"INPUT\" ||\n\t\t\ttarget.tagName === \"TEXTAREA\" ||\n\t\t\ttarget.contentEditable === \"true\"\n\t\t) {\n\t\t\treturn\n\t\t}\n\n\t\tswitch (event.code) {\n\t\t\tcase \"Space\":\n\t\t\tcase \"KeyK\":\n\t\t\t\tevent.preventDefault()\n\t\t\t\tcontrols.toggle()\n\t\t\t\tbreak\n\n\t\t\tcase \"KeyM\":\n\t\t\t\tevent.preventDefault()\n\t\t\t\tcontrols.toggleMute()\n\t\t\t\tbreak\n\n\t\t\tcase \"KeyF\":\n\t\t\t\tevent.preventDefault()\n\t\t\t\tcontrols.toggleFullscreen()\n\t\t\t\tbreak\n\n\t\t\tcase \"ArrowLeft\":\n\t\t\t\tevent.preventDefault()\n\t\t\t\tcontrols.seek(Math.max(0, state.currentTime - seekStep))\n\t\t\t\tbreak\n\n\t\t\tcase \"ArrowRight\":\n\t\t\t\tevent.preventDefault()\n\t\t\t\tcontrols.seek(Math.min(state.duration, state.currentTime + seekStep))\n\t\t\t\tbreak\n\n\t\t\tcase \"ArrowUp\":\n\t\t\t\tevent.preventDefault()\n\t\t\t\tcontrols.setVolume(Math.min(1, state.volume + volumeStep))\n\t\t\t\tbreak\n\n\t\t\tcase \"ArrowDown\":\n\t\t\t\tevent.preventDefault()\n\t\t\t\tcontrols.setVolume(Math.max(0, state.volume - volumeStep))\n\t\t\t\tbreak\n\n\t\t\tcase \"Digit0\":\n\t\t\tcase \"Digit1\":\n\t\t\tcase \"Digit2\":\n\t\t\tcase \"Digit3\":\n\t\t\tcase \"Digit4\":\n\t\t\tcase \"Digit5\":\n\t\t\tcase \"Digit6\":\n\t\t\tcase \"Digit7\":\n\t\t\tcase \"Digit8\":\n\t\t\tcase \"Digit9\":\n\t\t\t\tevent.preventDefault()\n\t\t\t\tconst digit = parseInt(event.code.replace(\"Digit\", \"\"), 10)\n\t\t\t\tconst percentage = digit / 10\n\t\t\t\tcontrols.seek(state.duration * percentage)\n\t\t\t\tbreak\n\n\t\t\tcase \"Home\":\n\t\t\t\tevent.preventDefault()\n\t\t\t\tcontrols.seek(0)\n\t\t\t\tbreak\n\n\t\t\tcase \"End\":\n\t\t\t\tevent.preventDefault()\n\t\t\t\tcontrols.seek(state.duration)\n\t\t\t\tbreak\n\n\t\t\tdefault:\n\t\t\t\t// Don't prevent default for unhandled keys\n\t\t\t\tbreak\n\t\t}\n\t}\n\n\tuseEffect(() => {\n\t\tif (!enabled) return\n\n\t\tdocument.addEventListener(\"keydown\", handleKeyDown)\n\t\treturn () => {\n\t\t\tdocument.removeEventListener(\"keydown\", handleKeyDown)\n\t\t}\n\t}, [enabled, handleKeyDown])\n\n\treturn {\n\t\thandleKeyDown\n\t}\n}\n","\"use client\"\n\nimport React, { useEffect, useRef, useCallback, useMemo } from \"react\"\n\n// Memory optimization hook for media players\nexport function useMemoryOptimization(\n\toptions: {\n\t\tmaxMemoryUsage?: number // in MB\n\t\tcleanupInterval?: number // in ms\n\t\tenableGC?: boolean\n\t\tmonitorMemory?: boolean\n\t} = {}\n) {\n\tconst {\n\t\tmaxMemoryUsage = 100, // 100MB default\n\t\tcleanupInterval = 30000, // 30 seconds default\n\t\tenableGC = true,\n\t\tmonitorMemory = true\n\t} = options\n\n\tconst cleanupTimeoutRef = useRef<ReturnType<typeof setTimeout> | undefined>(undefined)\n\tconst observersRef = useRef<Set<MutationObserver>>(new Set())\n\tconst eventListenersRef = useRef<Map<Element, Array<{ event: string; handler: EventListener }>>>(\n\t\tnew Map()\n\t)\n\tconst intervalRefs = useRef<Set<ReturnType<typeof setInterval>>>(new Set())\n\tconst animationFrameRefs = useRef<Set<number>>(new Set())\n\n\t// Get current memory usage\n\tconst getMemoryUsage = useCallback(() => {\n\t\tif (typeof window === \"undefined\" || !(\"memory\" in performance)) {\n\t\t\treturn { used: 0, total: 0, limit: 0 }\n\t\t}\n\n\t\tconst memory = (performance as any).memory\n\t\treturn {\n\t\t\tused: memory.usedJSHeapSize,\n\t\t\ttotal: memory.totalJSHeapSize,\n\t\t\tlimit: memory.jsHeapSizeLimit\n\t\t}\n\t}, [])\n\n\t// Memory monitoring state\n\tconst [memoryStats, setMemoryStats] = React.useState({\n\t\tused: 0,\n\t\ttotal: 0,\n\t\tlimit: 0,\n\t\tusage: 0,\n\t\tisHighUsage: false\n\t})\n\n\t// Cleanup function (must be declared before use)\n\tconst performCleanup = useCallback(() => {\n\t\t// Clear all timeouts\n\t\tintervalRefs.current.forEach((timeout) => {\n\t\t\tclearTimeout(timeout)\n\t\t})\n\t\tintervalRefs.current.clear()\n\n\t\t// Cancel all animation frames\n\t\tanimationFrameRefs.current.forEach((frameId) => {\n\t\t\tcancelAnimationFrame(frameId)\n\t\t})\n\t\tanimationFrameRefs.current.clear()\n\n\t\t// Disconnect all observers\n\t\tobserversRef.current.forEach((observer) => {\n\t\t\tobserver.disconnect()\n\t\t})\n\t\tobserversRef.current.clear()\n\n\t\t// Remove all event listeners\n\t\teventListenersRef.current.forEach((listeners, element) => {\n\t\t\tlisteners.forEach(({ event, handler }) => {\n\t\t\t\telement.removeEventListener(event, handler)\n\t\t\t})\n\t\t})\n\t\teventListenersRef.current.clear()\n\n\t\t// Force garbage collection if available\n\t\tif (typeof window !== \"undefined\" && \"gc\" in window) {\n\t\t\t;(window as any).gc()\n\t\t}\n\t}, [])\n\n\t// Safe interval management (must be declared before use)\n\tconst useInterval = useCallback((callback: () => void, delay: number) => {\n\t\tconst timeoutId = globalThis.setInterval(callback, delay)\n\t\tintervalRefs.current.add(timeoutId)\n\n\t\treturn () => {\n\t\t\tglobalThis.clearInterval(timeoutId)\n\t\t\tintervalRefs.current.delete(timeoutId)\n\t\t}\n\t}, [])\n\n\t// Memory monitoring\n\tuseEffect(() => {\n\t\tif (!monitorMemory) return\n\n\t\tconst checkMemory = () => {\n\t\t\tconst memory = getMemoryUsage()\n\t\t\tconst usage = memory.used / 1024 / 1024 // Convert to MB\n\t\t\tconst isHighUsage = usage > maxMemoryUsage\n\n\t\t\tsetMemoryStats({\n\t\t\t\t...memory,\n\t\t\t\tusage,\n\t\t\t\tisHighUsage\n\t\t\t})\n\n\t\t\t// Trigger cleanup if memory usage is high\n\t\t\tif (isHighUsage && enableGC) {\n\t\t\t\tperformCleanup()\n\t\t\t}\n\t\t}\n\n\t\tcheckMemory()\n\t\treturn useInterval(checkMemory, cleanupInterval)\n\t}, [monitorMemory, getMemoryUsage, maxMemoryUsage, enableGC, cleanupInterval, performCleanup])\n\n\t// Safe event listener management\n\tconst addEventListener = useCallback(\n\t\t(\n\t\t\telement: Element,\n\t\t\tevent: string,\n\t\t\thandler: EventListener,\n\t\t\toptions?: AddEventListenerOptions\n\t\t) => {\n\t\t\telement.addEventListener(event, handler, options)\n\n\t\t\tif (!eventListenersRef.current.has(element)) {\n\t\t\t\teventListenersRef.current.set(element, [])\n\t\t\t}\n\t\t\teventListenersRef.current.get(element)!.push({ event, handler })\n\n\t\t\t// Return cleanup function\n\t\t\treturn () => {\n\t\t\t\telement.removeEventListener(event, handler)\n\t\t\t\tconst listeners = eventListenersRef.current.get(element)\n\t\t\t\tif (listeners) {\n\t\t\t\t\tconst index = listeners.findIndex((l) => l.event === event && l.handler === handler)\n\t\t\t\t\tif (index > -1) {\n\t\t\t\t\t\tlisteners.splice(index, 1)\n\t\t\t\t\t}\n\t\t\t\t\tif (listeners.length === 0) {\n\t\t\t\t\t\teventListenersRef.current.delete(element)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t[]\n\t)\n\n\t// Safe timeout management\n\tconst useSafeTimeout = useCallback((callback: () => void, delay: number) => {\n\t\tconst timeoutId = globalThis.setTimeout(callback, delay)\n\t\tintervalRefs.current.add(timeoutId)\n\n\t\treturn () => {\n\t\t\tglobalThis.clearTimeout(timeoutId)\n\t\t\tintervalRefs.current.delete(timeoutId)\n\t\t}\n\t}, [])\n\n\t// Safe animation frame management\n\tconst useSafeAnimationFrame = useCallback((callback: FrameRequestCallback) => {\n\t\tconst frameId = globalThis.requestAnimationFrame(callback)\n\t\tanimationFrameRefs.current.add(frameId)\n\n\t\treturn () => {\n\t\t\tglobalThis.cancelAnimationFrame(frameId)\n\t\t\tanimationFrameRefs.current.delete(frameId)\n\t\t}\n\t}, [])\n\n\t// Safe observer management\n\tconst addObserver = useCallback((observer: MutationObserver) => {\n\t\tobserversRef.current.add(observer)\n\n\t\treturn () => {\n\t\t\tobserver.disconnect()\n\t\t\tobserversRef.current.delete(observer)\n\t\t}\n\t}, [])\n\n\t// Cleanup on unmount\n\tuseEffect(() => {\n\t\treturn () => {\n\t\t\tperformCleanup()\n\t\t}\n\t}, [performCleanup])\n\n\treturn {\n\t\t// Memory stats\n\t\tmemoryStats,\n\t\tgetMemoryUsage,\n\n\t\t// Cleanup functions\n\t\tperformCleanup,\n\n\t\t// Safe API functions\n\t\taddEventListener,\n\t\tsetInterval: useInterval,\n\t\tsetTimeout: useSafeTimeout,\n\t\trequestAnimationFrame: useSafeAnimationFrame,\n\t\taddObserver,\n\n\t\t// Utilities\n\t\tformatBytes: (bytes: number) => {\n\t\t\tif (bytes === 0) return \"0 Bytes\"\n\t\t\tconst k = 1024\n\t\t\tconst sizes = [\"Bytes\", \"KB\", \"MB\", \"GB\"]\n\t\t\tconst i = Math.floor(Math.log(bytes) / Math.log(k))\n\t\t\treturn parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + \" \" + sizes[i]\n\t\t}\n\t}\n}\n\n// Resource cleanup hook for media elements\nexport function useMediaResourceCleanup(\n\tmediaRef: React.RefObject<HTMLVideoElement | HTMLAudioElement>\n) {\n\tconst { addEventListener, performCleanup } = useMemoryOptimization()\n\n\t// Track resource cleanup\n\tconst cleanupResources = useCallback(() => {\n\t\tconst media = mediaRef.current\n\t\tif (!media) return\n\n\t\t// Stop media playback\n\t\tif (!media.paused) {\n\t\t\tmedia.pause()\n\t\t}\n\n\t\t// Clear source\n\t\tif (media.src) {\n\t\t\tmedia.src = \"\"\n\t\t\tmedia.load()\n\t\t}\n\n\t\t// Remove source elements\n\t\twhile (media.firstChild) {\n\t\t\tmedia.removeChild(media.firstChild)\n\t\t}\n\n\t\t// Clear any pending seeks\n\t\tmedia.currentTime = 0\n\n\t\t// Clear buffered data\n\t\tif (\"clearBuffered\" in media) {\n\t\t\t;(media as any).clearBuffered()\n\t\t}\n\t}, [mediaRef])\n\n\t// Enhanced event listener registration\n\tconst registerMediaEventListener = useCallback(\n\t\t(event: string, handler: EventListener, options?: AddEventListenerOptions) => {\n\t\t\tconst media = mediaRef.current\n\t\t\tif (!media) return () => {}\n\n\t\t\treturn addEventListener(media, event, handler, options)\n\t\t},\n\t\t[mediaRef, addEventListener]\n\t)\n\n\t// Cleanup on unmount\n\tuseEffect(() => {\n\t\treturn cleanupResources\n\t}, [cleanupResources])\n\n\treturn {\n\t\tcleanupResources,\n\t\tregisterMediaEventListener\n\t}\n}\n\n// Performance monitoring hook\nexport function usePerformanceMonitoring() {\n\tconst [metrics, setMetrics] = React.useState({\n\t\tfps: 0,\n\t\tframeDrops: 0,\n\t\tlongTasks: 0,\n\t\ttotalLongTaskDuration: 0\n\t})\n\n\tconst frameCountRef = useRef(0)\n\tconst lastFrameTimeRef = useRef(performance.now())\n\tconst longTaskObserverRef = useRef<PerformanceObserver | undefined>(undefined)\n\n\t// FPS monitoring\n\tuseEffect(() => {\n\t\tlet rafId: number\n\n\t\tconst measureFrame = () => {\n\t\t\tframeCountRef.current++\n\t\t\tconst now = performance.now()\n\n\t\t\t// Calculate FPS every second\n\t\t\tif (now - lastFrameTimeRef.current >= 1000) {\n\t\t\t\tconst fps = Math.round((frameCountRef.current * 1000) / (now - lastFrameTimeRef.current))\n\t\t\t\tconst expectedFrames = Math.round((now - lastFrameTimeRef.current) / 16.67) // 60fps\n\t\t\t\tconst frameDrops = Math.max(0, expectedFrames - frameCountRef.current)\n\n\t\t\t\tsetMetrics((prev) => ({\n\t\t\t\t\t...prev,\n\t\t\t\t\tfps,\n\t\t\t\t\tframeDrops: prev.frameDrops + frameDrops\n\t\t\t\t}))\n\n\t\t\t\tframeCountRef.current = 0\n\t\t\t\tlastFrameTimeRef.current = now\n\t\t\t}\n\n\t\t\trafId = requestAnimationFrame(measureFrame)\n\t\t}\n\n\t\trafId = requestAnimationFrame(measureFrame)\n\n\t\treturn () => {\n\t\t\tcancelAnimationFrame(rafId)\n\t\t}\n\t}, [])\n\n\t// Long task monitoring\n\tuseEffect(() => {\n\t\tif (!(\"PerformanceObserver\" in window)) return\n\n\t\ttry {\n\t\t\tconst observer = new PerformanceObserver((list) => {\n\t\t\t\tfor (const entry of list.getEntries()) {\n\t\t\t\t\tif (entry.duration > 50) {\n\t\t\t\t\t\t// Long task threshold\n\t\t\t\t\t\tsetMetrics((prev) => ({\n\t\t\t\t\t\t\t...prev,\n\t\t\t\t\t\t\tlongTasks: prev.longTasks + 1,\n\t\t\t\t\t\t\ttotalLongTaskDuration: prev.totalLongTaskDuration + entry.duration\n\t\t\t\t\t\t}))\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t})\n\n\t\t\tobserver.observe({ entryTypes: [\"longtask\"] })\n\t\t\tlongTaskObserverRef.current = observer\n\n\t\t\treturn () => {\n\t\t\t\tobserver.disconnect()\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tconsole.warn(\"Long task monitoring not supported:\", error)\n\t\t}\n\t}, [])\n\n\treturn {\n\t\t...metrics,\n\t\taverageLongTaskDuration:\n\t\t\tmetrics.longTasks > 0 ? metrics.totalLongTaskDuration / metrics.longTasks : 0,\n\t\tisPerformanceGood: metrics.fps >= 50 && metrics.frameDrops < 5\n\t}\n}\n","\"use client\"\n\nimport { useActionState, useCallback, useOptimistic, useState } from \"react\"\nimport { useMediaSelector, useMediaStore } from \"../context/media-context\"\nimport type { EnhancedMediaStore } from \"../context/media-store\"\nimport type { MediaPlayerState } from \"../types/index\"\nimport { useMediaActions } from \"./use-media-actions\"\nimport { useMediaOptimistic } from \"./use-media-optimistic\"\n\n// Legacy hook for backward compatibility\nexport function useMediaState() {\n\tconst [state, setState] = useState<MediaPlayerState>({\n\t\tisPlaying: false,\n\t\tcurrentTime: 0,\n\t\tduration: 0,\n\t\tvolume: 1,\n\t\tisMuted: false,\n\t\tisLoading: false,\n\t\tisFullscreen: false,\n\t\terror: null,\n\t\tbuffered: null\n\t})\n\n\tconst updateState = (updates: Partial<MediaPlayerState>) => {\n\t\tsetState((prev: MediaPlayerState) => ({ ...prev, ...updates }))\n\t}\n\n\tconst setPlaying = (isPlaying: boolean) => {\n\t\tupdateState({ isPlaying })\n\t}\n\n\tconst setCurrentTime = (currentTime: number) => {\n\t\tupdateState({ currentTime })\n\t}\n\n\tconst setDuration = (duration: number) => {\n\t\tupdateState({ duration })\n\t}\n\n\tconst setVolume = (volume: number) => {\n\t\tupdateState({ volume: Math.max(0, Math.min(1, volume)) })\n\t}\n\n\tconst setMuted = (isMuted: boolean) => {\n\t\tupdateState({ isMuted })\n\t}\n\n\tconst setLoading = (isLoading: boolean) => {\n\t\tupdateState({ isLoading })\n\t}\n\n\tconst setFullscreen = (isFullscreen: boolean) => {\n\t\tupdateState({ isFullscreen })\n\t}\n\n\tconst setError = (error: string | null) => {\n\t\tupdateState({ error })\n\t}\n\n\tconst setBuffered = (buffered: TimeRanges | null) => {\n\t\tupdateState({ buffered })\n\t}\n\n\treturn {\n\t\tstate,\n\t\tupdateState,\n\t\tsetPlaying,\n\t\tsetCurrentTime,\n\t\tsetDuration,\n\t\tsetVolume,\n\t\tsetMuted,\n\t\tsetLoading,\n\t\tsetFullscreen,\n\t\tsetError,\n\t\tsetBuffered\n\t}\n}\n\n// React 19 enhanced media state hook\nexport function useEnhancedMediaState() {\n\tconst store = useMediaStore()\n\n\t// Check if this is an enhanced store\n\tconst isEnhanced = \"getOptimisticState\" in store\n\n\t// Always call hooks unconditionally\n\tconst regularState = useMediaState()\n\tconst enhancedStore = store as unknown as EnhancedMediaStore\n\tconst optimisticState = useMediaOptimistic(enhancedStore)\n\tconst actions = useMediaActions(enhancedStore)\n\n\t// Return appropriate state based on store type\n\tif (!isEnhanced) {\n\t\t// Fall back to regular media state if not enhanced\n\t\treturn regularState as any\n\t}\n\n\treturn {\n\t\t// State (optimistic values for immediate UI feedback)\n\t\tstate: optimisticState.state,\n\t\tactualState: optimisticState.actualState,\n\n\t\t// Individual state selectors\n\t\tisPlaying: optimisticState.isPlaying,\n\t\tcurrentTime: optimisticState.currentTime,\n\t\tduration: optimisticState.state.duration,\n\t\tvolume: optimisticState.volume,\n\t\tisMuted: optimisticState.isMuted,\n\t\tisLoading: optimisticState.isBuffering,\n\t\tisFullscreen: optimisticState.isFullscreen,\n\t\terror: optimisticState.state.error,\n\t\tbuffered: optimisticState.state.buffered,\n\n\t\t// Computed values\n\t\tprogress: optimisticState.progress,\n\t\tformattedTime: optimisticState.formattedTime,\n\t\tformattedDuration: optimisticState.formattedDuration,\n\n\t\t// Actions with optimistic updates\n\t\tactions,\n\n\t\t// Action state for loading/error handling\n\t\tisActionLoading: actions.isLoading,\n\t\tactionError: actions.errorMessage,\n\t\tretryLastAction: actions.retryLastAction,\n\n\t\t// Legacy compatibility methods\n\t\tupdateState: (updates: Partial<MediaPlayerState>) => {\n\t\t\t// Map legacy updates to new actions\n\t\t\tif (\"isPlaying\" in updates) {\n\t\t\t\tupdates.isPlaying ? actions.play() : actions.pause()\n\t\t\t}\n\t\t\tif (\"currentTime\" in updates) {\n\t\t\t\tactions.setCurrentTime(updates.currentTime!)\n\t\t\t}\n\t\t\tif (\"duration\" in updates) {\n\t\t\t\tactions.setDuration(updates.duration!)\n\t\t\t}\n\t\t\tif (\"volume\" in updates) {\n\t\t\t\tactions.setVolume(updates.volume!)\n\t\t\t}\n\t\t\tif (\"isMuted\" in updates) {\n\t\t\t\tupdates.isMuted ? actions.mute() : actions.unmute()\n\t\t\t}\n\t\t\tif (\"isLoading\" in updates) {\n\t\t\t\tactions.setLoading(updates.isLoading!)\n\t\t\t}\n\t\t\tif (\"isFullscreen\" in updates) {\n\t\t\t\tupdates.isFullscreen ? actions.enterFullscreen() : actions.exitFullscreen()\n\t\t\t}\n\t\t\tif (\"error\" in updates) {\n\t\t\t\tactions.setError(updates.error ?? null)\n\t\t\t}\n\t\t\tif (\"buffered\" in updates) {\n\t\t\t\tactions.setBuffered(updates.buffered ?? null)\n\t\t\t}\n\t\t},\n\n\t\t// Individual action methods for legacy compatibility\n\t\tsetPlaying: (isPlaying: boolean) => {\n\t\t\tisPlaying ? actions.play(true) : actions.pause(true) // Use optimistic updates\n\t\t},\n\t\tsetCurrentTime: (time: number) => actions.setCurrentTime(time),\n\t\tsetDuration: (duration: number) => actions.setDuration(duration),\n\t\tsetVolume: (volume: number) => actions.setVolume(volume, true),\n\t\tsetMuted: (muted: boolean) => {\n\t\t\tmuted ? actions.mute(true) : actions.unmute(true)\n\t\t},\n\t\tsetLoading: (loading: boolean) => actions.setLoading(loading),\n\t\tsetFullscreen: (fullscreen: boolean) => {\n\t\t\tfullscreen ? actions.enterFullscreen(true) : actions.exitFullscreen(true)\n\t\t},\n\t\tsetError: (error: string | null) => actions.setError(error),\n\t\tsetBuffered: (buffered: TimeRanges | null) => actions.setBuffered(buffered)\n\t}\n}\n\n// Hook that automatically chooses between legacy and enhanced based on context availability\nexport function useAdaptiveMediaState() {\n\t// Always call hooks unconditionally\n\tconst enhancedState = useEnhancedMediaState()\n\tconst regularState = useMediaState()\n\n\t// Check if we're in an enhanced context by testing a property that would only exist in enhanced mode\n\tconst isEnhancedContext = \"getOptimisticState\" in enhancedState\n\n\tif (!isEnhancedContext) {\n\t\t// Fall back to legacy version if not in MediaProvider context\n\t\tconsole.warn(\"MediaStore context not available, using legacy state management\")\n\t\treturn regularState\n\t}\n\n\treturn enhancedState\n}\n","\"use client\"\n\nimport { useCallback, useEffect, useRef } from \"react\"\nimport type { MediaPlayerControls } from \"../types/index\"\nimport { useMediaState } from \"./use-media-state\"\n\ninterface UseMediaPlayerOptions {\n\tsrc: string | string[]\n\tautoPlay?: boolean\n\tloop?: boolean\n\tmuted?: boolean\n\tvolume?: number\n\tpreload?: \"none\" | \"metadata\" | \"auto\"\n\tcrossOrigin?: \"anonymous\" | \"use-credentials\"\n\tplaybackRates?: number[]\n\tkeyboardControls?: boolean\n\tshowControls?: boolean\n\tcustomControls?: boolean\n\tonPlay?: () => void\n\tonPause?: () => void\n\tonTimeUpdate?: (currentTime: number) => void\n\tonDurationChange?: (duration: number) => void\n\tonVolumeChange?: (volume: number) => void\n\tonError?: (error: string) => void\n\tonLoadStart?: () => void\n\tonLoadedData?: () => void\n\tonEnded?: () => void\n}\n\n/**\n * Safely sets currentTime on a media element, ensuring the value is finite\n */\nfunction safeSetCurrentTime(media: HTMLVideoElement | HTMLAudioElement, time: number): boolean {\n\tif (!Number.isFinite(time)) {\n\t\tconsole.warn(`Attempted to set non-finite currentTime: ${time}`)\n\t\treturn false\n\t}\n\n\tif (time < 0) {\n\t\tconsole.warn(`Attempted to set negative currentTime: ${time}`)\n\t\treturn false\n\t}\n\n\ttry {\n\t\tmedia.currentTime = time\n\t\treturn true\n\t} catch (error) {\n\t\tconsole.error(`Failed to set currentTime to ${time}:`, error)\n\t\treturn false\n\t}\n}\n\nexport function useMediaPlayer(options: UseMediaPlayerOptions) {\n\tconst mediaRef = useRef<HTMLVideoElement | HTMLAudioElement>(null)\n\tconst containerRef = useRef<HTMLDivElement>(null)\n\n\tconst {\n\t\tstate,\n\t\tsetPlaying,\n\t\tsetCurrentTime,\n\t\tsetDuration,\n\t\tsetVolume,\n\t\tsetMuted,\n\t\tsetLoading,\n\t\tsetFullscreen,\n\t\tsetError,\n\t\tsetBuffered\n\t} = useMediaState()\n\n\t// Initialize media element with options\n\tuseEffect(() => {\n\t\tconst media = mediaRef.current\n\t\tif (!media) return\n\n\t\t// Set initial properties\n\t\tif (options.volume !== undefined) {\n\t\t\tmedia.volume = options.volume\n\t\t\tsetVolume(options.volume)\n\t\t}\n\t\tif (options.muted !== undefined) {\n\t\t\tmedia.muted = options.muted\n\t\t\tsetMuted(options.muted)\n\t\t}\n\t\tif (options.autoPlay !== undefined) {\n\t\t\tmedia.autoplay = options.autoPlay\n\t\t}\n\t\tif (options.loop !== undefined) {\n\t\t\tmedia.loop = options.loop\n\t\t}\n\t\tif (options.preload !== undefined) {\n\t\t\tmedia.preload = options.preload\n\t\t}\n\t\tif (options.crossOrigin !== undefined) {\n\t\t\tmedia.crossOrigin = options.crossOrigin\n\t\t}\n\t}, [options, setVolume, setMuted])\n\n\t// Event handlers\n\tconst handlePlay = useCallback(() => {\n\t\tsetPlaying(true)\n\t\toptions.onPlay?.()\n\t}, [setPlaying, options])\n\n\tconst handlePause = useCallback(() => {\n\t\tsetPlaying(false)\n\t\toptions.onPause?.()\n\t}, [setPlaying, options])\n\n\tconst handleTimeUpdate = useCallback(() => {\n\t\tconst media = mediaRef.current\n\t\tif (!media) return\n\n\t\tsetCurrentTime(media.currentTime)\n\t\toptions.onTimeUpdate?.(media.currentTime)\n\t}, [setCurrentTime, options])\n\n\tconst handleDurationChange = useCallback(() => {\n\t\tconst media = mediaRef.current\n\t\tif (!media) return\n\n\t\tsetDuration(media.duration)\n\t\toptions.onDurationChange?.(media.duration)\n\t}, [setDuration, options])\n\n\tconst handleVolumeChange = useCallback(() => {\n\t\tconst media = mediaRef.current\n\t\tif (!media) return\n\n\t\tsetVolume(media.volume)\n\t\tsetMuted(media.muted)\n\t\toptions.onVolumeChange?.(media.volume)\n\t}, [setVolume, setMuted, options])\n\n\tconst handleLoadStart = useCallback(() => {\n\t\tsetLoading(true)\n\t\tsetError(null)\n\t\toptions.onLoadStart?.()\n\t}, [setLoading, setError, options])\n\n\tconst handleLoadedData = useCallback(() => {\n\t\tsetLoading(false)\n\t\toptions.onLoadedData?.()\n\t}, [setLoading, options])\n\n\tconst handleError = useCallback(() => {\n\t\tconst media = mediaRef.current\n\t\tif (!media) return\n\n\t\tconst errorMessage = media.error?.message || \"An error occurred while loading the media\"\n\t\tsetError(errorMessage)\n\t\tsetLoading(false)\n\t\toptions.onError?.(errorMessage)\n\t}, [setError, setLoading, options])\n\n\tconst handleEnded = useCallback(() => {\n\t\tsetPlaying(false)\n\t\toptions.onEnded?.()\n\t}, [setPlaying, options])\n\n\tconst handleProgress = useCallback(() => {\n\t\tconst media = mediaRef.current\n\t\tif (!media) return\n\n\t\tsetBuffered(media.buffered)\n\t}, [setBuffered])\n\n\t// Attach event listeners\n\tuseEffect(() => {\n\t\tconst media = mediaRef.current\n\t\tif (!media) return\n\n\t\tmedia.addEventListener(\"play\", handlePlay)\n\t\tmedia.addEventListener(\"pause\", handlePause)\n\t\tmedia.addEventListener(\"timeupdate\", handleTimeUpdate)\n\t\tmedia.addEventListener(\"durationchange\", handleDurationChange)\n\t\tmedia.addEventListener(\"volumechange\", handleVolumeChange)\n\t\tmedia.addEventListener(\"loadstart\", handleLoadStart)\n\t\tmedia.addEventListener(\"loadeddata\", handleLoadedData)\n\t\tmedia.addEventListener(\"error\", handleError)\n\t\tmedia.addEventListener(\"ended\", handleEnded)\n\t\tmedia.addEventListener(\"progress\", handleProgress)\n\n\t\treturn () => {\n\t\t\tmedia.removeEventListener(\"play\", handlePlay)\n\t\t\tmedia.removeEventListener(\"pause\", handlePause)\n\t\t\tmedia.removeEventListener(\"timeupdate\", handleTimeUpdate)\n\t\t\tmedia.removeEventListener(\"durationchange\", handleDurationChange)\n\t\t\tmedia.removeEventListener(\"volumechange\", handleVolumeChange)\n\t\t\tmedia.removeEventListener(\"loadstart\", handleLoadStart)\n\t\t\tmedia.removeEventListener(\"loadeddata\", handleLoadedData)\n\t\t\tmedia.removeEventListener(\"error\", handleError)\n\t\t\tmedia.removeEventListener(\"ended\", handleEnded)\n\t\t\tmedia.removeEventListener(\"progress\", handleProgress)\n\t\t}\n\t}, [\n\t\thandlePlay,\n\t\thandlePause,\n\t\thandleTimeUpdate,\n\t\thandleDurationChange,\n\t\thandleVolumeChange,\n\t\thandleLoadStart,\n\t\thandleLoadedData,\n\t\thandleError,\n\t\thandleEnded,\n\t\thandleProgress\n\t])\n\n\t// Control functions\n\tconst play = useCallback(async () => {\n\t\tconst media = mediaRef.current\n\t\tif (!media) return\n\n\t\ttry {\n\t\t\tawait media.play()\n\t\t} catch (error) {\n\t\t\tconsole.error(\"Failed to play media:\", error)\n\t\t\tsetError(\"Failed to play media\")\n\t\t}\n\t}, [setError])\n\n\tconst pause = useCallback(() => {\n\t\tconst media = mediaRef.current\n\t\tif (!media) return\n\n\t\tmedia.pause()\n\t}, [])\n\n\tconst toggle = useCallback(() => {\n\t\tif (state.isPlaying) {\n\t\t\tpause()\n\t\t} else {\n\t\t\tplay()\n\t\t}\n\t}, [state.isPlaying, pause, play])\n\n\tconst seek = useCallback((time: number) => {\n\t\tconst media = mediaRef.current\n\t\tif (!media) return\n\n\t\tconst duration = Number.isFinite(media.duration) ? media.duration : 0\n\t\tif (duration === 0) {\n\t\t\tconsole.warn(\"Cannot seek: duration is not available\")\n\t\t\treturn\n\t\t}\n\n\t\tconst clampedTime = Math.max(0, Math.min(time, duration))\n\t\tsafeSetCurrentTime(media, clampedTime)\n\t}, [])\n\n\tconst setVolumeControl = useCallback((volume: number) => {\n\t\tconst media = mediaRef.current\n\t\tif (!media) return\n\n\t\tconst clampedVolume = Math.max(0, Math.min(1, volume))\n\t\tmedia.volume = clampedVolume\n\t}, [])\n\n\tconst mute = useCallback(() => {\n\t\tconst media = mediaRef.current\n\t\tif (!media) return\n\n\t\tmedia.muted = true\n\t}, [])\n\n\tconst unmute = useCallback(() => {\n\t\tconst media = mediaRef.current\n\t\tif (!media) return\n\n\t\tmedia.muted = false\n\t}, [])\n\n\tconst toggleMute = useCallback(() => {\n\t\tconst media = mediaRef.current\n\t\tif (!media) return\n\n\t\tmedia.muted = !media.muted\n\t}, [])\n\n\tconst enterFullscreen = useCallback(async () => {\n\t\tconst container = containerRef.current\n\t\tif (!container || !document.fullscreenEnabled) return\n\n\t\ttry {\n\t\t\tawait container.requestFullscreen()\n\t\t\tsetFullscreen(true)\n\t\t} catch (error) {\n\t\t\tconsole.error(\"Failed to enter fullscreen:\", error)\n\t\t}\n\t}, [setFullscreen])\n\n\tconst exitFullscreen = useCallback(async () => {\n\t\tif (!document.fullscreenElement) return\n\n\t\ttry {\n\t\t\tawait document.exitFullscreen()\n\t\t\tsetFullscreen(false)\n\t\t} catch (error) {\n\t\t\tconsole.error(\"Failed to exit fullscreen:\", error)\n\t\t}\n\t}, [setFullscreen])\n\n\tconst toggleFullscreen = useCallback(() => {\n\t\tif (document.fullscreenElement) {\n\t\t\texitFullscreen()\n\t\t} else {\n\t\t\tenterFullscreen()\n\t\t}\n\t}, [exitFullscreen, enterFullscreen])\n\n\t// Listen for fullscreen changes\n\tuseEffect(() => {\n\t\tconst handleFullscreenChange = () => {\n\t\t\tsetFullscreen(!!document.fullscreenElement)\n\t\t}\n\n\t\tdocument.addEventListener(\"fullscreenchange\", handleFullscreenChange)\n\t\treturn () => {\n\t\t\tdocument.removeEventListener(\"fullscreenchange\", handleFullscreenChange)\n\t\t}\n\t}, [setFullscreen])\n\n\tconst controls: MediaPlayerControls = {\n\t\tplay,\n\t\tpause,\n\t\ttoggle,\n\t\tseek,\n\t\tsetCurrentTime: seek,\n\t\tsetVolume: setVolumeControl,\n\t\tmute,\n\t\tunmute,\n\t\ttoggleMute,\n\t\tenterFullscreen,\n\t\texitFullscreen,\n\t\ttoggleFullscreen\n\t}\n\n\treturn {\n\t\tstate,\n\t\tcontrols,\n\t\tmediaRef,\n\t\tcontainerRef\n\t}\n}\n","import * as React from \"react\"\n\n// Mobile breakpoints following mobile-first approach\nconst BREAKPOINTS = {\n mobile: 768,\n tablet: 1024,\n desktop: 1280\n} as const\n\n// Device detection utilities\nfunction detectPlatform(): 'ios' | 'android' | 'desktop' | 'unknown' {\n if (typeof window === 'undefined') return 'unknown'\n \n const userAgent = window.navigator.userAgent.toLowerCase()\n \n if (/iphone|ipad|ipod/.test(userAgent)) return 'ios'\n if (/android/.test(userAgent)) return 'android'\n if (/windows|mac|linux/.test(userAgent)) return 'desktop'\n \n return 'unknown'\n}\n\nfunction isTouchDevice(): boolean {\n if (typeof window === 'undefined') return false\n \n return (\n 'ontouchstart' in window ||\n navigator.maxTouchPoints > 0 ||\n // @ts-ignore - for older browsers\n navigator.msMaxTouchPoints > 0\n )\n}\n\nfunction supportsHaptics(): boolean {\n if (typeof window === 'undefined') return false\n \n // Check for haptic feedback support\n return (\n 'vibrate' in navigator ||\n // @ts-ignore - for newer Vibration API\n 'vibration' in navigator ||\n // @ts-ignore - for iOS haptic feedback\n 'ondevicemotion' in window\n )\n}\n\n// Enhanced device information interface\nexport interface DeviceInfo {\n isMobile: boolean\n isTablet: boolean\n isDesktop: boolean\n isTouchDevice: boolean\n platform: 'ios' | 'android' | 'desktop' | 'unknown'\n supportsHaptics: boolean\n screenSize: {\n width: number\n height: number\n }\n orientation: 'portrait' | 'landscape'\n}\n\n// Legacy hook for backward compatibility\nexport function useIsMobile(): boolean {\n const [isMobile, setIsMobile] = React.useState<boolean | undefined>(undefined)\n\n React.useEffect(() => {\n const mql = window.matchMedia(`(max-width: ${BREAKPOINTS.mobile - 1}px)`)\n const onChange = () => {\n setIsMobile(window.innerWidth < BREAKPOINTS.mobile)\n }\n mql.addEventListener(\"change\", onChange)\n setIsMobile(window.innerWidth < BREAKPOINTS.mobile)\n return () => mql.removeEventListener(\"change\", onChange)\n }, [])\n\n return !!isMobile\n}\n\n// Enhanced mobile detection hook with comprehensive device information\nexport function useDeviceInfo(): DeviceInfo {\n const [deviceInfo, setDeviceInfo] = React.useState<DeviceInfo>(() => {\n if (typeof window === 'undefined') {\n return {\n isMobile: false,\n isTablet: false,\n isDesktop: true,\n isTouchDevice: false,\n platform: 'unknown',\n supportsHaptics: false,\n screenSize: { width: 1920, height: 1080 },\n orientation: 'landscape'\n }\n }\n \n const width = window.innerWidth\n const height = window.innerHeight\n \n return {\n isMobile: width < BREAKPOINTS.mobile,\n isTablet: width >= BREAKPOINTS.mobile && width < BREAKPOINTS.desktop,\n isDesktop: width >= BREAKPOINTS.desktop,\n isTouchDevice: isTouchDevice(),\n platform: detectPlatform(),\n supportsHaptics: supportsHaptics(),\n screenSize: { width, height },\n orientation: width > height ? 'landscape' : 'portrait'\n }\n })\n\n React.useEffect(() => {\n const updateDeviceInfo = () => {\n const width = window.innerWidth\n const height = window.innerHeight\n \n setDeviceInfo({\n isMobile: width < BREAKPOINTS.mobile,\n isTablet: width >= BREAKPOINTS.mobile && width < BREAKPOINTS.desktop,\n isDesktop: width >= BREAKPOINTS.desktop,\n isTouchDevice: isTouchDevice(),\n platform: detectPlatform(),\n supportsHaptics: supportsHaptics(),\n screenSize: { width, height },\n orientation: width > height ? 'landscape' : 'portrait'\n })\n }\n\n // Listen for resize events\n window.addEventListener('resize', updateDeviceInfo)\n \n // Listen for orientation changes\n window.addEventListener('orientationchange', updateDeviceInfo)\n \n // Listen for media query changes for better performance\n const mobileQuery = window.matchMedia(`(max-width: ${BREAKPOINTS.mobile - 1}px)`)\n const tabletQuery = window.matchMedia(`(min-width: ${BREAKPOINTS.mobile}px) and (max-width: ${BREAKPOINTS.desktop - 1}px)`)\n const desktopQuery = window.matchMedia(`(min-width: ${BREAKPOINTS.desktop}px)`)\n \n mobileQuery.addEventListener('change', updateDeviceInfo)\n tabletQuery.addEventListener('change', updateDeviceInfo)\n desktopQuery.addEventListener('change', updateDeviceInfo)\n \n return () => {\n window.removeEventListener('resize', updateDeviceInfo)\n window.removeEventListener('orientationchange', updateDeviceInfo)\n mobileQuery.removeEventListener('change', updateDeviceInfo)\n tabletQuery.removeEventListener('change', updateDeviceInfo)\n desktopQuery.removeEventListener('change', updateDeviceInfo)\n }\n }, [])\n\n return deviceInfo\n}\n\n// Hook for container queries support (Tailwind CSS v4)\nexport function useContainerQuery(containerRef: React.RefObject<HTMLElement>, query: string) {\n const [matches, setMatches] = React.useState(false)\n\n React.useEffect(() => {\n const container = containerRef.current\n if (!container) return\n\n const observer = new ResizeObserver((entries) => {\n for (const entry of entries) {\n const size = entry.contentBoxSize[0]\n const width = size?.inlineSize || 0\n const height = size?.blockSize || 0\n \n // Simple container query evaluation\n // This is a basic implementation - in production you might want to use a library\n const queryMatch = evaluateContainerQuery(query, { width, height })\n setMatches(queryMatch)\n }\n })\n\n observer.observe(container)\n\n return () => {\n observer.disconnect()\n }\n }, [query])\n\n return matches\n}\n\n// Simple container query evaluator\nfunction evaluateContainerQuery(query: string, dimensions: { width: number; height: number }): boolean {\n // Basic implementation - supports (min-width: Xpx) and (max-width: Xpx)\n const minWidthMatch = query.match(/\\(min-width:\\s*(\\d+)px\\)/)\n const maxWidthMatch = query.match(/\\(max-width:\\s*(\\d+)px\\)/)\n \n if (minWidthMatch && minWidthMatch[1]) {\n const minWidth = parseInt(minWidthMatch[1], 10)\n return dimensions.width >= minWidth\n }\n \n if (maxWidthMatch && maxWidthMatch[1]) {\n const maxWidth = parseInt(maxWidthMatch[1], 10)\n return dimensions.width <= maxWidth\n }\n \n return false\n}\n\n// Performance optimization hook for mobile devices\nexport function useMobileOptimizations() {\n const { platform, isMobile } = useDeviceInfo()\n \n React.useEffect(() => {\n if (!isMobile) return\n \n // iOS-specific optimizations\n if (platform === 'ios') {\n // Prevent zoom on double tap for iOS Safari\n const preventZoom = (e: TouchEvent) => {\n if (e.touches.length > 1) {\n e.preventDefault()\n }\n }\n \n document.addEventListener('touchstart', preventZoom, { passive: false })\n \n // Enable momentum scrolling\n ;(document.body.style as any).webkitOverflowScrolling = 'touch'\n \n return () => {\n document.removeEventListener('touchstart', preventZoom)\n }\n }\n \n // Android-specific optimizations\n if (platform === 'android') {\n // Improve touch responsiveness\n document.body.style.touchAction = 'manipulation'\n }\n \n // General mobile optimizations\n // Improve rendering performance\n document.documentElement.style.setProperty('--webkit-transform', 'translateZ(0)')\n document.documentElement.style.setProperty('--transform', 'translateZ(0)')\n \n }, [platform, isMobile])\n}\n\n// Haptic feedback utility\nexport function useHapticFeedback() {\n const { supportsHaptics } = useDeviceInfo()\n \n const triggerHaptic = React.useCallback((type: 'light' | 'medium' | 'heavy' | 'success' | 'warning' | 'error' = 'light') => {\n if (!supportsHaptics) return\n \n // Map haptic types to vibration patterns\n const patterns = {\n light: [10],\n medium: [20],\n heavy: [30],\n success: [10, 10, 10],\n warning: [20, 20],\n error: [50, 20, 50]\n }\n \n const pattern = patterns[type]\n \n if ('vibrate' in navigator) {\n navigator.vibrate(pattern)\n }\n }, [supportsHaptics])\n \n return { triggerHaptic, supportsHaptics }\n}\n","\"use client\"\n\nimport { useDeviceInfo, useHapticFeedback } from \"@rp/ui/hooks/use-mobile\"\nimport * as React from \"react\"\n\n// Gesture types\nexport type GestureType =\n\t| \"tap\"\n\t| \"double-tap\"\n\t| \"long-press\"\n\t| \"swipe-left\"\n\t| \"swipe-right\"\n\t| \"swipe-up\"\n\t| \"swipe-down\"\n\t| \"pinch-in\"\n\t| \"pinch-out\"\n\n// Gesture event data\nexport interface GestureEvent {\n\ttype: GestureType\n\tstartPoint: { x: number; y: number }\n\tcurrentPoint: { x: number; y: number }\n\tvelocity?: { x: number; y: number }\n\tscale?: number\n\trotation?: number\n\tdistance?: number\n\tduration: number\n\tpreventDefault: () => void\n\ttarget: HTMLElement\n}\n\n// Gesture configuration\nexport interface GestureConfig {\n\tenabledGestures?: GestureType[]\n\ttapThreshold?: number // ms\n\tdoubleTapThreshold?: number // ms\n\tlongPressThreshold?: number // ms\n\tswipeThreshold?: number // px\n\tswipeVelocityThreshold?: number // px/ms\n\tpinchThreshold?: number // scale difference\n\trotationThreshold?: number // degrees\n\tenableHapticFeedback?: boolean\n}\n\n// Default configuration\nconst defaultConfig: Required<GestureConfig> = {\n\tenabledGestures: [\n\t\t\"tap\",\n\t\t\"double-tap\",\n\t\t\"long-press\",\n\t\t\"swipe-left\",\n\t\t\"swipe-right\",\n\t\t\"swipe-up\",\n\t\t\"swipe-down\",\n\t\t\"pinch-in\",\n\t\t\"pinch-out\"\n\t],\n\ttapThreshold: 200,\n\tdoubleTapThreshold: 300,\n\tlongPressThreshold: 500,\n\tswipeThreshold: 50,\n\tswipeVelocityThreshold: 0.5,\n\tpinchThreshold: 0.1,\n\trotationThreshold: 15,\n\tenableHapticFeedback: true\n}\n\n// Touch point interface\ninterface TouchPoint {\n\tid: number\n\tx: number\n\ty: number\n\ttimestamp: number\n}\n\n// Gesture state\ninterface GestureState {\n\tisTracking: boolean\n\ttouches: TouchPoint[]\n\tstartTouches: TouchPoint[]\n\tlastTap?: { timestamp: number; point: { x: number; y: number } }\n\tlongPressTimer?: NodeJS.Timeout\n\tinitialDistance?: number\n\tinitialScale?: number\n\tlastScale?: number\n}\n\n// Touch gesture hook\nexport function useTouchGestures(\n\tref: React.RefObject<HTMLElement>,\n\tonGesture: (event: GestureEvent) => void,\n\tconfig: GestureConfig = {}\n) {\n\tconst mergedConfig = { ...defaultConfig, ...config }\n\tconst { isTouchDevice } = useDeviceInfo()\n\tconst { triggerHaptic } = useHapticFeedback()\n\tconst gestureState = React.useRef<GestureState>({\n\t\tisTracking: false,\n\t\ttouches: [],\n\t\tstartTouches: []\n\t})\n\n\t// Helper functions\n\tconst getTouchPoint = (touch: Touch): TouchPoint => ({\n\t\tid: touch.identifier,\n\t\tx: touch.clientX,\n\t\ty: touch.clientY,\n\t\ttimestamp: Date.now()\n\t})\n\n\tconst getDistance = (p1: TouchPoint, p2: TouchPoint): number =>\n\t\tMath.sqrt(Math.pow(p2.x - p1.x, 2) + Math.pow(p2.y - p1.y, 2))\n\n\tconst getVelocity = (start: TouchPoint, end: TouchPoint): { x: number; y: number } => {\n\t\tconst timeDiff = Math.max(end.timestamp - start.timestamp, 1)\n\t\treturn {\n\t\t\tx: (end.x - start.x) / timeDiff,\n\t\t\ty: (end.y - start.y) / timeDiff\n\t\t}\n\t}\n\n\tconst createGestureEvent = (\n\t\ttype: GestureType,\n\t\tstartPoint: TouchPoint,\n\t\tcurrentPoint: TouchPoint,\n\t\tadditionalData: Partial<GestureEvent> = {}\n\t): GestureEvent => ({\n\t\ttype,\n\t\tstartPoint: { x: startPoint.x, y: startPoint.y },\n\t\tcurrentPoint: { x: currentPoint.x, y: currentPoint.y },\n\t\tduration: currentPoint.timestamp - startPoint.timestamp,\n\t\ttarget: ref.current!,\n\t\tpreventDefault: () => {},\n\t\t...additionalData\n\t})\n\n\t// Handle touch start\n\tconst handleTouchStart = React.useCallback(\n\t\t(e: TouchEvent) => {\n\t\t\tif (!mergedConfig.enabledGestures.length) return\n\n\t\t\tconst touches = Array.from(e.touches).map(getTouchPoint)\n\t\t\tconst state = gestureState.current\n\n\t\t\tstate.isTracking = true\n\t\t\tstate.touches = touches\n\t\t\tstate.startTouches = [...touches]\n\n\t\t\t// Clear any existing long press timer\n\t\t\tif (state.longPressTimer) {\n\t\t\t\tclearTimeout(state.longPressTimer)\n\t\t\t}\n\n\t\t\t// Set up long press detection for single touch\n\t\t\tif (touches.length === 1 && mergedConfig.enabledGestures.includes(\"long-press\")) {\n\t\t\t\tstate.longPressTimer = setTimeout(() => {\n\t\t\t\t\tif (state.touches.length === 1 && touches[0]) {\n\t\t\t\t\t\tconst gestureEvent = createGestureEvent(\"long-press\", touches[0], touches[0])\n\t\t\t\t\t\tonGesture(gestureEvent)\n\n\t\t\t\t\t\tif (mergedConfig.enableHapticFeedback) {\n\t\t\t\t\t\t\ttriggerHaptic(\"heavy\")\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}, mergedConfig.longPressThreshold)\n\t\t\t}\n\n\t\t\t// Handle multi-touch gestures\n\t\t\tif (touches.length === 2 && touches[0] && touches[1]) {\n\t\t\t\tstate.initialDistance = getDistance(touches[0], touches[1])\n\t\t\t\tstate.initialScale = 1\n\t\t\t\tstate.lastScale = 1\n\t\t\t}\n\t\t},\n\t\t[mergedConfig, onGesture, triggerHaptic]\n\t)\n\n\t// Handle touch move\n\tconst handleTouchMove = React.useCallback(\n\t\t(e: TouchEvent) => {\n\t\t\tconst state = gestureState.current\n\t\t\tif (!state.isTracking) return\n\n\t\t\tconst touches = Array.from(e.touches).map(getTouchPoint)\n\t\t\tstate.touches = touches\n\n\t\t\t// Handle pinch gesture\n\t\t\tif (touches.length === 2 && state.initialDistance && touches[0] && touches[1]) {\n\t\t\t\tconst currentDistance = getDistance(touches[0], touches[1])\n\t\t\t\tconst scale = currentDistance / state.initialDistance\n\t\t\t\tconst scaleDiff = Math.abs(scale - (state.lastScale || 1))\n\n\t\t\t\tif (scaleDiff > mergedConfig.pinchThreshold) {\n\t\t\t\t\tconst gestureType = scale > (state.lastScale || 1) ? \"pinch-out\" : \"pinch-in\"\n\n\t\t\t\t\tif (mergedConfig.enabledGestures.includes(gestureType)) {\n\t\t\t\t\t\tconst centerPoint = {\n\t\t\t\t\t\t\tx: (touches[0].x + touches[1].x) / 2,\n\t\t\t\t\t\t\ty: (touches[0].y + touches[1].y) / 2,\n\t\t\t\t\t\t\tid: -1,\n\t\t\t\t\t\t\ttimestamp: Date.now()\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst startCenterPoint = {\n\t\t\t\t\t\t\tx: ((state.startTouches[0]?.x ?? 0) + (state.startTouches[1]?.x ?? 0)) / 2,\n\t\t\t\t\t\t\ty: ((state.startTouches[0]?.y ?? 0) + (state.startTouches[1]?.y ?? 0)) / 2,\n\t\t\t\t\t\t\tid: -1,\n\t\t\t\t\t\t\ttimestamp: state.startTouches[0]?.timestamp ?? Date.now()\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst gestureEvent = createGestureEvent(gestureType, startCenterPoint, centerPoint, {\n\t\t\t\t\t\t\tscale,\n\t\t\t\t\t\t\tdistance: currentDistance\n\t\t\t\t\t\t})\n\n\t\t\t\t\t\tonGesture(gestureEvent)\n\t\t\t\t\t\tstate.lastScale = scale\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Clear long press timer on move\n\t\t\tif (state.longPressTimer && touches.length === 1 && state.startTouches[0] && touches[0]) {\n\t\t\t\tconst startTouch = state.startTouches[0]\n\t\t\t\tconst currentTouch = touches[0]\n\t\t\t\tconst distance = getDistance(startTouch, currentTouch)\n\n\t\t\t\tif (distance > mergedConfig.swipeThreshold) {\n\t\t\t\t\tclearTimeout(state.longPressTimer)\n\t\t\t\t\tstate.longPressTimer = undefined\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t[mergedConfig, onGesture]\n\t)\n\n\t// Handle touch end\n\tconst handleTouchEnd = React.useCallback(\n\t\t(e: TouchEvent) => {\n\t\t\tconst state = gestureState.current\n\t\t\tif (!state.isTracking) return\n\n\t\t\tconst endTouches = Array.from(e.changedTouches).map(getTouchPoint)\n\t\t\tconst currentTime = Date.now()\n\n\t\t\t// Clear long press timer\n\t\t\tif (state.longPressTimer) {\n\t\t\t\tclearTimeout(state.longPressTimer)\n\t\t\t\tstate.longPressTimer = undefined\n\t\t\t}\n\n\t\t\t// Handle single touch gestures\n\t\t\tif (\n\t\t\t\tstate.startTouches.length === 1 &&\n\t\t\t\tendTouches.length === 1 &&\n\t\t\t\tstate.startTouches[0] &&\n\t\t\t\tendTouches[0]\n\t\t\t) {\n\t\t\t\tconst startTouch = state.startTouches[0]\n\t\t\t\tconst endTouch = endTouches[0]\n\t\t\t\tconst distance = getDistance(startTouch, endTouch)\n\t\t\t\tconst duration = endTouch.timestamp - startTouch.timestamp\n\n\t\t\t\t// Check for swipe gestures\n\t\t\t\tif (distance > mergedConfig.swipeThreshold) {\n\t\t\t\t\tconst velocity = getVelocity(startTouch, endTouch)\n\t\t\t\t\tconst absVelX = Math.abs(velocity.x)\n\t\t\t\t\tconst absVelY = Math.abs(velocity.y)\n\n\t\t\t\t\tif (\n\t\t\t\t\t\tabsVelX > mergedConfig.swipeVelocityThreshold ||\n\t\t\t\t\t\tabsVelY > mergedConfig.swipeVelocityThreshold\n\t\t\t\t\t) {\n\t\t\t\t\t\tlet gestureType: GestureType\n\n\t\t\t\t\t\tif (absVelX > absVelY) {\n\t\t\t\t\t\t\tgestureType = velocity.x > 0 ? \"swipe-right\" : \"swipe-left\"\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tgestureType = velocity.y > 0 ? \"swipe-down\" : \"swipe-up\"\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (mergedConfig.enabledGestures.includes(gestureType)) {\n\t\t\t\t\t\t\tconst gestureEvent = createGestureEvent(gestureType, startTouch, endTouch, {\n\t\t\t\t\t\t\t\tvelocity,\n\t\t\t\t\t\t\t\tdistance\n\t\t\t\t\t\t\t})\n\n\t\t\t\t\t\t\tonGesture(gestureEvent)\n\n\t\t\t\t\t\t\tif (mergedConfig.enableHapticFeedback) {\n\t\t\t\t\t\t\t\ttriggerHaptic(\"light\")\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// Check for tap gestures\n\t\t\t\telse if (duration < mergedConfig.tapThreshold && distance < mergedConfig.swipeThreshold) {\n\t\t\t\t\t// Check for double tap\n\t\t\t\t\tif (\n\t\t\t\t\t\tstate.lastTap &&\n\t\t\t\t\t\tcurrentTime - state.lastTap.timestamp < mergedConfig.doubleTapThreshold &&\n\t\t\t\t\t\tgetDistance(\n\t\t\t\t\t\t\t{ ...state.lastTap.point, id: -1, timestamp: state.lastTap.timestamp },\n\t\t\t\t\t\t\tendTouch\n\t\t\t\t\t\t) < mergedConfig.swipeThreshold\n\t\t\t\t\t) {\n\t\t\t\t\t\tif (mergedConfig.enabledGestures.includes(\"double-tap\")) {\n\t\t\t\t\t\t\tconst gestureEvent = createGestureEvent(\"double-tap\", startTouch, endTouch)\n\t\t\t\t\t\t\tonGesture(gestureEvent)\n\n\t\t\t\t\t\t\tif (mergedConfig.enableHapticFeedback) {\n\t\t\t\t\t\t\t\ttriggerHaptic(\"medium\")\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tstate.lastTap = undefined\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Single tap\n\t\t\t\t\t\tif (mergedConfig.enabledGestures.includes(\"tap\")) {\n\t\t\t\t\t\t\tconst gestureEvent = createGestureEvent(\"tap\", startTouch, endTouch)\n\t\t\t\t\t\t\tonGesture(gestureEvent)\n\n\t\t\t\t\t\t\tif (mergedConfig.enableHapticFeedback) {\n\t\t\t\t\t\t\t\ttriggerHaptic(\"light\")\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tstate.lastTap = {\n\t\t\t\t\t\t\ttimestamp: currentTime,\n\t\t\t\t\t\t\tpoint: { x: endTouch.x, y: endTouch.y }\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Reset gesture state\n\t\t\tif (e.touches.length === 0) {\n\t\t\t\tstate.isTracking = false\n\t\t\t\tstate.touches = []\n\t\t\t\tstate.startTouches = []\n\t\t\t\tstate.initialDistance = undefined\n\t\t\t\tstate.initialScale = undefined\n\t\t\t\tstate.lastScale = undefined\n\t\t\t}\n\t\t},\n\t\t[mergedConfig, onGesture, triggerHaptic]\n\t)\n\n\t// Attach event listeners\n\tReact.useEffect(() => {\n\t\tconst element = ref.current\n\t\tif (!element || !isTouchDevice) return\n\n\t\telement.addEventListener(\"touchstart\", handleTouchStart, { passive: false })\n\t\telement.addEventListener(\"touchmove\", handleTouchMove, { passive: false })\n\t\telement.addEventListener(\"touchend\", handleTouchEnd, { passive: false })\n\t\telement.addEventListener(\"touchcancel\", handleTouchEnd, { passive: false })\n\n\t\treturn () => {\n\t\t\telement.removeEventListener(\"touchstart\", handleTouchStart)\n\t\t\telement.removeEventListener(\"touchmove\", handleTouchMove)\n\t\t\telement.removeEventListener(\"touchend\", handleTouchEnd)\n\t\t\telement.removeEventListener(\"touchcancel\", handleTouchEnd)\n\t\t}\n\t}, [handleTouchStart, handleTouchMove, handleTouchEnd, isTouchDevice])\n\n\treturn {\n\t\tisGestureEnabled: isTouchDevice && mergedConfig.enabledGestures.length > 0\n\t}\n}\n\n// Media player specific gesture hook with predefined actions\nexport function useMediaGestures(\n\tref: React.RefObject<HTMLElement>,\n\tactions: {\n\t\tonPlayPause?: () => void\n\t\tonSeek?: (direction: \"forward\" | \"backward\", amount: number) => void\n\t\tonVolumeChange?: (direction: \"up\" | \"down\", amount: number) => void\n\t\tonToggleFullscreen?: () => void\n\t\tonZoom?: (scale: number) => void\n\t}\n) {\n\tconst handleGesture = React.useCallback(\n\t\t(event: GestureEvent) => {\n\t\t\tconst { type, velocity, distance, scale } = event\n\n\t\t\tswitch (type) {\n\t\t\t\tcase \"double-tap\":\n\t\t\t\t\t// Double tap to play/pause\n\t\t\t\t\tactions.onPlayPause?.()\n\t\t\t\t\tbreak\n\n\t\t\t\tcase \"swipe-left\":\n\t\t\t\t\t// Swipe left to seek backward\n\t\t\t\t\tconst backwardAmount = Math.min((distance || 0) / 10, 30) // Max 30 seconds\n\t\t\t\t\tactions.onSeek?.(\"backward\", backwardAmount)\n\t\t\t\t\tbreak\n\n\t\t\t\tcase \"swipe-right\":\n\t\t\t\t\t// Swipe right to seek forward\n\t\t\t\t\tconst forwardAmount = Math.min((distance || 0) / 10, 30) // Max 30 seconds\n\t\t\t\t\tactions.onSeek?.(\"forward\", forwardAmount)\n\t\t\t\t\tbreak\n\n\t\t\t\tcase \"swipe-up\":\n\t\t\t\t\t// Swipe up on right side for volume up\n\t\t\t\t\tif (event.startPoint.x > (ref.current?.clientWidth || 0) / 2) {\n\t\t\t\t\t\tconst volumeAmount = Math.min((distance || 0) / 100, 0.2) // Max 20%\n\t\t\t\t\t\tactions.onVolumeChange?.(\"up\", volumeAmount)\n\t\t\t\t\t}\n\t\t\t\t\tbreak\n\n\t\t\t\tcase \"swipe-down\":\n\t\t\t\t\t// Swipe down on right side for volume down\n\t\t\t\t\tif (event.startPoint.x > (ref.current?.clientWidth || 0) / 2) {\n\t\t\t\t\t\tconst volumeAmount = Math.min((distance || 0) / 100, 0.2) // Max 20%\n\t\t\t\t\t\tactions.onVolumeChange?.(\"down\", volumeAmount)\n\t\t\t\t\t}\n\t\t\t\t\tbreak\n\n\t\t\t\tcase \"pinch-out\":\n\t\t\t\t\t// Pinch out to zoom in (for video zoom functionality)\n\t\t\t\t\tactions.onZoom?.(scale || 1)\n\t\t\t\t\tbreak\n\n\t\t\t\tcase \"pinch-in\":\n\t\t\t\t\t// Pinch in to zoom out\n\t\t\t\t\tactions.onZoom?.(scale || 1)\n\t\t\t\t\tbreak\n\n\t\t\t\tcase \"long-press\":\n\t\t\t\t\t// Long press for fullscreen toggle\n\t\t\t\t\tactions.onToggleFullscreen?.()\n\t\t\t\t\tbreak\n\n\t\t\t\tdefault:\n\t\t\t\t\tbreak\n\t\t\t}\n\t\t},\n\t\t[actions, ref]\n\t)\n\n\tconst gestureConfig: GestureConfig = {\n\t\tenabledGestures: [\n\t\t\t\"tap\",\n\t\t\t\"double-tap\",\n\t\t\t\"long-press\",\n\t\t\t\"swipe-left\",\n\t\t\t\"swipe-right\",\n\t\t\t\"swipe-up\",\n\t\t\t\"swipe-down\",\n\t\t\t\"pinch-in\",\n\t\t\t\"pinch-out\"\n\t\t],\n\t\tenableHapticFeedback: true,\n\t\tswipeThreshold: 30,\n\t\tswipeVelocityThreshold: 0.3\n\t}\n\n\treturn useTouchGestures(ref, handleGesture, gestureConfig)\n}\n","import { useCallback, useEffect, useMemo, useState } from \"react\"\n\ninterface SubtitleCue {\n\tstart: number\n\tend: number\n\ttext: string\n}\n\nexport interface SubtitleTrack {\n\tid: string\n\tlabel: string\n\tlanguage?: string\n\tsrc?: string\n}\n\nexport interface UseEnhancedSubtitlesOptions {\n\tsubtitleSrc?: string\n\tsubtitleTracks?: SubtitleTrack[]\n\tdefaultFontSize?: \"small\" | \"medium\" | \"large\"\n\tonLoadError?: (error: Error) => void\n}\n\nexport function useEnhancedSubtitles({\n\tsubtitleSrc,\n\tsubtitleTracks = [],\n\tdefaultFontSize = \"medium\",\n\tonLoadError\n}: UseEnhancedSubtitlesOptions = {}) {\n\tconst [subtitlesEnabled, setSubtitlesEnabled] = useState(false)\n\tconst [subtitleCues, setSubtitleCues] = useState<SubtitleCue[]>([])\n\tconst [currentSubtitle, setCurrentSubtitle] = useState(\"\")\n\tconst [currentTrackId, setCurrentTrackId] = useState<string | null>(null)\n\tconst [fontSize, setFontSize] = useState<\"small\" | \"medium\" | \"large\">(defaultFontSize)\n\tconst [loadError, setLoadError] = useState<Error | null>(null)\n\tconst [isLoading, setIsLoading] = useState(false)\n\n\t// Size mapping for subtitle font sizes\n\tconst sizeMap = {\n\t\tsmall: \"text-sm\",\n\t\tmedium: \"text-base\",\n\t\tlarge: \"text-lg\"\n\t}\n\n\t// Determine if subtitles are available\n\tconst hasSubtitles = !!(subtitleSrc || (subtitleTracks && subtitleTracks.length > 0))\n\n\t// Parse VTT/WebVTT timestamp\n\tconst parseVTTTime = (timeStr: string): number => {\n\t\tconst parts = timeStr.split(\":\")\n\t\tconst seconds = parts[2] ? parseFloat(parts[2]) : 0\n\t\tconst minutes = parts[1] ? parseInt(parts[1], 10) * 60 : 0\n\t\tconst hours = parts[0] ? parseInt(parts[0], 10) * 3600 : 0\n\t\treturn hours + minutes + seconds\n\t}\n\n\t// Parse SRT timestamp\n\tconst parseSRTTime = (timeStr: string): number => {\n\t\t// SRT format: 00:00:00,000 (hours:minutes:seconds,milliseconds)\n\t\tconst [time, ms] = timeStr.split(\",\")\n\t\tconst parts = (time || \"\").split(\":\")\n\t\tconst milliseconds = ms ? parseInt(ms, 10) / 1000 : 0\n\t\tconst seconds = parts[2] ? parseInt(parts[2], 10) : 0\n\t\tconst minutes = parts[1] ? parseInt(parts[1], 10) * 60 : 0\n\t\tconst hours = parts[0] ? parseInt(parts[0], 10) * 3600 : 0\n\t\treturn hours + minutes + seconds + milliseconds\n\t}\n\n\t// Load and parse subtitle file\n\tconst loadSubtitles = async (url: string) => {\n\t\tsetIsLoading(true)\n\t\tsetLoadError(null)\n\n\t\ttry {\n\t\t\tconst response = await fetch(url)\n\t\t\tif (!response.ok) {\n\t\t\t\tthrow new Error(`Failed to load subtitles: ${response.status} ${response.statusText}`)\n\t\t\t}\n\n\t\t\tconst text = await response.text()\n\t\t\tconst cues: SubtitleCue[] = []\n\t\t\tconst lines = text.split(\"\\n\")\n\t\t\tlet i = 0\n\n\t\t\t// Detect format (VTT or SRT)\n\t\t\tconst isVTT = text.includes(\"WEBVTT\") || url.endsWith(\".vtt\")\n\t\t\tconst isSRT = url.endsWith(\".srt\") || /^\\d+$/.test(lines[0]?.trim() || \"\")\n\n\t\t\tif (isVTT) {\n\t\t\t\t// Parse VTT format\n\t\t\t\twhile (i < lines.length) {\n\t\t\t\t\tif (lines[i]?.includes(\"-->\")) {\n\t\t\t\t\t\tconst [startStr, endStr] = (lines[i] || \"\").split(\"-->\").map((s) => s.trim())\n\t\t\t\t\t\tconst start = parseVTTTime(startStr || \"\")\n\t\t\t\t\t\tconst end = parseVTTTime(endStr || \"\")\n\n\t\t\t\t\t\ti++\n\t\t\t\t\t\tlet subtitleText = \"\"\n\t\t\t\t\t\twhile (i < lines.length && lines[i]?.trim() !== \"\") {\n\t\t\t\t\t\t\tsubtitleText += (subtitleText ? \" \" : \"\") + lines[i]?.trim()\n\t\t\t\t\t\t\ti++\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (subtitleText) {\n\t\t\t\t\t\t\tcues.push({ start, end, text: subtitleText })\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\ti++\n\t\t\t\t}\n\t\t\t} else if (isSRT) {\n\t\t\t\t// Parse SRT format\n\t\t\t\twhile (i < lines.length) {\n\t\t\t\t\t// Skip the sequence number\n\t\t\t\t\tif (/^\\d+$/.test(lines[i]?.trim() || \"\")) {\n\t\t\t\t\t\ti++\n\t\t\t\t\t\t// Parse timestamp line\n\t\t\t\t\t\tif (lines[i]?.includes(\"-->\")) {\n\t\t\t\t\t\t\tconst [startStr, endStr] = (lines[i] || \"\").split(\"-->\").map((s) => s.trim())\n\t\t\t\t\t\t\tconst start = parseSRTTime(startStr || \"\")\n\t\t\t\t\t\t\tconst end = parseSRTTime(endStr || \"\")\n\n\t\t\t\t\t\t\ti++\n\t\t\t\t\t\t\tlet subtitleText = \"\"\n\t\t\t\t\t\t\twhile (i < lines.length && lines[i]?.trim() !== \"\") {\n\t\t\t\t\t\t\t\tsubtitleText += (subtitleText ? \" \" : \"\") + lines[i]?.trim()\n\t\t\t\t\t\t\t\ti++\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (subtitleText) {\n\t\t\t\t\t\t\t\tcues.push({ start, end, text: subtitleText })\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\ti++\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthrow new Error(\"Unsupported subtitle format. Only VTT and SRT are supported.\")\n\t\t\t}\n\n\t\t\tif (cues.length === 0) {\n\t\t\t\tthrow new Error(\"No subtitle cues found in file\")\n\t\t\t}\n\n\t\t\tsetSubtitleCues(cues)\n\t\t\tsetIsLoading(false)\n\t\t} catch (error) {\n\t\t\tconst err = error instanceof Error ? error : new Error(\"Failed to load subtitles\")\n\t\t\tconsole.error(\"Failed to load subtitles:\", err)\n\t\t\tsetLoadError(err)\n\t\t\tsetIsLoading(false)\n\t\t\tsetSubtitleCues([])\n\t\t\tonLoadError?.(err)\n\t\t}\n\t}\n\n\t// Get current subtitle text based on time\n\tconst getCurrentSubtitle = (currentTime: number) => {\n\t\tif (!subtitlesEnabled || subtitleCues.length === 0) return \"\"\n\n\t\tconst currentCue = subtitleCues.find(\n\t\t\t(cue) => currentTime >= cue.start && currentTime <= cue.end\n\t\t)\n\t\treturn currentCue?.text || \"\"\n\t}\n\n\t// Toggle subtitles on/off\n\tconst toggleSubtitles = () => {\n\t\tsetSubtitlesEnabled((prev) => {\n\t\t\tconst newEnabled = !prev\n\n\t\t\tif (newEnabled && !loadError) {\n\t\t\t\t// Try to load subtitles if not already loaded\n\t\t\t\tif (subtitleCues.length === 0 && !isLoading) {\n\t\t\t\t\t// Load default subtitle source or first track\n\t\t\t\t\tconst srcToLoad = subtitleSrc || subtitleTracks[0]?.src\n\t\t\t\t\tif (srcToLoad) {\n\t\t\t\t\t\tloadSubtitles(srcToLoad)\n\t\t\t\t\t\tif (subtitleTracks[0]) {\n\t\t\t\t\t\t\tsetCurrentTrackId(subtitleTracks[0].id)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if (!newEnabled) {\n\t\t\t\tsetCurrentSubtitle(\"\")\n\t\t\t}\n\n\t\t\treturn newEnabled\n\t\t})\n\t}\n\n\t// Select a specific subtitle track\n\tconst selectSubtitleTrack = (trackId: string | null) => {\n\t\tif (!trackId) {\n\t\t\t// Turn off subtitles\n\t\t\tsetSubtitlesEnabled(false)\n\t\t\tsetCurrentTrackId(null)\n\t\t\tsetCurrentSubtitle(\"\")\n\t\t\treturn\n\t\t}\n\n\t\tconst track = subtitleTracks.find((t) => t.id === trackId)\n\t\tif (track?.src) {\n\t\t\tsetCurrentTrackId(trackId)\n\t\t\tloadSubtitles(track.src)\n\t\t\tsetSubtitlesEnabled(true)\n\t\t}\n\t}\n\n\t// Change subtitle font size\n\tconst changeSubtitleFontSize = (size: \"small\" | \"medium\" | \"large\") => {\n\t\tsetFontSize(size)\n\t}\n\n\t// Get CSS classes for subtitle display\n\tconst getSubtitleStyles = {\n\t\tfontSize: sizeMap[fontSize],\n\t\tclassName: `${sizeMap[fontSize]} font-medium`\n\t}\n\n\t// Clear subtitle on disable\n\tuseEffect(() => {\n\t\tif (!subtitlesEnabled) {\n\t\t\tsetCurrentSubtitle(\"\")\n\t\t}\n\t}, [subtitlesEnabled])\n\n\t// Auto-load default subtitles on mount if available\n\tuseEffect(() => {\n\t\tif (subtitleSrc && !subtitleCues.length && !loadError && !isLoading) {\n\t\t\t// Don't auto-load, wait for user to enable\n\t\t\t// This prevents errors on initial load\n\t\t}\n\t}, [])\n\n\treturn {\n\t\t// State\n\t\tsubtitlesEnabled,\n\t\tcurrentSubtitle,\n\t\tsubtitleCues,\n\t\tcurrentTrackId,\n\t\tfontSize,\n\t\tloadError,\n\t\tisLoading,\n\t\thasSubtitles,\n\n\t\t// Actions\n\t\ttoggleSubtitles,\n\t\tselectSubtitleTrack,\n\t\tchangeSubtitleFontSize,\n\t\tsetCurrentSubtitle,\n\n\t\t// Utilities\n\t\tgetCurrentSubtitle,\n\t\tgetSubtitleStyles,\n\n\t\t// Track info\n\t\tavailableTracks: subtitleTracks\n\t}\n}\n","import { useCallback, useEffect } from \"react\"\nimport type { VideoControls } from \"./useVideoPlayer\"\n\ninterface UseKeyboardShortcutsProps {\n\tvideoControls: VideoControls\n\ttoggleSubtitles: () => void\n\ttakeScreenshot: (ctrlKey?: boolean) => void\n\tduration: number\n}\n\n/**\n * Safely sets currentTime on a video element, ensuring the value is finite\n */\nfunction safeSetCurrentTime(video: HTMLVideoElement, time: number): boolean {\n\tif (!Number.isFinite(time)) {\n\t\tconsole.warn(`Attempted to set non-finite currentTime: ${time}`)\n\t\treturn false\n\t}\n\n\tif (time < 0) {\n\t\tconsole.warn(`Attempted to set negative currentTime: ${time}`)\n\t\treturn false\n\t}\n\n\ttry {\n\t\tvideo.currentTime = time\n\t\treturn true\n\t} catch (error) {\n\t\tconsole.error(`Failed to set currentTime to ${time}:`, error)\n\t\treturn false\n\t}\n}\n\nexport function useKeyboardShortcuts({\n\tvideoControls,\n\ttoggleSubtitles,\n\ttakeScreenshot,\n\tduration\n}: UseKeyboardShortcutsProps) {\n\tconst handleKeyDown = (e: KeyboardEvent) => {\n\t\tconst video = document.querySelector(\"video\")\n\t\tif (!video) return\n\n\t\tswitch (e.key.toLowerCase()) {\n\t\t\tcase \" \":\n\t\t\tcase \"k\":\n\t\t\t\te.preventDefault()\n\t\t\t\tvideoControls.togglePlay()\n\t\t\t\tbreak\n\t\t\tcase \"j\":\n\t\t\t\te.preventDefault()\n\t\t\t\tvideoControls.seekBackward()\n\t\t\t\tbreak\n\t\t\tcase \"l\":\n\t\t\t\te.preventDefault()\n\t\t\t\tvideoControls.seekForward()\n\t\t\t\tbreak\n\t\t\tcase \"arrowleft\":\n\t\t\t\te.preventDefault()\n\t\t\t\tconst currentTime = Number.isFinite(video.currentTime) ? video.currentTime : 0\n\t\t\t\tconst newTimeLeft = Math.max(0, currentTime - 5)\n\t\t\t\tsafeSetCurrentTime(video, newTimeLeft)\n\t\t\t\tbreak\n\t\t\tcase \"arrowright\":\n\t\t\t\te.preventDefault()\n\t\t\t\tconst validDuration = Number.isFinite(duration) && duration > 0 ? duration : Number.isFinite(video.duration) ? video.duration : 0\n\t\t\t\tif (validDuration === 0) {\n\t\t\t\t\tconsole.warn(\"Cannot seek: duration is not available\")\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tconst currentTimeRight = Number.isFinite(video.currentTime) ? video.currentTime : 0\n\t\t\t\tconst newTimeRight = Math.min(validDuration, currentTimeRight + 5)\n\t\t\t\tsafeSetCurrentTime(video, newTimeRight)\n\t\t\t\tbreak\n\t\t\tcase \"arrowup\":\n\t\t\t\te.preventDefault()\n\t\t\t\tvideo.volume = Math.min(1, video.volume + 0.1)\n\t\t\t\tbreak\n\t\t\tcase \"arrowdown\":\n\t\t\t\te.preventDefault()\n\t\t\t\tvideo.volume = Math.max(0, video.volume - 0.1)\n\t\t\t\tbreak\n\t\t\tcase \"m\":\n\t\t\t\te.preventDefault()\n\t\t\t\tvideoControls.toggleMute()\n\t\t\t\tbreak\n\t\t\tcase \"f\":\n\t\t\t\te.preventDefault()\n\t\t\t\tvideoControls.toggleFullscreen()\n\t\t\t\tbreak\n\t\t\tcase \"c\":\n\t\t\t\te.preventDefault()\n\t\t\t\ttoggleSubtitles()\n\t\t\t\tbreak\n\t\t\tcase \"s\":\n\t\t\t\te.preventDefault()\n\t\t\t\ttakeScreenshot(e.ctrlKey || e.metaKey)\n\t\t\t\tbreak\n\t\t}\n\t}\n\n\tuseEffect(() => {\n\t\tdocument.addEventListener(\"keydown\", handleKeyDown)\n\t\treturn () => document.removeEventListener(\"keydown\", handleKeyDown)\n\t}, [handleKeyDown])\n}\n","import { useCallback, useEffect, useRef, useState } from \"react\"\n\nexport function useMediaControls(isPlaying: boolean, showSettings: boolean) {\n\tconst [controlsVisible, setControlsVisible] = useState(true)\n\tconst [showVolumeSlider, setShowVolumeSlider] = useState(false)\n\tconst hideTimeoutRef = useRef<NodeJS.Timeout | null>(null)\n\n\tconst showControls = () => {\n\t\tsetControlsVisible(true)\n\t\tif (hideTimeoutRef.current) {\n\t\t\tclearTimeout(hideTimeoutRef.current)\n\t\t}\n\n\t\tif (isPlaying && !showSettings) {\n\t\t\thideTimeoutRef.current = setTimeout(() => {\n\t\t\t\tsetControlsVisible(false)\n\t\t\t}, 3000)\n\t\t}\n\t}\n\n\tconst handleMouseMove = () => {\n\t\tshowControls()\n\t}\n\n\tconst handleMouseEnter = () => {\n\t\tsetControlsVisible(true)\n\t}\n\n\tconst handleMouseLeave = () => {\n\t\tif (isPlaying) {\n\t\t\tsetControlsVisible(false)\n\t\t}\n\t}\n\n\tuseEffect(() => {\n\t\tshowControls()\n\t\treturn () => {\n\t\t\tif (hideTimeoutRef.current) {\n\t\t\t\tclearTimeout(hideTimeoutRef.current)\n\t\t\t}\n\t\t}\n\t}, [showControls])\n\n\treturn {\n\t\tcontrolsVisible,\n\t\tshowVolumeSlider,\n\t\tsetShowVolumeSlider,\n\t\thandleMouseMove,\n\t\thandleMouseEnter,\n\t\thandleMouseLeave\n\t}\n}\n","import { useCallback } from \"react\"\n\nexport function useScreenshot(videoRef: React.RefObject<HTMLVideoElement | null>) {\n\tconst takeScreenshot = (ctrlKey: boolean = false) => {\n\t\tif (!videoRef.current) return\n\n\t\tconst video = videoRef.current\n\t\tconst canvas = document.createElement(\"canvas\")\n\t\tcanvas.width = video.videoWidth\n\t\tcanvas.height = video.videoHeight\n\t\tconst ctx = canvas.getContext(\"2d\")\n\t\tif (!ctx) return\n\n\t\ttry {\n\t\t\t// Draw the video frame to canvas\n\t\t\tctx.drawImage(video, 0, 0)\n\n\t\t\t// Try to export the canvas\n\t\t\tcanvas.toBlob((blob) => {\n\t\t\t\tif (!blob) {\n\t\t\t\t\tconsole.error(\"Failed to create blob from canvas\")\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tif (ctrlKey) {\n\t\t\t\t\t// Copy to clipboard\n\t\t\t\t\tif (navigator.clipboard && window.ClipboardItem) {\n\t\t\t\t\t\tconst item = new ClipboardItem({ \"image/png\": blob })\n\t\t\t\t\t\tnavigator.clipboard.write([item]).catch((err) => {\n\t\t\t\t\t\t\tconsole.error(\"Failed to copy to clipboard:\", err)\n\t\t\t\t\t\t})\n\t\t\t\t\t} else {\n\t\t\t\t\t\tconsole.warn(\"Clipboard API not supported\")\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// Download\n\t\t\t\t\tconst url = URL.createObjectURL(blob)\n\t\t\t\t\tconst a = document.createElement(\"a\")\n\t\t\t\t\ta.href = url\n\t\t\t\t\ta.download = `screenshot-${Date.now()}.png`\n\t\t\t\t\ta.click()\n\t\t\t\t\tURL.revokeObjectURL(url)\n\t\t\t\t}\n\t\t\t}, \"image/png\")\n\t\t} catch (error) {\n\t\t\tif (error instanceof Error && error.message.includes(\"tainted\")) {\n\t\t\t\tconsole.error(\n\t\t\t\t\t\"Canvas is tainted - video source may not have proper CORS headers. Try setting crossOrigin='anonymous' on the video element.\"\n\t\t\t\t)\n\t\t\t\talert(\n\t\t\t\t\t\"Screenshot failed: The video source doesn't allow screenshots due to CORS policy. Please ensure the video server includes proper CORS headers or set crossOrigin='anonymous' on the video player.\"\n\t\t\t\t)\n\t\t\t} else {\n\t\t\t\tconsole.error(\"Screenshot failed:\", error)\n\t\t\t\talert(\"Screenshot failed: \" + (error instanceof Error ? error.message : \"Unknown error\"))\n\t\t\t}\n\t\t}\n\t}\n\n\treturn { takeScreenshot }\n}\n","import { useCallback, useEffect, useRef, useState } from \"react\"\n\nexport interface BufferedRange {\n\tstart: number\n\tend: number\n\tpercentage: number\n}\n\nexport interface VideoState {\n\tisPlaying: boolean\n\tcurrentTime: number\n\tduration: number\n\tvolume: number\n\tisMuted: boolean\n\tisFullscreen: boolean\n\tisLoading: boolean\n\tisSeeking: boolean\n\tisBuffering: boolean\n\tbufferedRanges: BufferedRange[]\n}\n\nexport interface VideoControls {\n\ttogglePlay: () => void\n\tseekForward: (seconds?: number) => void\n\tseekBackward: (seconds?: number) => void\n\ttoggleMute: () => void\n\tsetVolume: (volume: number) => void\n\ttoggleFullscreen: () => void\n\tseekTo: (time: number) => void\n}\n\n/**\n * Safely sets currentTime on a video element, ensuring the value is finite\n * @param video - The video element\n * @param time - The desired time value\n * @returns true if successfully set, false otherwise\n */\nfunction safeSetCurrentTime(video: HTMLVideoElement, time: number): boolean {\n\tif (!Number.isFinite(time)) {\n\t\tconsole.warn(`Attempted to set non-finite currentTime: ${time}`)\n\t\treturn false\n\t}\n\n\tif (time < 0) {\n\t\tconsole.warn(`Attempted to set negative currentTime: ${time}`)\n\t\treturn false\n\t}\n\n\ttry {\n\t\tvideo.currentTime = time\n\t\treturn true\n\t} catch (error) {\n\t\tconsole.error(`Failed to set currentTime to ${time}:`, error)\n\t\treturn false\n\t}\n}\n\nexport function useVideoPlayer(containerRef: React.RefObject<HTMLDivElement | null>) {\n\tconst videoRef = useRef<HTMLVideoElement>(null)\n\tconst [state, setState] = useState<VideoState>({\n\t\tisPlaying: false,\n\t\tcurrentTime: 0,\n\t\tduration: 0,\n\t\tvolume: 1,\n\t\tisMuted: false,\n\t\tisFullscreen: false,\n\t\tisLoading: true,\n\t\tisSeeking: false,\n\t\tisBuffering: false,\n\t\tbufferedRanges: []\n\t})\n\n\tuseEffect(() => {\n\t\tconst video = videoRef.current\n\t\tif (!video) return\n\n\t\tconst handleTimeUpdate = () => {\n\t\t\tsetState((prev) => ({ ...prev, currentTime: video.currentTime }))\n\t\t}\n\n\t\tconst handleLoadedMetadata = () => {\n\t\t\tsetState((prev) => ({ ...prev, duration: video.duration }))\n\t\t}\n\n\t\tconst handlePlay = () => {\n\t\t\tsetState((prev) => ({ ...prev, isPlaying: true, isBuffering: false }))\n\t\t}\n\n\t\tconst handlePause = () => {\n\t\t\tsetState((prev) => ({ ...prev, isPlaying: false }))\n\t\t}\n\n\t\tconst handleVolumeChange = () => {\n\t\t\tsetState((prev) => ({\n\t\t\t\t...prev,\n\t\t\t\tvolume: video.volume,\n\t\t\t\tisMuted: video.muted\n\t\t\t}))\n\t\t}\n\n\t\t// Loading state handlers\n\t\tconst handleLoadStart = () => {\n\t\t\tsetState((prev) => ({ ...prev, isLoading: true }))\n\t\t}\n\n\t\tconst handleLoadedData = () => {\n\t\t\tsetState((prev) => ({ ...prev, isLoading: false }))\n\t\t}\n\n\t\t// Seeking state handlers\n\t\tconst handleSeeking = () => {\n\t\t\tsetState((prev) => ({ ...prev, isSeeking: true }))\n\t\t}\n\n\t\tconst handleSeeked = () => {\n\t\t\tsetState((prev) => ({ ...prev, isSeeking: false }))\n\t\t}\n\n\t\t// Buffering state handlers\n\t\tconst handleWaiting = () => {\n\t\t\tsetState((prev) => ({ ...prev, isBuffering: true }))\n\t\t}\n\n\t\tconst handlePlaying = () => {\n\t\t\tsetState((prev) => ({ ...prev, isBuffering: false, isLoading: false }))\n\t\t}\n\n\t\tconst handleCanPlay = () => {\n\t\t\tsetState((prev) => ({ ...prev, isLoading: false, isBuffering: false }))\n\t\t}\n\n\t\t// Progress handler for buffered ranges\n\t\tconst handleProgress = () => {\n\t\t\tif (!video.buffered || video.buffered.length === 0 || video.duration === 0) {\n\t\t\t\tsetState((prev) => ({ ...prev, bufferedRanges: [] }))\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tconst ranges: BufferedRange[] = []\n\t\t\tfor (let i = 0; i < video.buffered.length; i++) {\n\t\t\t\tconst start = video.buffered.start(i)\n\t\t\t\tconst end = video.buffered.end(i)\n\t\t\t\tranges.push({\n\t\t\t\t\tstart,\n\t\t\t\t\tend,\n\t\t\t\t\tpercentage: ((end - start) / video.duration) * 100\n\t\t\t\t})\n\t\t\t}\n\t\t\tsetState((prev) => ({ ...prev, bufferedRanges: ranges }))\n\t\t}\n\n\t\tvideo.addEventListener(\"timeupdate\", handleTimeUpdate)\n\t\tvideo.addEventListener(\"loadedmetadata\", handleLoadedMetadata)\n\t\tvideo.addEventListener(\"play\", handlePlay)\n\t\tvideo.addEventListener(\"pause\", handlePause)\n\t\tvideo.addEventListener(\"volumechange\", handleVolumeChange)\n\t\tvideo.addEventListener(\"loadstart\", handleLoadStart)\n\t\tvideo.addEventListener(\"loadeddata\", handleLoadedData)\n\t\tvideo.addEventListener(\"seeking\", handleSeeking)\n\t\tvideo.addEventListener(\"seeked\", handleSeeked)\n\t\tvideo.addEventListener(\"waiting\", handleWaiting)\n\t\tvideo.addEventListener(\"playing\", handlePlaying)\n\t\tvideo.addEventListener(\"canplay\", handleCanPlay)\n\t\tvideo.addEventListener(\"progress\", handleProgress)\n\n\t\treturn () => {\n\t\t\tvideo.removeEventListener(\"timeupdate\", handleTimeUpdate)\n\t\t\tvideo.removeEventListener(\"loadedmetadata\", handleLoadedMetadata)\n\t\t\tvideo.removeEventListener(\"play\", handlePlay)\n\t\t\tvideo.removeEventListener(\"pause\", handlePause)\n\t\t\tvideo.removeEventListener(\"volumechange\", handleVolumeChange)\n\t\t\tvideo.removeEventListener(\"loadstart\", handleLoadStart)\n\t\t\tvideo.removeEventListener(\"loadeddata\", handleLoadedData)\n\t\t\tvideo.removeEventListener(\"seeking\", handleSeeking)\n\t\t\tvideo.removeEventListener(\"seeked\", handleSeeked)\n\t\t\tvideo.removeEventListener(\"waiting\", handleWaiting)\n\t\t\tvideo.removeEventListener(\"playing\", handlePlaying)\n\t\t\tvideo.removeEventListener(\"canplay\", handleCanPlay)\n\t\t\tvideo.removeEventListener(\"progress\", handleProgress)\n\t\t}\n\t}, [])\n\n\tconst togglePlay = () => {\n\t\tconst video = videoRef.current\n\t\tif (!video) return\n\n\t\tif (state.isPlaying) {\n\t\t\tvideo.pause()\n\t\t} else {\n\t\t\tvideo.play()\n\t\t}\n\t}\n\n\tconst seekForward = (seconds = 10) => {\n\t\tconst video = videoRef.current\n\t\tif (!video) return\n\n\t\tconst duration = Number.isFinite(video.duration) ? video.duration : Number.isFinite(state.duration) ? state.duration : 0\n\t\tif (duration === 0) {\n\t\t\tconsole.warn(\"Cannot seek forward: duration is not available\")\n\t\t\treturn\n\t\t}\n\n\t\tconst currentTime = Number.isFinite(video.currentTime) ? video.currentTime : 0\n\t\tconst newTime = Math.min(duration, currentTime + seconds)\n\t\tsafeSetCurrentTime(video, newTime)\n\t}\n\n\tconst seekBackward = (seconds = 10) => {\n\t\tconst video = videoRef.current\n\t\tif (!video) return\n\n\t\tconst currentTime = Number.isFinite(video.currentTime) ? video.currentTime : 0\n\t\tconst newTime = Math.max(0, currentTime - seconds)\n\t\tsafeSetCurrentTime(video, newTime)\n\t}\n\n\tconst toggleMute = () => {\n\t\tconst video = videoRef.current\n\t\tif (!video) return\n\t\tvideo.muted = !state.isMuted\n\t}\n\n\tconst setVolume = (volume: number) => {\n\t\tconst video = videoRef.current\n\t\tif (!video) return\n\t\tvideo.volume = volume\n\t\tif (volume > 0 && state.isMuted) {\n\t\t\tvideo.muted = false\n\t\t}\n\t}\n\n\tconst toggleFullscreen = () => {\n\t\tconst container = containerRef.current\n\t\tif (!container) return\n\n\t\tif (!state.isFullscreen) {\n\t\t\tif (container.requestFullscreen) {\n\t\t\t\tcontainer.requestFullscreen()\n\t\t\t}\n\t\t} else {\n\t\t\tif (document.exitFullscreen) {\n\t\t\t\tdocument.exitFullscreen()\n\t\t\t}\n\t\t}\n\t\tsetState((prev) => ({ ...prev, isFullscreen: !prev.isFullscreen }))\n\t}\n\n\tconst seekTo = (time: number) => {\n\t\tconst video = videoRef.current\n\t\tif (!video) return\n\n\t\tconst duration = Number.isFinite(video.duration) ? video.duration : Number.isFinite(state.duration) ? state.duration : 0\n\t\tif (duration === 0) {\n\t\t\tconsole.warn(\"Cannot seek: duration is not available\")\n\t\t\treturn\n\t\t}\n\n\t\tconst clampedTime = Math.max(0, Math.min(duration, time))\n\t\tsafeSetCurrentTime(video, clampedTime)\n\t}\n\n\tconst controls: VideoControls = {\n\t\ttogglePlay,\n\t\tseekForward,\n\t\tseekBackward,\n\t\ttoggleMute,\n\t\tsetVolume,\n\t\ttoggleFullscreen,\n\t\tseekTo\n\t}\n\n\treturn {\n\t\tvideoRef,\n\t\tstate,\n\t\tcontrols\n\t}\n}\n","/**\n * Intelligent Preloading Hook\n * Combines user behavior analysis with network conditions for optimal preloading\n */\n\nimport { useCallback, useEffect, useMemo, useRef } from \"react\"\nimport { MediaSource } from \"../types\"\n\ninterface NetworkInformation {\n\ttype?: string\n\tdownlink?: number\n\teffectiveType?: \"slow-2g\" | \"2g\" | \"3g\" | \"4g\"\n\tsaveData?: boolean\n\trtt?: number\n\taddEventListener?: (type: string, listener: EventListener) => void\n\tremoveEventListener?: (type: string, listener: EventListener) => void\n}\n\ninterface IntelligentPreloadingOptions {\n\t/** Enable user behavior tracking */\n\ttrackUserBehavior?: boolean\n\t/** Adapt to network conditions */\n\tadaptToNetwork?: boolean\n\t/** Preload strategy */\n\tstrategy?: \"conservative\" | \"balanced\" | \"aggressive\"\n\t/** Maximum number of items to preload */\n\tmaxPreloadItems?: number\n\t/** Preload radius for playlist items */\n\tpreloadRadius?: number\n}\n\ninterface UserBehaviorData {\n\tmouseMovements: number\n\tscrollEvents: number\n\tkeyPresses: number\n\tfocusEvents: number\n\ttimeOnPage: number\n\tengagementScore: number\n\tlastInteraction: number\n}\n\ninterface PreloadingDecision {\n\tshouldPreload: boolean\n\tpriority: \"high\" | \"medium\" | \"low\"\n\treason: string\n}\n\nexport const useIntelligentPreloading = (\n\tsources: MediaSource[],\n\toptions: IntelligentPreloadingOptions = {}\n) => {\n\tconst {\n\t\ttrackUserBehavior = true,\n\t\tadaptToNetwork = true,\n\t\tstrategy = \"balanced\",\n\t\tmaxPreloadItems = 3,\n\t\tpreloadRadius = 2\n\t} = options\n\n\tconst userBehaviorRef = useRef<UserBehaviorData>({\n\t\tmouseMovements: 0,\n\t\tscrollEvents: 0,\n\t\tkeyPresses: 0,\n\t\tfocusEvents: 0,\n\t\ttimeOnPage: 0,\n\t\tengagementScore: 0,\n\t\tlastInteraction: Date.now()\n\t})\n\n\tconst networkInfoRef = useRef<NetworkInformation | null>(null)\n\tconst preloadedItemsRef = useRef<Set<string>>(new Set())\n\tconst preloadQueueRef = useRef<Array<{ source: MediaSource; priority: number }>>([])\n\n\t// Calculate user engagement score\n\tconst calculateEngagementScore = useCallback((): number => {\n\t\tconst behavior = userBehaviorRef.current\n\t\tconst timeFactor = Math.min(behavior.timeOnPage / 60000, 1) // Cap at 1 minute\n\t\tconst interactionFactor = Math.min(\n\t\t\t(behavior.mouseMovements + behavior.scrollEvents + behavior.keyPresses) / 100,\n\t\t\t1\n\t\t)\n\n\t\treturn (timeFactor * 0.4 + interactionFactor * 0.6) * 100\n\t}, [])\n\n\t// Update user behavior tracking\n\tconst updateUserBehavior = useCallback(\n\t\t(type: keyof UserBehaviorData, increment = 1) => {\n\t\t\tconst behavior = userBehaviorRef.current\n\t\t\tbehavior[type] = typeof behavior[type] === \"number\" ? behavior[type] + increment : Date.now()\n\t\t\tbehavior.engagementScore = calculateEngagementScore()\n\t\t\tbehavior.lastInteraction = Date.now()\n\t\t},\n\t\t[calculateEngagementScore]\n\t)\n\n\t// Get current network conditions\n\tconst getNetworkConditions = useCallback(() => {\n\t\tif (!networkInfoRef.current || !adaptToNetwork) {\n\t\t\treturn { type: \"unknown\", downlink: 10, effectiveType: \"4g\", saveData: false }\n\t\t}\n\n\t\tconst network = networkInfoRef.current\n\t\treturn {\n\t\t\ttype: network.type,\n\t\t\tdownlink: network.downlink || 10,\n\t\t\teffectiveType: network.effectiveType || \"4g\",\n\t\t\tsaveData: network.saveData || false,\n\t\t\trtt: network.rtt || 100\n\t\t}\n\t}, [adaptToNetwork])\n\n\t// Determine if a source should be preloaded\n\tconst shouldPreloadSource = useCallback(\n\t\t(source: MediaSource, index: number, currentIndex: number = 0): PreloadingDecision => {\n\t\t\t// Skip if already preloaded\n\t\t\tif (preloadedItemsRef.current.has(source.src)) {\n\t\t\t\treturn { shouldPreload: false, priority: \"low\", reason: \"Already preloaded\" }\n\t\t\t}\n\n\t\t\t// Check if within preload radius\n\t\t\tconst distance = Math.abs(index - currentIndex)\n\t\t\tif (distance > preloadRadius) {\n\t\t\t\treturn { shouldPreload: false, priority: \"low\", reason: \"Outside preload radius\" }\n\t\t\t}\n\n\t\t\tconst behavior = userBehaviorRef.current\n\t\t\tconst network = getNetworkConditions()\n\t\t\tconst engagementScore = behavior.engagementScore\n\t\t\tconst timeSinceInteraction = Date.now() - behavior.lastInteraction\n\n\t\t\t// Network-based decisions\n\t\t\tif (network.saveData) {\n\t\t\t\treturn { shouldPreload: false, priority: \"low\", reason: \"Data saver mode\" }\n\t\t\t}\n\n\t\t\t// Strategy-based filtering\n\t\t\tlet shouldPreload = false\n\t\t\tlet priority: \"high\" | \"medium\" | \"low\" = \"medium\"\n\t\t\tlet reason = \"\"\n\n\t\t\tswitch (strategy) {\n\t\t\t\tcase \"conservative\":\n\t\t\t\t\tshouldPreload = engagementScore > 70 && network.effectiveType !== \"2g\" && distance === 1\n\t\t\t\t\tpriority = shouldPreload ? \"medium\" : \"low\"\n\t\t\t\t\treason = shouldPreload ? \"High engagement and optimal network\" : \"Conservative strategy\"\n\t\t\t\t\tbreak\n\n\t\t\t\tcase \"aggressive\":\n\t\t\t\t\tshouldPreload = engagementScore > 30 && network.effectiveType !== \"slow-2g\"\n\t\t\t\t\tpriority = engagementScore > 70 ? \"high\" : engagementScore > 50 ? \"medium\" : \"low\"\n\t\t\t\t\treason = shouldPreload ? \"Aggressive preloading\" : \"Low engagement\"\n\t\t\t\t\tbreak\n\n\t\t\t\tcase \"balanced\":\n\t\t\t\tdefault:\n\t\t\t\t\tconst networkMultiplier =\n\t\t\t\t\t\tnetwork.effectiveType === \"4g\" ? 1 : network.effectiveType === \"3g\" ? 0.7 : 0.3\n\t\t\t\t\tconst adjustedScore = engagementScore * networkMultiplier\n\n\t\t\t\t\tshouldPreload = adjustedScore > 40 && distance <= 2\n\t\t\t\t\tpriority = adjustedScore > 70 ? \"high\" : adjustedScore > 55 ? \"medium\" : \"low\"\n\t\t\t\t\treason = shouldPreload\n\t\t\t\t\t\t? `Balanced: score ${adjustedScore.toFixed(1)}`\n\t\t\t\t\t\t: \"Low adjusted score\"\n\t\t\t\t\tbreak\n\t\t\t}\n\n\t\t\t// Additional heuristics\n\t\t\tif (shouldPreload) {\n\t\t\t\tconst sourceType = source.type as string\n\n\t\t\t\t// Prioritize HLS and adaptive streaming\n\t\t\t\tif (sourceType === \"hls\" || sourceType === \"m3u8\" || sourceType === \"application/x-mpegURL\") {\n\t\t\t\t\tpriority = priority === \"low\" ? \"medium\" : \"high\"\n\t\t\t\t}\n\n\t\t\t\t// Boost priority for recent user interaction\n\t\t\t\tif (timeSinceInteraction < 5000) {\n\t\t\t\t\t// Within 5 seconds\n\t\t\t\t\tpriority = \"high\"\n\t\t\t\t\treason += \" + Recent interaction\"\n\t\t\t\t}\n\n\t\t\t\t// Consider content type (video gets higher priority than audio)\n\t\t\t\tif (sourceType === \"mp4\" || sourceType === \"webm\" || sourceType === \"video/mp4\" || sourceType === \"video/webm\") {\n\t\t\t\t\tpriority = priority === \"low\" ? \"medium\" : priority\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn { shouldPreload, priority, reason }\n\t\t},\n\t\t[strategy, preloadRadius, getNetworkConditions, calculateEngagementScore]\n\t)\n\n\t// Preload a specific source\n\tconst preloadSource = useCallback(async (source: MediaSource, priority: number) => {\n\t\ttry {\n\t\t\t// Create a preload link element\n\t\t\tconst link = document.createElement(\"link\")\n\t\t\tlink.rel = \"preload\"\n\t\t\tlink.href = source.src\n\n\t\t\tconst sourceType = source.type as string\n\n\t\t\t// Determine the correct 'as' attribute\n\t\t\tswitch (sourceType) {\n\t\t\t\tcase \"hls\":\n\t\t\t\tcase \"m3u8\":\n\t\t\t\tcase \"application/x-mpegURL\":\n\t\t\t\t\tlink.as = \"fetch\"\n\t\t\t\t\tbreak\n\t\t\t\tcase \"mp4\":\n\t\t\t\tcase \"webm\":\n\t\t\t\tcase \"video/mp4\":\n\t\t\t\tcase \"video/webm\":\n\t\t\t\t\tlink.as = \"video\"\n\t\t\t\t\tbreak\n\t\t\t\tcase \"mp3\":\n\t\t\t\tcase \"wav\":\n\t\t\t\tcase \"ogg\":\n\t\t\t\tcase \"audio/mpeg\":\n\t\t\t\tcase \"audio/wav\":\n\t\t\t\tcase \"audio/ogg\":\n\t\t\t\t\tlink.as = \"audio\"\n\t\t\t\t\tbreak\n\t\t\t\tdefault:\n\t\t\t\t\tlink.as = \"fetch\"\n\t\t\t}\n\n\t\t\tlink.crossOrigin = \"anonymous\"\n\n\t\t\t// Add to document head\n\t\t\tdocument.head.appendChild(link)\n\n\t\t\t// Mark as preloaded\n\t\t\tpreloadedItemsRef.current.add(source.src)\n\n\t\t\tconsole.debug(`Preloaded: ${source.src} (${priority})`)\n\n\t\t\t// Cleanup after 30 seconds to prevent memory issues\n\t\t\tsetTimeout(() => {\n\t\t\t\tif (document.head.contains(link)) {\n\t\t\t\t\tdocument.head.removeChild(link)\n\t\t\t\t}\n\t\t\t}, 30000)\n\t\t} catch (error) {\n\t\t\tconsole.warn(\"Failed to preload source:\", source.src, error)\n\t\t}\n\t}, [])\n\n\t// Process preload queue\n\tconst processPreloadQueue = useCallback(() => {\n\t\tif (preloadQueueRef.current.length === 0) return\n\n\t\t// Sort by priority (higher number = higher priority)\n\t\tconst sortedQueue = [...preloadQueueRef.current].sort((a, b) => b.priority - a.priority)\n\n\t\t// Take top items based on maxPreloadItems\n\t\tconst itemsToPreload = sortedQueue.slice(0, maxPreloadItems)\n\n\t\t// Clear queue\n\t\tpreloadQueueRef.current = []\n\n\t\t// Preload items\n\t\titemsToPreload.forEach(({ source, priority }) => {\n\t\t\tpreloadSource(source, priority)\n\t\t})\n\t}, [maxPreloadItems, preloadSource])\n\n\t// Update preloading decisions\n\tconst updatePreloading = useCallback(\n\t\t(currentIndex: number = 0) => {\n\t\t\tpreloadQueueRef.current = []\n\n\t\t\tsources.forEach((source, index) => {\n\t\t\t\tconst decision = shouldPreloadSource(source, index, currentIndex)\n\n\t\t\t\tif (decision.shouldPreload) {\n\t\t\t\t\tconst priority = decision.priority === \"high\" ? 3 : decision.priority === \"medium\" ? 2 : 1\n\n\t\t\t\t\tpreloadQueueRef.current.push({ source, priority })\n\t\t\t\t}\n\t\t\t})\n\n\t\t\tprocessPreloadQueue()\n\t\t},\n\t\t[sources, shouldPreloadSource, processPreloadQueue]\n\t)\n\n\t// Set up user behavior tracking\n\tuseEffect(() => {\n\t\tif (!trackUserBehavior) return\n\n\t\tconst handleMouseMove = () => updateUserBehavior(\"mouseMovements\")\n\t\tconst handleScroll = () => updateUserBehavior(\"scrollEvents\")\n\t\tconst handleKeyPress = () => updateUserBehavior(\"keyPresses\")\n\t\tconst handleFocus = () => updateUserBehavior(\"focusEvents\")\n\n\t\t// Add event listeners\n\t\tdocument.addEventListener(\"mousemove\", handleMouseMove, { passive: true })\n\t\tdocument.addEventListener(\"scroll\", handleScroll, { passive: true })\n\t\tdocument.addEventListener(\"keydown\", handleKeyPress, { passive: true })\n\t\tdocument.addEventListener(\"focusin\", handleFocus, { passive: true })\n\n\t\t// Update time on page every second\n\t\tconst timeInterval = setInterval(() => {\n\t\t\tupdateUserBehavior(\"timeOnPage\", 1)\n\t\t}, 1000)\n\n\t\treturn () => {\n\t\t\tdocument.removeEventListener(\"mousemove\", handleMouseMove)\n\t\t\tdocument.removeEventListener(\"scroll\", handleScroll)\n\t\t\tdocument.removeEventListener(\"keydown\", handleKeyPress)\n\t\t\tdocument.removeEventListener(\"focusin\", handleFocus)\n\t\t\tclearInterval(timeInterval)\n\t\t}\n\t}, [trackUserBehavior, updateUserBehavior])\n\n\t// Set up network monitoring\n\tuseEffect(() => {\n\t\tif (!adaptToNetwork || !(\"connection\" in navigator)) return\n\n\t\tconst network = (navigator as any).connection\n\t\tnetworkInfoRef.current = network\n\n\t\tconst handleNetworkChange = () => {\n\t\t\t// Re-evaluate preloading when network conditions change\n\t\t\tupdatePreloading()\n\t\t}\n\n\t\tnetwork.addEventListener(\"change\", handleNetworkChange)\n\n\t\treturn () => {\n\t\t\tnetwork.removeEventListener(\"change\", handleNetworkChange)\n\t\t}\n\t}, [adaptToNetwork, updatePreloading])\n\n\t// Initial preloading\n\tuseEffect(() => {\n\t\tupdatePreloading()\n\t}, [updatePreloading])\n\n\t// Memoize return values\n\tconst controls = useMemo(\n\t\t() => ({\n\t\t\t/**\n\t\t\t * Manually trigger preloading for specific index\n\t\t\t */\n\t\t\tpreloadAtIndex: (index: number) => {\n\t\t\t\tupdatePreloading(index)\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Get current user behavior data\n\t\t\t */\n\t\t\tgetUserBehavior: () => ({ ...userBehaviorRef.current }),\n\n\t\t\t/**\n\t\t\t * Get current network conditions\n\t\t\t */\n\t\t\tgetNetworkConditions: getNetworkConditions,\n\n\t\t\t/**\n\t\t\t * Clear preloaded items cache\n\t\t\t */\n\t\t\tclearCache: () => {\n\t\t\t\tpreloadedItemsRef.current.clear()\n\t\t\t},\n\n\t\t\t/**\n\t\t\t * Get preloading statistics\n\t\t\t */\n\t\t\tgetStats: () => ({\n\t\t\t\tpreloadedItems: preloadedItemsRef.current.size,\n\t\t\t\tengagementScore: userBehaviorRef.current.engagementScore,\n\t\t\t\tqueueLength: preloadQueueRef.current.length,\n\t\t\t\tmaxPreloadItems\n\t\t\t})\n\t\t}),\n\t\t[updatePreloading, getNetworkConditions, maxPreloadItems]\n\t)\n\n\treturn controls\n}\n\nexport default useIntelligentPreloading\n","import { useCallback, useEffect, useMemo, useState } from \"react\"\n\ninterface SubtitleCue {\n\tstart: number\n\tend: number\n\ttext: string\n}\n\nexport function useSubtitles(subtitleSrc?: string) {\n\tconst [subtitlesEnabled, setSubtitlesEnabled] = useState(false)\n\tconst [subtitleCues, setSubtitleCues] = useState<SubtitleCue[]>([])\n\tconst [currentSubtitle, setCurrentSubtitle] = useState(\"\")\n\n\tconst parseVTTTime = (timeStr: string): number => {\n\t\tconst parts = timeStr.split(\":\")\n\t\tconst seconds = parts[2] ? parseFloat(parts[2]) : 0\n\t\tconst minutes = parts[1] ? parseInt(parts[1], 10) * 60 : 0\n\t\tconst hours = parts[0] ? parseInt(parts[0], 10) * 3600 : 0\n\t\treturn hours + minutes + seconds\n\t}\n\n\tconst loadSubtitles = async (url: string) => {\n\t\ttry {\n\t\t\tconst response = await fetch(url)\n\t\t\tconst text = await response.text()\n\n\t\t\tconst cues: SubtitleCue[] = []\n\t\t\tconst lines = text.split(\"\\n\")\n\t\t\tlet i = 0\n\n\t\t\twhile (i < lines.length) {\n\t\t\t\tif (lines[i]?.includes(\"-->\")) {\n\t\t\t\t\tconst [startStr, endStr] = (lines[i] || \"\").split(\"-->\").map((s) => s.trim())\n\t\t\t\t\tconst start = parseVTTTime(startStr || \"\")\n\t\t\t\t\tconst end = parseVTTTime(endStr || \"\")\n\n\t\t\t\t\ti++\n\t\t\t\t\tlet subtitleText = \"\"\n\t\t\t\t\twhile (i < lines.length && lines[i]?.trim() !== \"\") {\n\t\t\t\t\t\tsubtitleText += (subtitleText ? \" \" : \"\") + lines[i]?.trim()\n\t\t\t\t\t\ti++\n\t\t\t\t\t}\n\n\t\t\t\t\tif (subtitleText) {\n\t\t\t\t\t\tcues.push({ start, end, text: subtitleText })\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\ti++\n\t\t\t}\n\n\t\t\tsetSubtitleCues(cues)\n\t\t} catch (error) {\n\t\t\tconsole.error(\"Failed to load subtitles:\", error)\n\t\t}\n\t}\n\n\tconst getCurrentSubtitle = (currentTime: number) => {\n\t\tif (!subtitlesEnabled || subtitleCues.length === 0) return \"\"\n\n\t\tconst currentCue = subtitleCues.find(\n\t\t\t(cue) => currentTime >= cue.start && currentTime <= cue.end\n\t\t)\n\t\treturn currentCue?.text || \"\"\n\t}\n\n\tconst toggleSubtitles = () => {\n\t\tsetSubtitlesEnabled((prev) => {\n\t\t\tconst newEnabled = !prev\n\t\t\tif (newEnabled && subtitleSrc && subtitleCues.length === 0) {\n\t\t\t\tloadSubtitles(subtitleSrc)\n\t\t\t} else if (!newEnabled) {\n\t\t\t\tsetCurrentSubtitle(\"\")\n\t\t\t}\n\t\t\treturn newEnabled\n\t\t})\n\t}\n\n\tuseEffect(() => {\n\t\tif (!subtitlesEnabled) {\n\t\t\tsetCurrentSubtitle(\"\")\n\t\t}\n\t}, [subtitlesEnabled])\n\n\treturn {\n\t\tsubtitlesEnabled,\n\t\tcurrentSubtitle,\n\t\ttoggleSubtitles,\n\t\tgetCurrentSubtitle,\n\t\tsetCurrentSubtitle\n\t}\n}\n","/**\n * Legacy Hooks (Deprecated)\n * These hooks are wrapped with deprecation warnings\n */\n\nimport { showDeprecationWarning } from \"../lib/deprecation\"\n\n// Import current hooks\nimport { useMediaPlayer } from \"./use-media-player\"\nimport { useSubtitles } from \"./useSubtitles\"\n\n// Legacy hook wrappers with deprecation warnings\nexport function useVideoPlayer(props: any) {\n\tshowDeprecationWarning(\"useVideoPlayer\", \"useMediaPlayer (the primary media player hook)\")\n\treturn useMediaPlayer(props)\n}\n\nexport function useEnhancedSubtitles(props: any) {\n\tshowDeprecationWarning(\"useEnhancedSubtitles\", \"useSubtitles (the current subtitle hook)\")\n\treturn useSubtitles(props)\n}\n"],"names":["createOptimisticAction","type","store","payload","optimistic","action","useMediaActionState","actionState","setActionState","React","newActionState","current","useMediaActions","actions","MediaActionTypes","optimisticActions","isPlaying","time","delta","currentVolume","newVolume","isFullscreen","retryLastAction","lastAction","optimisticMediaReducer","state","useMediaOptimistic","actualState","optimisticState","addOptimistic","useOptimistic","dispatchOptimistic","volume","rate","selectors","formatTime","seconds","mins","secs","hours","safeSetCurrentTime","media","error","useEnhancedMediaPlayer","options","mediaRef","useRef","containerRef","isPending","startTransition","useTransition","isSeeking","startSeekTransition","frameCount","lastFrameTime","lastTimeUpdate","useMediaStore","isEnhanced","useMediaSelector","currentTime","duration","isMuted","isLoading","isBuffering","buffered","enhancedStore","performanceMetrics","setPerformanceMetrics","optimisticVolume","setOptimisticVolume","newTime","useEffect","initProps","key","value","handleTimeUpdate","useCallback","now","handlePlay","handlePause","handleVolumeChange","handleSeeking","handleSeeked","handleProgress","measureRenderTime","fps","prev","eventListeners","event","handler","passive","rafId","performanceLoop","controls","useMemo","play","pause","toggle","seek","validDuration","clampedTime","setVolume","clampedVolume","toggleMute","enterFullscreen","container","exitFullscreen","computedState","useKeyboardControls","enabled","seekStep","volumeStep","handleKeyDown","target","percentage","useMemoryOptimization","maxMemoryUsage","cleanupInterval","enableGC","monitorMemory","observersRef","eventListenersRef","intervalRefs","animationFrameRefs","getMemoryUsage","memory","memoryStats","setMemoryStats","performCleanup","timeout","frameId","observer","listeners","element","useInterval","callback","delay","timeoutId","checkMemory","usage","isHighUsage","addEventListener","index","l","useSafeTimeout","useSafeAnimationFrame","addObserver","bytes","k","sizes","i","useMediaState","setState","useState","updateState","updates","useMediaPlayer","setPlaying","setCurrentTime","setDuration","setMuted","setLoading","setFullscreen","setError","setBuffered","handleDurationChange","handleLoadStart","handleLoadedData","handleError","errorMessage","handleEnded","setVolumeControl","mute","unmute","toggleFullscreen","handleFullscreenChange","BREAKPOINTS","detectPlatform","userAgent","isTouchDevice","supportsHaptics","useDeviceInfo","deviceInfo","setDeviceInfo","width","height","updateDeviceInfo","mobileQuery","tabletQuery","desktopQuery","useMobileOptimizations","platform","isMobile","preventZoom","e","useHapticFeedback","pattern","defaultConfig","useTouchGestures","ref","onGesture","config","mergedConfig","triggerHaptic","gestureState","getTouchPoint","touch","getDistance","p1","p2","getVelocity","start","end","timeDiff","createGestureEvent","startPoint","currentPoint","additionalData","handleTouchStart","touches","gestureEvent","handleTouchMove","currentDistance","scale","gestureType","centerPoint","startCenterPoint","startTouch","currentTouch","handleTouchEnd","endTouches","endTouch","distance","velocity","absVelX","absVelY","useMediaGestures","handleGesture","backwardAmount","forwardAmount","volumeAmount","useEnhancedSubtitles","subtitleSrc","subtitleTracks","defaultFontSize","onLoadError","subtitlesEnabled","setSubtitlesEnabled","subtitleCues","setSubtitleCues","currentSubtitle","setCurrentSubtitle","currentTrackId","setCurrentTrackId","fontSize","setFontSize","loadError","setLoadError","setIsLoading","sizeMap","hasSubtitles","parseVTTTime","timeStr","parts","minutes","parseSRTTime","ms","milliseconds","loadSubtitles","url","response","text","cues","lines","isVTT","isSRT","startStr","endStr","s","subtitleText","err","getCurrentSubtitle","cue","toggleSubtitles","newEnabled","srcToLoad","selectSubtitleTrack","trackId","track","t","changeSubtitleFontSize","size","getSubtitleStyles","video","useKeyboardShortcuts","videoControls","takeScreenshot","newTimeLeft","currentTimeRight","newTimeRight","useMediaControls","showSettings","controlsVisible","setControlsVisible","showVolumeSlider","setShowVolumeSlider","hideTimeoutRef","showControls","handleMouseMove","handleMouseEnter","handleMouseLeave","useScreenshot","videoRef","ctrlKey","canvas","ctx","blob","item","a","useVideoPlayer","handleLoadedMetadata","handleWaiting","handlePlaying","handleCanPlay","ranges","useIntelligentPreloading","sources","trackUserBehavior","adaptToNetwork","strategy","maxPreloadItems","preloadRadius","userBehaviorRef","networkInfoRef","preloadedItemsRef","preloadQueueRef","calculateEngagementScore","behavior","timeFactor","interactionFactor","updateUserBehavior","increment","getNetworkConditions","network","shouldPreloadSource","source","currentIndex","engagementScore","timeSinceInteraction","shouldPreload","priority","reason","networkMultiplier","adjustedScore","sourceType","preloadSource","link","processPreloadQueue","itemsToPreload","b","updatePreloading","decision","handleScroll","handleKeyPress","handleFocus","timeInterval","handleNetworkChange","useSubtitles","props","showDeprecationWarning"],"mappings":"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"}
|