@therealtinhtute/baroiplayer 1.2.0 → 2.0.0-beta.1
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/README.md +91 -73
- package/dist/components/icons/index.d.ts +36 -0
- package/dist/components/icons/index.d.ts.map +1 -0
- package/dist/components/icons/svg-icons/ArrowLeftIcon.d.ts +4 -0
- package/dist/components/icons/svg-icons/ArrowLeftIcon.d.ts.map +1 -0
- package/dist/components/icons/svg-icons/ArrowRightIcon.d.ts +5 -0
- package/dist/components/icons/svg-icons/ArrowRightIcon.d.ts.map +1 -0
- package/dist/components/icons/svg-icons/AudioIcon.d.ts +5 -0
- package/dist/components/icons/svg-icons/AudioIcon.d.ts.map +1 -0
- package/dist/components/icons/svg-icons/BackwardIcon.d.ts +5 -0
- package/dist/components/icons/svg-icons/BackwardIcon.d.ts.map +1 -0
- package/dist/components/icons/svg-icons/CameraIcon.d.ts +5 -0
- package/dist/components/icons/svg-icons/CameraIcon.d.ts.map +1 -0
- package/dist/components/icons/svg-icons/CheckIcon.d.ts +5 -0
- package/dist/components/icons/svg-icons/CheckIcon.d.ts.map +1 -0
- package/dist/components/icons/svg-icons/EnablePiPIcon.d.ts +4 -0
- package/dist/components/icons/svg-icons/EnablePiPIcon.d.ts.map +1 -0
- package/dist/components/icons/svg-icons/ForwardIcon.d.ts +5 -0
- package/dist/components/icons/svg-icons/ForwardIcon.d.ts.map +1 -0
- package/dist/components/icons/svg-icons/FullscreenEnterIcon.d.ts +5 -0
- package/dist/components/icons/svg-icons/FullscreenEnterIcon.d.ts.map +1 -0
- package/dist/components/icons/svg-icons/FullscreenExitIcon.d.ts +5 -0
- package/dist/components/icons/svg-icons/FullscreenExitIcon.d.ts.map +1 -0
- package/dist/components/icons/svg-icons/LoadingIcon.d.ts +5 -0
- package/dist/components/icons/svg-icons/LoadingIcon.d.ts.map +1 -0
- package/dist/components/icons/svg-icons/PauseIcon.d.ts +5 -0
- package/dist/components/icons/svg-icons/PauseIcon.d.ts.map +1 -0
- package/dist/components/icons/svg-icons/PlayIcon.d.ts +5 -0
- package/dist/components/icons/svg-icons/PlayIcon.d.ts.map +1 -0
- package/dist/components/icons/svg-icons/PlaybackSpeedIcon.d.ts +5 -0
- package/dist/components/icons/svg-icons/PlaybackSpeedIcon.d.ts.map +1 -0
- package/dist/components/icons/svg-icons/QualityIcon.d.ts +5 -0
- package/dist/components/icons/svg-icons/QualityIcon.d.ts.map +1 -0
- package/dist/components/icons/svg-icons/SettingsIcon.d.ts +5 -0
- package/dist/components/icons/svg-icons/SettingsIcon.d.ts.map +1 -0
- package/dist/components/icons/svg-icons/SliderIcon.d.ts +5 -0
- package/dist/components/icons/svg-icons/SliderIcon.d.ts.map +1 -0
- package/dist/components/icons/svg-icons/SubtitleIcon.d.ts +5 -0
- package/dist/components/icons/svg-icons/SubtitleIcon.d.ts.map +1 -0
- package/dist/components/icons/svg-icons/SubtitleOffIcon.d.ts +5 -0
- package/dist/components/icons/svg-icons/SubtitleOffIcon.d.ts.map +1 -0
- package/dist/components/icons/svg-icons/UnPiPIcon.d.ts +4 -0
- package/dist/components/icons/svg-icons/UnPiPIcon.d.ts.map +1 -0
- package/dist/components/icons/svg-icons/VolumeMutedIcon.d.ts +5 -0
- package/dist/components/icons/svg-icons/VolumeMutedIcon.d.ts.map +1 -0
- package/dist/components/icons/svg-icons/VolumeOneIcon.d.ts +5 -0
- package/dist/components/icons/svg-icons/VolumeOneIcon.d.ts.map +1 -0
- package/dist/components/icons/svg-icons/VolumeThreeIcon.d.ts +5 -0
- package/dist/components/icons/svg-icons/VolumeThreeIcon.d.ts.map +1 -0
- package/dist/components/icons/svg-icons/VolumeTwoIcon.d.ts +5 -0
- package/dist/components/icons/svg-icons/VolumeTwoIcon.d.ts.map +1 -0
- package/dist/components/variants/gradient/gradient-audio.d.ts +13 -0
- package/dist/components/variants/gradient/gradient-audio.d.ts.map +1 -0
- package/dist/components/variants/gradient/gradient-controls.d.ts +4 -0
- package/dist/components/variants/gradient/gradient-controls.d.ts.map +1 -0
- package/dist/components/variants/gradient/gradient-glyphs.d.ts +30 -0
- package/dist/components/variants/gradient/gradient-glyphs.d.ts.map +1 -0
- package/dist/components/variants/gradient/gradient-video.d.ts +16 -0
- package/dist/components/variants/gradient/gradient-video.d.ts.map +1 -0
- package/dist/index.css +1 -1
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2 -112
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +786 -6271
- package/dist/index.mjs.map +1 -1
- package/dist/package.json +3 -0
- package/package.json +110 -108
- package/src/components/variants/gradient/gradient-audio.tsx +47 -0
- package/src/components/variants/gradient/gradient-controls.tsx +254 -0
- package/src/components/variants/gradient/gradient-glyphs.test.tsx +69 -0
- package/src/components/variants/gradient/gradient-glyphs.tsx +129 -0
- package/src/components/variants/gradient/gradient-skin.css +211 -0
- package/src/components/variants/gradient/gradient-video.tsx +70 -0
- package/src/index.ts +5 -198
- package/src/test/accessibility-utils.ts +0 -59
- package/dist/context/media.js +0 -2
- package/dist/context/media.js.map +0 -1
- package/dist/context/media.mjs +0 -15
- package/dist/context/media.mjs.map +0 -1
- package/dist/context/store.js +0 -2
- package/dist/context/store.js.map +0 -1
- package/dist/context/store.mjs +0 -5
- package/dist/context/store.mjs.map +0 -1
- package/dist/context-BYwDoSRX.js +0 -1172
- package/dist/context-BYwDoSRX.js.map +0 -1
- package/dist/context-eNS62_ac.cjs +0 -23
- package/dist/context-eNS62_ac.cjs.map +0 -1
- package/dist/core-events-B1iM2F46.cjs +0 -2
- package/dist/core-events-B1iM2F46.cjs.map +0 -1
- package/dist/core-events-DunPHKRE.js +0 -484
- package/dist/core-events-DunPHKRE.js.map +0 -1
- package/dist/core-plugins-By-4-kGs.cjs +0 -2
- package/dist/core-plugins-By-4-kGs.cjs.map +0 -1
- package/dist/core-plugins-DSBWcTuX.js +0 -821
- package/dist/core-plugins-DSBWcTuX.js.map +0 -1
- package/dist/core.js +0 -37
- package/dist/core.js.map +0 -1
- package/dist/core.mjs +0 -1233
- package/dist/core.mjs.map +0 -1
- package/dist/enhanced-components-B_l3cist.js +0 -1142
- package/dist/enhanced-components-B_l3cist.js.map +0 -1
- package/dist/enhanced-components-BspFs9OO.cjs +0 -2
- package/dist/enhanced-components-BspFs9OO.cjs.map +0 -1
- package/dist/hooks-BXwI8QG6.cjs +0 -4
- package/dist/hooks-BXwI8QG6.cjs.map +0 -1
- package/dist/hooks-Bpi-jDiO.js +0 -1816
- package/dist/hooks-Bpi-jDiO.js.map +0 -1
- package/dist/minimal-components-C4z900Ro.js +0 -1926
- package/dist/minimal-components-C4z900Ro.js.map +0 -1
- package/dist/minimal-components-v4qBp6jv.cjs +0 -2
- package/dist/minimal-components-v4qBp6jv.cjs.map +0 -1
- package/dist/minimal-components.css +0 -1
- package/dist/mona-loading.gif +0 -0
- package/dist/performance-monitor-C5k6FDXw.js +0 -301
- package/dist/performance-monitor-C5k6FDXw.js.map +0 -1
- package/dist/performance-monitor-lJmuUjQQ.cjs +0 -2
- package/dist/performance-monitor-lJmuUjQQ.cjs.map +0 -1
- package/dist/utils-CFOue_9K.cjs +0 -9
- package/dist/utils-CFOue_9K.cjs.map +0 -1
- package/dist/utils-Dzpl2ArK.js +0 -2844
- package/dist/utils-Dzpl2ArK.js.map +0 -1
- package/dist/utils.js +0 -2
- package/dist/utils.js.map +0 -1
- package/dist/utils.mjs +0 -11
- package/dist/utils.mjs.map +0 -1
- package/src/adapters/videojs-adapter.tsx +0 -470
- package/src/assets/mona-loading.gif +0 -0
- package/src/components/AnimateLoading.tsx +0 -107
- package/src/components/LoadingState.tsx +0 -239
- package/src/components/__tests__/media-player-accessibility.test.tsx +0 -510
- package/src/components/__tests__/media-player-react19.test.tsx +0 -457
- package/src/components/accessibility/keyboard-help-overlay.tsx +0 -207
- package/src/components/audio-player.tsx +0 -85
- package/src/components/basic/index.ts +0 -37
- package/src/components/enhanced/advanced-features.tsx +0 -311
- package/src/components/enhanced/debug-panel.tsx +0 -448
- package/src/components/enhanced/enhanced-controls.tsx +0 -597
- package/src/components/enhanced/enhanced-media-player.tsx +0 -566
- package/src/components/enhanced/error-handling.tsx +0 -338
- package/src/components/enhanced/index.ts +0 -39
- package/src/components/enhanced/media-player-enhanced.tsx +0 -383
- package/src/components/examples/basic-video-player.tsx +0 -50
- package/src/components/examples/custom-controls-example.tsx +0 -63
- package/src/components/examples/enhanced-controls-example.tsx +0 -100
- package/src/components/examples/enhanced-media-player-example.tsx +0 -302
- package/src/components/examples/loading-states-demo.tsx +0 -142
- package/src/components/examples/react-19-demo.tsx +0 -353
- package/src/components/examples/volume-orientation-demo.tsx +0 -106
- package/src/components/icon-demo.tsx +0 -196
- package/src/components/legacy.tsx +0 -87
- package/src/components/media-metadata-display.tsx +0 -99
- package/src/components/media-player-audio.tsx +0 -39
- package/src/components/media-player-controls.tsx +0 -223
- package/src/components/media-player-error.tsx +0 -163
- package/src/components/media-player-fullscreen.tsx +0 -109
- package/src/components/media-player-hls.tsx +0 -111
- package/src/components/media-player-loading.tsx +0 -76
- package/src/components/media-player-play.tsx +0 -75
- package/src/components/media-player-root.tsx +0 -338
- package/src/components/media-player-seek.tsx +0 -168
- package/src/components/media-player-time.tsx +0 -99
- package/src/components/media-player-tooltip.tsx +0 -58
- package/src/components/media-player-video.tsx +0 -54
- package/src/components/media-player-volume.tsx +0 -155
- package/src/components/media-player.tsx +0 -292
- package/src/components/media-suspense.tsx +0 -344
- package/src/components/player-settings-form.tsx +0 -158
- package/src/components/react-player-wrapper.tsx +0 -651
- package/src/components/simple-video-player.tsx +0 -62
- package/src/components/ui/blur-poster.tsx +0 -93
- package/src/components/ui/empty-state.tsx +0 -91
- package/src/components/ui/enhanced-seek-bar.tsx +0 -254
- package/src/components/ui/error-state.tsx +0 -124
- package/src/components/ui/fullscreen-button.tsx +0 -81
- package/src/components/ui/loading-skeleton.tsx +0 -107
- package/src/components/ui/media-resource-preloader.tsx +0 -458
- package/src/components/ui/offline-message.tsx +0 -98
- package/src/components/ui/play-button.tsx +0 -99
- package/src/components/ui/seek-bar.tsx +0 -191
- package/src/components/ui/time-display.tsx +0 -61
- package/src/components/ui/volume-control.tsx +0 -190
- package/src/components/unified/base-media-player.tsx +0 -252
- package/src/components/unified/media-player.tsx +0 -75
- package/src/components/variants/minimal/AccessibleMinimalPlayer.tsx +0 -587
- package/src/components/variants/minimal/EnhancedMinimalMediaPlayer.tsx +0 -573
- package/src/components/variants/minimal/MinimalControls.tsx +0 -124
- package/src/components/variants/minimal/MinimalLoading.tsx +0 -28
- package/src/components/variants/minimal/MinimalMediaPlayer.tsx +0 -318
- package/src/components/variants/minimal/MinimalOverlay.tsx +0 -58
- package/src/components/variants/minimal/MinimalPlayButton.tsx +0 -56
- package/src/components/variants/minimal/MinimalSeekBar.tsx +0 -140
- package/src/components/variants/minimal/MinimalVolumeControl.tsx +0 -75
- package/src/components/variants/minimal/SimpleMinimalPlayer.tsx +0 -206
- package/src/components/variants/minimal/components/CenterPlayButton.tsx +0 -22
- package/src/components/variants/minimal/components/ControlBar.tsx +0 -142
- package/src/components/variants/minimal/components/EnhancedSettingsMenu.tsx +0 -412
- package/src/components/variants/minimal/components/PlaybackControls.tsx +0 -46
- package/src/components/variants/minimal/components/RightControls.tsx +0 -164
- package/src/components/variants/minimal/components/SeekBar.tsx +0 -127
- package/src/components/variants/minimal/components/SettingsDropdown.tsx +0 -68
- package/src/components/variants/minimal/components/SubtitleDisplay.tsx +0 -21
- package/src/components/variants/minimal/components/TimeDisplay.tsx +0 -15
- package/src/components/variants/minimal/components/VideoElement.tsx +0 -33
- package/src/components/variants/minimal/components/VolumeControl.tsx +0 -220
- package/src/components/variants/minimal/index.ts +0 -23
- package/src/components/video-player.tsx +0 -100
- package/src/context/__tests__/media-store.test.ts +0 -509
- package/src/context/error-handling.ts +0 -398
- package/src/context/media-context.tsx +0 -254
- package/src/context/media-provider.tsx +0 -264
- package/src/context/media-store.ts +0 -387
- package/src/context/persistence.ts +0 -462
- package/src/core/events/event-system.ts +0 -448
- package/src/core/events/hooks.ts +0 -325
- package/src/core/events/index.ts +0 -22
- package/src/core/events/middleware.ts +0 -286
- package/src/core/index.ts +0 -22
- package/src/core/optimization/bundle-optimizer.tsx +0 -312
- package/src/core/performance/cicd.ts +0 -98
- package/src/core/performance/index.ts +0 -38
- package/src/core/performance/media-loading-optimizer.ts +0 -544
- package/src/core/performance/performance-budgets.ts +0 -437
- package/src/core/performance/performance-monitor.tsx +0 -488
- package/src/core/performance/performance-testing.ts +0 -461
- package/src/core/plugins/__tests__/registry.test.ts +0 -595
- package/src/core/plugins/base-plugin.ts +0 -225
- package/src/core/plugins/enhanced-plugin-system.ts +0 -435
- package/src/core/plugins/examples/analytics-plugin.ts +0 -241
- package/src/core/plugins/index.ts +0 -39
- package/src/core/plugins/registry.ts +0 -546
- package/src/core/plugins/types.ts +0 -169
- package/src/core/plugins/utils.ts +0 -317
- package/src/core/progressive-loading.tsx +0 -331
- package/src/core/providers/enhanced-hls-provider.ts +0 -307
- package/src/core/providers/lazy-provider.tsx +0 -14
- package/src/core/providers/service-provider.tsx +0 -164
- package/src/core/utils.tsx +0 -34
- package/src/features/media-session/media-session-manager.ts +0 -411
- package/src/features/picture-in-picture/pip-manager.ts +0 -428
- package/src/features/playlist/playlist-manager.ts +0 -626
- package/src/features/subtitles/subtitle-manager.ts +0 -435
- package/src/features/subtitles/subtitle-parser.ts +0 -284
- package/src/features/thumbnails/thumbnail-generator.ts +0 -528
- package/src/hooks/__tests__/currentTime-fix.test.ts +0 -149
- package/src/hooks/__tests__/use-media-player.test.ts +0 -712
- package/src/hooks/__tests__/use-media-state.test.tsx +0 -316
- package/src/hooks/accessibility/index.ts +0 -27
- package/src/hooks/accessibility/use-accessibility-preferences.ts +0 -190
- package/src/hooks/accessibility/use-focus-management.ts +0 -183
- package/src/hooks/accessibility/use-keyboard-shortcuts.ts +0 -152
- package/src/hooks/accessibility/use-screen-reader.ts +0 -212
- package/src/hooks/core/index.ts +0 -47
- package/src/hooks/legacy.ts +0 -21
- package/src/hooks/use-buffer-health.ts +0 -218
- package/src/hooks/use-enhanced-media-player.ts +0 -575
- package/src/hooks/use-focus-trap.tsx +0 -162
- package/src/hooks/use-intelligent-preloading.ts +0 -387
- package/src/hooks/use-keyboard-controls.ts +0 -115
- package/src/hooks/use-keyboard-shortcuts.ts +0 -255
- package/src/hooks/use-media-actions.ts +0 -184
- package/src/hooks/use-media-metadata.ts +0 -91
- package/src/hooks/use-media-optimistic.ts +0 -264
- package/src/hooks/use-media-player.ts +0 -343
- package/src/hooks/use-media-state.ts +0 -194
- package/src/hooks/use-memory-optimization.ts +0 -360
- package/src/hooks/use-network-status.ts +0 -124
- package/src/hooks/use-optimistic-controls.ts +0 -95
- package/src/hooks/use-optimized-media.ts +0 -283
- package/src/hooks/use-smart-preload.ts +0 -229
- package/src/hooks/use-touch-gestures.ts +0 -461
- package/src/hooks/useEnhancedSubtitles.ts +0 -258
- package/src/hooks/useKeyboardShortcuts.ts +0 -106
- package/src/hooks/useMediaControls.ts +0 -52
- package/src/hooks/useScreenshot.ts +0 -61
- package/src/hooks/useSubtitles.ts +0 -91
- package/src/hooks/useVideoPlayer.ts +0 -278
- package/src/icons/components/FullscreenIcon.tsx +0 -36
- package/src/icons/components/SettingsIcon.tsx +0 -37
- package/src/icons/components/animated/LoadingIcon.tsx +0 -27
- package/src/icons/components/animated/PlayPauseIcon.tsx +0 -42
- package/src/icons/components/media/PauseIcon.tsx +0 -38
- package/src/icons/components/media/PlayIcon.tsx +0 -37
- package/src/icons/components/volume/VolumeIcon.tsx +0 -38
- package/src/icons/components/volume/VolumeOffIcon.tsx +0 -38
- package/src/icons/index.ts +0 -56
- package/src/icons/provider.tsx +0 -58
- package/src/icons/types.ts +0 -60
- package/src/index-enhanced.ts +0 -35
- package/src/index-legacy.ts +0 -324
- package/src/index.css +0 -102
- package/src/lib/__tests__/async-utils.test.ts +0 -291
- package/src/lib/async-utils.ts +0 -194
- package/src/lib/deprecation.ts +0 -51
- package/src/lib/format-time.ts +0 -37
- package/src/lib/index.ts +0 -4
- package/src/lib/utils.ts +0 -6
- package/src/styles/globals.css +0 -462
- package/src/styles/minimal-player.css +0 -621
- package/src/styles/pixel-art.css +0 -41
- package/src/styles/videojs.css +0 -100
- package/src/types/events.ts +0 -47
- package/src/types/formats.ts +0 -79
- package/src/types/index.ts +0 -203
- package/src/types/videojs-plugins.d.ts +0 -14
|
@@ -1,292 +0,0 @@
|
|
|
1
|
-
"use client"
|
|
2
|
-
|
|
3
|
-
import { forwardRef, startTransition, useMemo, useTransition } from "react"
|
|
4
|
-
import { useEnhancedMediaPlayer } from "../hooks/use-enhanced-media-player"
|
|
5
|
-
import { useKeyboardControls } from "../hooks/use-keyboard-controls"
|
|
6
|
-
import { useMemoryOptimization } from "../hooks/use-memory-optimization"
|
|
7
|
-
import { cn } from "../lib/utils"
|
|
8
|
-
import type { MediaPlayerProps } from "../types/index"
|
|
9
|
-
import { EnhancedMediaWrapper } from "./media-suspense"
|
|
10
|
-
|
|
11
|
-
export const MediaPlayer = forwardRef<HTMLDivElement, MediaPlayerProps>(
|
|
12
|
-
(
|
|
13
|
-
{
|
|
14
|
-
src,
|
|
15
|
-
className,
|
|
16
|
-
children,
|
|
17
|
-
keyboardControls = true,
|
|
18
|
-
showControls = true,
|
|
19
|
-
customControls = false,
|
|
20
|
-
crossOrigin,
|
|
21
|
-
enablePerformanceMonitoring = true,
|
|
22
|
-
bufferingStrategy = "adaptive",
|
|
23
|
-
preloadStrategy = "progressive",
|
|
24
|
-
enableOptimizations = true,
|
|
25
|
-
...options
|
|
26
|
-
},
|
|
27
|
-
ref
|
|
28
|
-
) => {
|
|
29
|
-
// React 19 concurrent features
|
|
30
|
-
const [isPending] = useTransition()
|
|
31
|
-
|
|
32
|
-
// Enhanced media player with optimizations
|
|
33
|
-
const { state, controls, mediaRef, containerRef, performanceMetrics, isEnhanced } =
|
|
34
|
-
useEnhancedMediaPlayer({
|
|
35
|
-
src,
|
|
36
|
-
crossOrigin,
|
|
37
|
-
enablePerformanceMonitoring,
|
|
38
|
-
bufferingStrategy,
|
|
39
|
-
preloadStrategy,
|
|
40
|
-
enableTimeUpdateThrottling: true,
|
|
41
|
-
timeUpdateThrottleMs: 100,
|
|
42
|
-
enableSeekPreview: true,
|
|
43
|
-
...options
|
|
44
|
-
})
|
|
45
|
-
|
|
46
|
-
// Memory optimization
|
|
47
|
-
const { memoryStats, addEventListener } = useMemoryOptimization({
|
|
48
|
-
maxMemoryUsage: 50, // 50MB for media player
|
|
49
|
-
cleanupInterval: 15000, // 15 seconds
|
|
50
|
-
enableGC: true,
|
|
51
|
-
monitorMemory: enableOptimizations
|
|
52
|
-
})
|
|
53
|
-
|
|
54
|
-
// Keyboard controls with performance optimization
|
|
55
|
-
useKeyboardControls({
|
|
56
|
-
enabled: keyboardControls,
|
|
57
|
-
state,
|
|
58
|
-
controls
|
|
59
|
-
})
|
|
60
|
-
|
|
61
|
-
// Memoize media type detection
|
|
62
|
-
const isVideo = useMemo(() => {
|
|
63
|
-
return Array.isArray(src)
|
|
64
|
-
? src.some((s) => /\.(mp4|webm|ogv|mov|avi)$/i.test(s))
|
|
65
|
-
: /\.(mp4|webm|ogv|mov|avi)$/i.test(src)
|
|
66
|
-
}, [src])
|
|
67
|
-
|
|
68
|
-
// Memoize source rendering
|
|
69
|
-
const renderSources = useMemo(() => {
|
|
70
|
-
if (!Array.isArray(src)) return null
|
|
71
|
-
|
|
72
|
-
return src.map((source, index) => <source key={`${source}-${index}`} src={source} />)
|
|
73
|
-
}, [src])
|
|
74
|
-
|
|
75
|
-
// Memoize common props
|
|
76
|
-
const commonProps = useMemo(
|
|
77
|
-
() => ({
|
|
78
|
-
controls: showControls && !customControls,
|
|
79
|
-
className: cn(
|
|
80
|
-
"w-full transition-all duration-300",
|
|
81
|
-
isVideo && "aspect-video",
|
|
82
|
-
"bg-[color:var(--media-bg)] rounded-lg",
|
|
83
|
-
state.isTransitioning && "opacity-90"
|
|
84
|
-
),
|
|
85
|
-
preload: preloadStrategy === "eager" ? "auto" : "metadata",
|
|
86
|
-
crossOrigin,
|
|
87
|
-
...(Array.isArray(src) ? {} : { src })
|
|
88
|
-
}),
|
|
89
|
-
[
|
|
90
|
-
showControls,
|
|
91
|
-
customControls,
|
|
92
|
-
isVideo,
|
|
93
|
-
state.isTransitioning,
|
|
94
|
-
preloadStrategy,
|
|
95
|
-
crossOrigin,
|
|
96
|
-
src
|
|
97
|
-
]
|
|
98
|
-
)
|
|
99
|
-
|
|
100
|
-
return (
|
|
101
|
-
<EnhancedMediaWrapper
|
|
102
|
-
priority="high"
|
|
103
|
-
errorFallback={({ error, resetError }) => (
|
|
104
|
-
<div
|
|
105
|
-
className={cn(
|
|
106
|
-
"absolute inset-0 flex items-center justify-center",
|
|
107
|
-
"glass-strong animate-enter rounded-lg",
|
|
108
|
-
"bg-[color:var(--color-error)]/10 backdrop-blur-md"
|
|
109
|
-
)}>
|
|
110
|
-
<div className="space-y-2 text-center text-[color:var(--media-text)]">
|
|
111
|
-
<div className="mx-auto w-fit rounded-full bg-[color:var(--color-error)]/20 p-3">
|
|
112
|
-
<svg
|
|
113
|
-
className="size-6 text-[color:var(--color-error)]"
|
|
114
|
-
fill="none"
|
|
115
|
-
viewBox="0 0 24 24"
|
|
116
|
-
stroke="currentColor">
|
|
117
|
-
<path
|
|
118
|
-
strokeLinecap="round"
|
|
119
|
-
strokeLinejoin="round"
|
|
120
|
-
strokeWidth={2}
|
|
121
|
-
d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
|
|
122
|
-
/>
|
|
123
|
-
</svg>
|
|
124
|
-
</div>
|
|
125
|
-
<p className="font-semibold text-lg">Playback Error</p>
|
|
126
|
-
<p className="max-w-xs text-[color:var(--media-text-secondary)] text-sm">
|
|
127
|
-
{error.message || state.error}
|
|
128
|
-
</p>
|
|
129
|
-
<button
|
|
130
|
-
onClick={resetError}
|
|
131
|
-
className="mt-2 rounded bg-[color:var(--color-brand-primary)] px-4 py-2 text-sm text-white transition-colors hover:bg-[color:var(--color-brand-accent)]">
|
|
132
|
-
Try Again
|
|
133
|
-
</button>
|
|
134
|
-
</div>
|
|
135
|
-
</div>
|
|
136
|
-
)}
|
|
137
|
-
loadingFallback={
|
|
138
|
-
<div
|
|
139
|
-
className={cn(
|
|
140
|
-
"absolute inset-0 flex items-center justify-center",
|
|
141
|
-
"glass animate-enter rounded-lg",
|
|
142
|
-
"bg-[color:var(--media-bg)]/20 backdrop-blur-sm"
|
|
143
|
-
)}>
|
|
144
|
-
<div className="space-y-4 text-center text-[color:var(--media-text)]">
|
|
145
|
-
<div className="relative">
|
|
146
|
-
<div
|
|
147
|
-
className={cn(
|
|
148
|
-
"size-12 animate-spin rounded-full border-2",
|
|
149
|
-
"border-[color:var(--color-brand-accent)]/30",
|
|
150
|
-
"border-t-[color:var(--color-brand-accent)]"
|
|
151
|
-
)}></div>
|
|
152
|
-
<div
|
|
153
|
-
className={cn(
|
|
154
|
-
"absolute inset-0 size-12 rounded-full",
|
|
155
|
-
"bg-gradient-to-r from-[color:var(--color-brand-primary)] to-[color:var(--color-brand-accent)]",
|
|
156
|
-
"animate-pulse opacity-20 blur-sm"
|
|
157
|
-
)}></div>
|
|
158
|
-
</div>
|
|
159
|
-
<p className="font-medium text-[color:var(--media-text-secondary)] text-sm">
|
|
160
|
-
Loading media...
|
|
161
|
-
</p>
|
|
162
|
-
</div>
|
|
163
|
-
</div>
|
|
164
|
-
}>
|
|
165
|
-
<div
|
|
166
|
-
ref={ref || containerRef}
|
|
167
|
-
className={cn(
|
|
168
|
-
"media-container relative overflow-hidden contain-strict",
|
|
169
|
-
"bg-[color:var(--media-bg)] focus-within:outline-none",
|
|
170
|
-
"rounded-xl border border-[color:var(--media-border)]/30",
|
|
171
|
-
"shadow-2xl shadow-[color:var(--media-bg)]/50",
|
|
172
|
-
"transition-all duration-300 ease-out",
|
|
173
|
-
"hover:border-[color:var(--media-border)]/50",
|
|
174
|
-
"hover:shadow-3xl hover:shadow-[color:var(--media-bg)]/60",
|
|
175
|
-
// Performance optimizations
|
|
176
|
-
"will-change-transform",
|
|
177
|
-
state.isTransitioning && "cursor-wait",
|
|
178
|
-
className
|
|
179
|
-
)}
|
|
180
|
-
tabIndex={0}
|
|
181
|
-
// Performance attributes
|
|
182
|
-
role="application"
|
|
183
|
-
aria-label={isVideo ? "Video player" : "Audio player"}
|
|
184
|
-
aria-busy={state.isLoading || state.isBuffering}>
|
|
185
|
-
{isVideo ? (
|
|
186
|
-
<video
|
|
187
|
-
ref={mediaRef as React.RefObject<HTMLVideoElement>}
|
|
188
|
-
{...commonProps}
|
|
189
|
-
// Performance optimizations
|
|
190
|
-
disablePictureInPicture={false}
|
|
191
|
-
playsInline
|
|
192
|
-
x-webkit-airplay="allow"
|
|
193
|
-
style={{ willChange: "transform" }}>
|
|
194
|
-
{renderSources}
|
|
195
|
-
Your browser does not support the video element.
|
|
196
|
-
</video>
|
|
197
|
-
) : (
|
|
198
|
-
<audio
|
|
199
|
-
ref={mediaRef as React.RefObject<HTMLAudioElement>}
|
|
200
|
-
{...commonProps}
|
|
201
|
-
// Performance optimizations
|
|
202
|
-
preload={preloadStrategy === "eager" ? "auto" : "metadata"}
|
|
203
|
-
>
|
|
204
|
-
{renderSources}
|
|
205
|
-
Your browser does not support the audio element.
|
|
206
|
-
</audio>
|
|
207
|
-
)}
|
|
208
|
-
|
|
209
|
-
{state.error && (
|
|
210
|
-
<div
|
|
211
|
-
className={cn(
|
|
212
|
-
"absolute inset-0 flex items-center justify-center",
|
|
213
|
-
"glass-strong animate-enter rounded-lg",
|
|
214
|
-
"bg-[color:var(--color-error)]/10 backdrop-blur-md"
|
|
215
|
-
)}>
|
|
216
|
-
<div className="space-y-2 text-center text-[color:var(--media-text)]">
|
|
217
|
-
<div className="mx-auto w-fit rounded-full bg-[color:var(--color-error)]/20 p-3">
|
|
218
|
-
<svg
|
|
219
|
-
className="size-6 text-[color:var(--color-error)]"
|
|
220
|
-
fill="none"
|
|
221
|
-
viewBox="0 0 24 24"
|
|
222
|
-
stroke="currentColor">
|
|
223
|
-
<path
|
|
224
|
-
strokeLinecap="round"
|
|
225
|
-
strokeLinejoin="round"
|
|
226
|
-
strokeWidth={2}
|
|
227
|
-
d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
|
|
228
|
-
/>
|
|
229
|
-
</svg>
|
|
230
|
-
</div>
|
|
231
|
-
<p className="font-semibold text-lg">Playback Error</p>
|
|
232
|
-
<p className="max-w-xs text-[color:var(--media-text-secondary)] text-sm">
|
|
233
|
-
{state.error}
|
|
234
|
-
</p>
|
|
235
|
-
</div>
|
|
236
|
-
</div>
|
|
237
|
-
)}
|
|
238
|
-
|
|
239
|
-
{state.isLoading && (
|
|
240
|
-
<div
|
|
241
|
-
className={cn(
|
|
242
|
-
"absolute inset-0 flex items-center justify-center",
|
|
243
|
-
"glass animate-enter rounded-lg",
|
|
244
|
-
"bg-[color:var(--media-bg)]/20 backdrop-blur-sm"
|
|
245
|
-
)}>
|
|
246
|
-
<div className="space-y-4 text-center text-[color:var(--media-text)]">
|
|
247
|
-
<div className="relative">
|
|
248
|
-
<div
|
|
249
|
-
className={cn(
|
|
250
|
-
"size-12 animate-spin rounded-full border-2",
|
|
251
|
-
"border-[color:var(--color-brand-accent)]/30",
|
|
252
|
-
"border-t-[color:var(--color-brand-accent)]"
|
|
253
|
-
)}></div>
|
|
254
|
-
<div
|
|
255
|
-
className={cn(
|
|
256
|
-
"absolute inset-0 size-12 rounded-full",
|
|
257
|
-
"bg-gradient-to-r from-[color:var(--color-brand-primary)] to-[color:var(--color-brand-accent)]",
|
|
258
|
-
"animate-pulse opacity-20 blur-sm"
|
|
259
|
-
)}></div>
|
|
260
|
-
</div>
|
|
261
|
-
<p className="font-medium text-[color:var(--media-text-secondary)] text-sm">
|
|
262
|
-
{state.isBuffering ? "Buffering..." : "Loading media..."}
|
|
263
|
-
</p>
|
|
264
|
-
</div>
|
|
265
|
-
</div>
|
|
266
|
-
)}
|
|
267
|
-
|
|
268
|
-
{customControls && typeof children === "function" && (
|
|
269
|
-
<div className="pointer-events-auto absolute inset-0 z-50">
|
|
270
|
-
{children({ state, controls })}
|
|
271
|
-
</div>
|
|
272
|
-
)}
|
|
273
|
-
|
|
274
|
-
{customControls && typeof children !== "function" && (
|
|
275
|
-
<div className="pointer-events-auto absolute inset-0 z-50">{children}</div>
|
|
276
|
-
)}
|
|
277
|
-
|
|
278
|
-
{/* Performance indicator for development */}
|
|
279
|
-
{process.env.NODE_ENV === "development" && enablePerformanceMonitoring && (
|
|
280
|
-
<div className="absolute bottom-2 left-2 rounded bg-black/50 px-2 py-1 text-white text-xs">
|
|
281
|
-
<div>FPS: {performanceMetrics.frameRate || 0}</div>
|
|
282
|
-
<div>Memory: {memoryStats.usage.toFixed(1)}MB</div>
|
|
283
|
-
{isEnhanced && <div>Enhanced ✓</div>}
|
|
284
|
-
</div>
|
|
285
|
-
)}
|
|
286
|
-
</div>
|
|
287
|
-
</EnhancedMediaWrapper>
|
|
288
|
-
)
|
|
289
|
-
}
|
|
290
|
-
)
|
|
291
|
-
|
|
292
|
-
MediaPlayer.displayName = "MediaPlayer"
|
|
@@ -1,344 +0,0 @@
|
|
|
1
|
-
"use client"
|
|
2
|
-
|
|
3
|
-
import React, { Suspense } from "react"
|
|
4
|
-
import { cn } from "../lib/utils"
|
|
5
|
-
|
|
6
|
-
// Loading state component for media operations
|
|
7
|
-
export interface MediaLoadingProps {
|
|
8
|
-
children?: React.ReactNode
|
|
9
|
-
className?: string
|
|
10
|
-
size?: "sm" | "md" | "lg"
|
|
11
|
-
variant?: "spinner" | "skeleton" | "pulse"
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export function MediaLoading({
|
|
15
|
-
children,
|
|
16
|
-
className,
|
|
17
|
-
size = "md",
|
|
18
|
-
variant = "spinner"
|
|
19
|
-
}: MediaLoadingProps) {
|
|
20
|
-
const sizeClasses = {
|
|
21
|
-
sm: "w-4 h-4",
|
|
22
|
-
md: "w-8 h-8",
|
|
23
|
-
lg: "w-12 h-12"
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
if (variant === "spinner") {
|
|
27
|
-
return (
|
|
28
|
-
<div className={cn("flex items-center justify-center", className)}>
|
|
29
|
-
<div
|
|
30
|
-
className={cn(
|
|
31
|
-
"animate-spin rounded-full border-2 border-current border-t-transparent",
|
|
32
|
-
sizeClasses[size]
|
|
33
|
-
)}
|
|
34
|
-
/>
|
|
35
|
-
{children && <span className="ml-2 text-muted-foreground text-sm">{children}</span>}
|
|
36
|
-
</div>
|
|
37
|
-
)
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
if (variant === "skeleton") {
|
|
41
|
-
return <div className={cn("animate-pulse rounded bg-muted", sizeClasses[size], className)} />
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
// Pulse variant
|
|
45
|
-
return (
|
|
46
|
-
<div
|
|
47
|
-
className={cn(
|
|
48
|
-
"animate-pulse bg-gradient-to-r bg-pos-0 bg-size-200 from-muted via-muted/50 to-muted",
|
|
49
|
-
"animate-shimmer rounded",
|
|
50
|
-
sizeClasses[size],
|
|
51
|
-
className
|
|
52
|
-
)}
|
|
53
|
-
/>
|
|
54
|
-
)
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
// Suspense wrapper for media components
|
|
58
|
-
export interface MediaSuspenseProps {
|
|
59
|
-
children: React.ReactNode
|
|
60
|
-
fallback?: React.ReactNode
|
|
61
|
-
className?: string
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
export function MediaSuspense({
|
|
65
|
-
children,
|
|
66
|
-
fallback = <MediaLoading />,
|
|
67
|
-
className
|
|
68
|
-
}: MediaSuspenseProps) {
|
|
69
|
-
return (
|
|
70
|
-
<div className={className}>
|
|
71
|
-
<Suspense fallback={fallback}>{children}</Suspense>
|
|
72
|
-
</div>
|
|
73
|
-
)
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
// Lazy loading wrapper for heavy media components
|
|
77
|
-
export function withMediaSuspense<P extends object>(
|
|
78
|
-
Component: React.ComponentType<P>,
|
|
79
|
-
loadingComponent?: React.ComponentType
|
|
80
|
-
) {
|
|
81
|
-
const WrappedComponent = React.forwardRef<any, P>((props, ref) => {
|
|
82
|
-
const LoadingComp = loadingComponent
|
|
83
|
-
return (
|
|
84
|
-
<MediaSuspense fallback={LoadingComp ? <LoadingComp /> : <MediaLoading />}>
|
|
85
|
-
<Component {...(props as any)} ref={ref} />
|
|
86
|
-
</MediaSuspense>
|
|
87
|
-
)
|
|
88
|
-
})
|
|
89
|
-
|
|
90
|
-
WrappedComponent.displayName = `withMediaSuspense(${Component.displayName || Component.name})`
|
|
91
|
-
|
|
92
|
-
return WrappedComponent
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
// Hook for managing concurrent state updates
|
|
96
|
-
export function useMediaConcurrent() {
|
|
97
|
-
const [isPending, startTransition] = React.useTransition()
|
|
98
|
-
|
|
99
|
-
// Wrap state updates in transitions for better performance
|
|
100
|
-
const updateWithTransition = React.useCallback(
|
|
101
|
-
(updateFn: () => any): Promise<any> => {
|
|
102
|
-
return new Promise((resolve) => {
|
|
103
|
-
startTransition(() => {
|
|
104
|
-
const result = updateFn()
|
|
105
|
-
resolve(result)
|
|
106
|
-
})
|
|
107
|
-
})
|
|
108
|
-
},
|
|
109
|
-
[startTransition]
|
|
110
|
-
)
|
|
111
|
-
|
|
112
|
-
// Batch multiple updates together
|
|
113
|
-
const batchUpdates = React.useCallback(
|
|
114
|
-
(updates: Array<() => any>): Promise<any[]> => {
|
|
115
|
-
return new Promise((resolve) => {
|
|
116
|
-
startTransition(() => {
|
|
117
|
-
const results = updates.map((update) => update())
|
|
118
|
-
resolve(results)
|
|
119
|
-
})
|
|
120
|
-
})
|
|
121
|
-
},
|
|
122
|
-
[startTransition]
|
|
123
|
-
)
|
|
124
|
-
|
|
125
|
-
return {
|
|
126
|
-
isPending,
|
|
127
|
-
updateWithTransition,
|
|
128
|
-
batchUpdates
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
// Error boundary for media components
|
|
133
|
-
export interface MediaErrorBoundaryProps {
|
|
134
|
-
children: React.ReactNode
|
|
135
|
-
fallback?: React.ComponentType<{ error: Error; resetError: () => void }>
|
|
136
|
-
onError?: (error: Error, errorInfo: React.ErrorInfo) => void
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
interface MediaErrorBoundaryState {
|
|
140
|
-
hasError: boolean
|
|
141
|
-
error: Error | null
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
// Default error fallback component
|
|
145
|
-
function DefaultErrorFallback({
|
|
146
|
-
error,
|
|
147
|
-
resetError
|
|
148
|
-
}: {
|
|
149
|
-
error: Error
|
|
150
|
-
resetError: () => void
|
|
151
|
-
}) {
|
|
152
|
-
return (
|
|
153
|
-
<div className="flex flex-col items-center justify-center rounded-lg border border-destructive/20 bg-destructive/10 p-6">
|
|
154
|
-
<div className="mb-2 font-semibold text-destructive text-lg">Media Player Error</div>
|
|
155
|
-
<div className="mb-4 text-center text-muted-foreground text-sm">{error.message}</div>
|
|
156
|
-
<button
|
|
157
|
-
onClick={resetError}
|
|
158
|
-
className="rounded bg-primary px-4 py-2 text-primary-foreground transition-colors hover:bg-primary/90">
|
|
159
|
-
Try Again
|
|
160
|
-
</button>
|
|
161
|
-
</div>
|
|
162
|
-
)
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
export class MediaErrorBoundary extends React.Component<
|
|
166
|
-
MediaErrorBoundaryProps,
|
|
167
|
-
MediaErrorBoundaryState
|
|
168
|
-
> {
|
|
169
|
-
constructor(props: MediaErrorBoundaryProps) {
|
|
170
|
-
super(props)
|
|
171
|
-
this.state = { hasError: false, error: null }
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
static getDerivedStateFromError(error: Error): MediaErrorBoundaryState {
|
|
175
|
-
return { hasError: true, error }
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {
|
|
179
|
-
this.props.onError?.(error, errorInfo)
|
|
180
|
-
console.error("MediaErrorBoundary caught an error:", error, errorInfo)
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
resetError = () => {
|
|
184
|
-
this.setState({ hasError: false, error: null })
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
render() {
|
|
188
|
-
if (this.state.hasError && this.state.error) {
|
|
189
|
-
const FallbackComponent = this.props.fallback || DefaultErrorFallback
|
|
190
|
-
return <FallbackComponent error={this.state.error} resetError={this.resetError} />
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
return this.props.children
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
// Concurrent media component wrapper
|
|
198
|
-
export interface ConcurrentMediaProps {
|
|
199
|
-
children: React.ReactNode
|
|
200
|
-
priority?: "high" | "normal" | "low"
|
|
201
|
-
deferredMs?: number
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
export function ConcurrentMedia({
|
|
205
|
-
children,
|
|
206
|
-
priority = "normal",
|
|
207
|
-
deferredMs = 0
|
|
208
|
-
}: ConcurrentMediaProps) {
|
|
209
|
-
const [isDeferred, setIsDeferred] = React.useState(deferredMs > 0)
|
|
210
|
-
|
|
211
|
-
// Always call hooks unconditionally
|
|
212
|
-
const deferredChildren = React.useDeferredValue(children)
|
|
213
|
-
|
|
214
|
-
React.useEffect(() => {
|
|
215
|
-
if (deferredMs > 0) {
|
|
216
|
-
const timer = setTimeout(() => {
|
|
217
|
-
setIsDeferred(false)
|
|
218
|
-
}, deferredMs)
|
|
219
|
-
|
|
220
|
-
return () => clearTimeout(timer)
|
|
221
|
-
}
|
|
222
|
-
}, [deferredMs])
|
|
223
|
-
|
|
224
|
-
if (isDeferred) {
|
|
225
|
-
return <MediaLoading variant="skeleton" />
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
// Use different rendering strategies based on priority
|
|
229
|
-
if (priority === "high") {
|
|
230
|
-
// Render immediately without deferring
|
|
231
|
-
return <>{children}</>
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
if (priority === "low") {
|
|
235
|
-
// Use deferred value for lower priority updates
|
|
236
|
-
return <>{deferredChildren}</>
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
// Normal priority - use transition
|
|
240
|
-
return <React.Suspense fallback={<MediaLoading />}>{children}</React.Suspense>
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
// Hook for deferred loading of media resources
|
|
244
|
-
export function useDeferredMediaLoading(delay: number = 100) {
|
|
245
|
-
const [isReady, setIsReady] = React.useState(false)
|
|
246
|
-
const deferredIsReady = React.useDeferredValue(isReady)
|
|
247
|
-
|
|
248
|
-
React.useEffect(() => {
|
|
249
|
-
const timer = setTimeout(() => {
|
|
250
|
-
setIsReady(true)
|
|
251
|
-
}, delay)
|
|
252
|
-
|
|
253
|
-
return () => clearTimeout(timer)
|
|
254
|
-
}, [delay])
|
|
255
|
-
|
|
256
|
-
return {
|
|
257
|
-
isReady: deferredIsReady,
|
|
258
|
-
actualIsReady: isReady
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
// Media component with full React 19 concurrent features
|
|
263
|
-
export interface EnhancedMediaWrapperProps {
|
|
264
|
-
children: React.ReactNode
|
|
265
|
-
className?: string
|
|
266
|
-
loadingFallback?: React.ReactNode
|
|
267
|
-
errorFallback?: React.ComponentType<{ error: Error; resetError: () => void }>
|
|
268
|
-
priority?: "high" | "normal" | "low"
|
|
269
|
-
deferredMs?: number
|
|
270
|
-
onError?: (error: Error, errorInfo: React.ErrorInfo) => void
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
export function EnhancedMediaWrapper({
|
|
274
|
-
children,
|
|
275
|
-
className,
|
|
276
|
-
loadingFallback = <MediaLoading />,
|
|
277
|
-
errorFallback,
|
|
278
|
-
priority = "normal",
|
|
279
|
-
deferredMs = 0,
|
|
280
|
-
onError
|
|
281
|
-
}: EnhancedMediaWrapperProps) {
|
|
282
|
-
return (
|
|
283
|
-
<div className={className}>
|
|
284
|
-
<MediaErrorBoundary fallback={errorFallback} onError={onError}>
|
|
285
|
-
<MediaSuspense fallback={loadingFallback}>
|
|
286
|
-
<ConcurrentMedia priority={priority} deferredMs={deferredMs}>
|
|
287
|
-
{children}
|
|
288
|
-
</ConcurrentMedia>
|
|
289
|
-
</MediaSuspense>
|
|
290
|
-
</MediaErrorBoundary>
|
|
291
|
-
</div>
|
|
292
|
-
)
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
// Export enhanced components with concurrent features
|
|
296
|
-
export const EnhancedMediaSuspense = MediaSuspense
|
|
297
|
-
export const EnhancedMediaLoading = MediaLoading
|
|
298
|
-
|
|
299
|
-
// Performance monitoring hook for concurrent features
|
|
300
|
-
export function useMediaPerformance() {
|
|
301
|
-
const [metrics, setMetrics] = React.useState({
|
|
302
|
-
renderTime: 0,
|
|
303
|
-
suspenseCount: 0,
|
|
304
|
-
errorCount: 0,
|
|
305
|
-
transitionCount: 0
|
|
306
|
-
})
|
|
307
|
-
|
|
308
|
-
const recordRenderTime = React.useCallback((startTime: number) => {
|
|
309
|
-
const renderTime = performance.now() - startTime
|
|
310
|
-
setMetrics((prev) => ({
|
|
311
|
-
...prev,
|
|
312
|
-
renderTime: Math.round(renderTime * 100) / 100
|
|
313
|
-
}))
|
|
314
|
-
}, [])
|
|
315
|
-
|
|
316
|
-
const incrementSuspense = React.useCallback(() => {
|
|
317
|
-
setMetrics((prev) => ({
|
|
318
|
-
...prev,
|
|
319
|
-
suspenseCount: prev.suspenseCount + 1
|
|
320
|
-
}))
|
|
321
|
-
}, [])
|
|
322
|
-
|
|
323
|
-
const incrementError = React.useCallback(() => {
|
|
324
|
-
setMetrics((prev) => ({
|
|
325
|
-
...prev,
|
|
326
|
-
errorCount: prev.errorCount + 1
|
|
327
|
-
}))
|
|
328
|
-
}, [])
|
|
329
|
-
|
|
330
|
-
const incrementTransition = React.useCallback(() => {
|
|
331
|
-
setMetrics((prev) => ({
|
|
332
|
-
...prev,
|
|
333
|
-
transitionCount: prev.transitionCount + 1
|
|
334
|
-
}))
|
|
335
|
-
}, [])
|
|
336
|
-
|
|
337
|
-
return {
|
|
338
|
-
metrics,
|
|
339
|
-
recordRenderTime,
|
|
340
|
-
incrementSuspense,
|
|
341
|
-
incrementError,
|
|
342
|
-
incrementTransition
|
|
343
|
-
}
|
|
344
|
-
}
|