@djangocfg/ui-nextjs 2.1.66 → 2.1.67

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. package/package.json +8 -6
  2. package/src/stores/index.ts +8 -0
  3. package/src/stores/mediaCache.ts +464 -0
  4. package/src/tools/AudioPlayer/@refactoring/00-PLAN.md +148 -0
  5. package/src/tools/AudioPlayer/@refactoring/01-TYPES.md +301 -0
  6. package/src/tools/AudioPlayer/@refactoring/02-HOOKS.md +281 -0
  7. package/src/tools/AudioPlayer/@refactoring/03-CONTEXT.md +328 -0
  8. package/src/tools/AudioPlayer/@refactoring/04-COMPONENTS.md +251 -0
  9. package/src/tools/AudioPlayer/@refactoring/05-EFFECTS.md +427 -0
  10. package/src/tools/AudioPlayer/@refactoring/06-UTILS-AND-INDEX.md +193 -0
  11. package/src/tools/AudioPlayer/@refactoring/07-EXECUTION-CHECKLIST.md +146 -0
  12. package/src/tools/AudioPlayer/README.md +35 -11
  13. package/src/tools/AudioPlayer/{AudioEqualizer.tsx → components/AudioEqualizer.tsx} +29 -64
  14. package/src/tools/AudioPlayer/{AudioPlayer.tsx → components/AudioPlayer.tsx} +22 -14
  15. package/src/tools/AudioPlayer/{AudioShortcutsPopover.tsx → components/AudioShortcutsPopover.tsx} +6 -2
  16. package/src/tools/AudioPlayer/components/ReactiveCover/AudioReactiveCover.tsx +147 -0
  17. package/src/tools/AudioPlayer/components/ReactiveCover/effects/GlowEffect.tsx +110 -0
  18. package/src/tools/AudioPlayer/components/ReactiveCover/effects/MeshEffect.tsx +58 -0
  19. package/src/tools/AudioPlayer/components/ReactiveCover/effects/OrbsEffect.tsx +45 -0
  20. package/src/tools/AudioPlayer/components/ReactiveCover/effects/SpotlightEffect.tsx +82 -0
  21. package/src/tools/AudioPlayer/components/ReactiveCover/effects/index.ts +8 -0
  22. package/src/tools/AudioPlayer/components/ReactiveCover/index.ts +6 -0
  23. package/src/tools/AudioPlayer/{SimpleAudioPlayer.tsx → components/SimpleAudioPlayer.tsx} +12 -7
  24. package/src/tools/AudioPlayer/{VisualizationToggle.tsx → components/VisualizationToggle.tsx} +2 -6
  25. package/src/tools/AudioPlayer/components/index.ts +21 -0
  26. package/src/tools/AudioPlayer/context/AudioProvider.tsx +292 -0
  27. package/src/tools/AudioPlayer/context/index.ts +11 -0
  28. package/src/tools/AudioPlayer/context/selectors.ts +96 -0
  29. package/src/tools/AudioPlayer/hooks/index.ts +29 -0
  30. package/src/tools/AudioPlayer/hooks/useAudioAnalysis.ts +110 -0
  31. package/src/tools/AudioPlayer/{useAudioHotkeys.ts → hooks/useAudioHotkeys.ts} +11 -4
  32. package/src/tools/AudioPlayer/hooks/useSharedWebAudio.ts +106 -0
  33. package/src/tools/AudioPlayer/{useAudioVisualization.tsx → hooks/useVisualization.tsx} +11 -5
  34. package/src/tools/AudioPlayer/index.ts +104 -49
  35. package/src/tools/AudioPlayer/types/audio.ts +107 -0
  36. package/src/tools/AudioPlayer/{types.ts → types/components.ts} +20 -84
  37. package/src/tools/AudioPlayer/types/effects.ts +73 -0
  38. package/src/tools/AudioPlayer/types/index.ts +35 -0
  39. package/src/tools/AudioPlayer/utils/formatTime.ts +10 -0
  40. package/src/tools/AudioPlayer/utils/index.ts +5 -0
  41. package/src/tools/ImageViewer/@refactoring/00-PLAN.md +71 -0
  42. package/src/tools/ImageViewer/@refactoring/01-TYPES.md +121 -0
  43. package/src/tools/ImageViewer/@refactoring/02-UTILS.md +143 -0
  44. package/src/tools/ImageViewer/@refactoring/03-HOOKS.md +261 -0
  45. package/src/tools/ImageViewer/@refactoring/04-COMPONENTS.md +427 -0
  46. package/src/tools/ImageViewer/@refactoring/05-EXECUTION-CHECKLIST.md +126 -0
  47. package/src/tools/ImageViewer/README.md +16 -3
  48. package/src/tools/ImageViewer/components/ImageInfo.tsx +44 -0
  49. package/src/tools/ImageViewer/components/ImageToolbar.tsx +150 -0
  50. package/src/tools/ImageViewer/components/ImageViewer.tsx +235 -0
  51. package/src/tools/ImageViewer/components/index.ts +7 -0
  52. package/src/tools/ImageViewer/hooks/index.ts +9 -0
  53. package/src/tools/ImageViewer/hooks/useImageLoading.ts +153 -0
  54. package/src/tools/ImageViewer/hooks/useImageTransform.ts +101 -0
  55. package/src/tools/ImageViewer/index.ts +47 -3
  56. package/src/tools/ImageViewer/types.ts +75 -0
  57. package/src/tools/ImageViewer/utils/constants.ts +59 -0
  58. package/src/tools/ImageViewer/utils/index.ts +16 -0
  59. package/src/tools/ImageViewer/utils/lqip.ts +47 -0
  60. package/src/tools/VideoPlayer/@refactoring/00-PLAN.md +91 -0
  61. package/src/tools/VideoPlayer/@refactoring/01-TYPES.md +284 -0
  62. package/src/tools/VideoPlayer/@refactoring/02-UTILS.md +141 -0
  63. package/src/tools/VideoPlayer/@refactoring/03-HOOKS.md +178 -0
  64. package/src/tools/VideoPlayer/@refactoring/04-COMPONENTS.md +95 -0
  65. package/src/tools/VideoPlayer/@refactoring/05-EXECUTION-CHECKLIST.md +139 -0
  66. package/src/tools/VideoPlayer/README.md +26 -10
  67. package/src/tools/VideoPlayer/{VideoControls.tsx → components/VideoControls.tsx} +8 -9
  68. package/src/tools/VideoPlayer/{VideoErrorFallback.tsx → components/VideoErrorFallback.tsx} +2 -2
  69. package/src/tools/VideoPlayer/{VideoPlayer.tsx → components/VideoPlayer.tsx} +4 -5
  70. package/src/tools/VideoPlayer/components/index.ts +14 -0
  71. package/src/tools/VideoPlayer/context/VideoPlayerContext.tsx +52 -0
  72. package/src/tools/VideoPlayer/context/index.ts +8 -0
  73. package/src/tools/VideoPlayer/hooks/index.ts +9 -0
  74. package/src/tools/VideoPlayer/hooks/useVideoPositionCache.ts +109 -0
  75. package/src/tools/VideoPlayer/index.ts +29 -20
  76. package/src/tools/VideoPlayer/providers/StreamProvider.tsx +118 -28
  77. package/src/tools/VideoPlayer/providers/VidstackProvider.tsx +89 -11
  78. package/src/tools/VideoPlayer/types/index.ts +38 -0
  79. package/src/tools/VideoPlayer/types/player.ts +116 -0
  80. package/src/tools/VideoPlayer/types/provider.ts +93 -0
  81. package/src/tools/VideoPlayer/types/sources.ts +97 -0
  82. package/src/tools/VideoPlayer/utils/fileSource.ts +78 -0
  83. package/src/tools/VideoPlayer/utils/index.ts +11 -0
  84. package/src/tools/VideoPlayer/utils/resolvers.ts +75 -0
  85. package/src/tools/index.ts +10 -0
  86. package/src/tools/AudioPlayer/AudioReactiveCover.tsx +0 -389
  87. package/src/tools/AudioPlayer/context.tsx +0 -426
  88. package/src/tools/ImageViewer/ImageViewer.tsx +0 -416
  89. package/src/tools/VideoPlayer/VideoPlayerContext.tsx +0 -125
  90. package/src/tools/VideoPlayer/types.ts +0 -367
@@ -8,9 +8,53 @@
8
8
  * - Flip horizontal/vertical
9
9
  * - Fullscreen dialog mode
10
10
  * - Keyboard shortcuts (+/-, 0 for reset, r for rotate)
11
+ * - Progressive loading with LQIP for large images
11
12
  * - Checkerboard background for transparency
12
- * - Image dimensions display
13
+ * - Image dimensions display with caching
13
14
  */
14
15
 
15
- export { ImageViewer } from './ImageViewer';
16
- export type { ImageViewerProps, ImageFile } from './ImageViewer';
16
+ // =============================================================================
17
+ // COMPONENTS
18
+ // =============================================================================
19
+
20
+ export { ImageViewer, ImageToolbar, ImageInfo } from './components';
21
+
22
+ // =============================================================================
23
+ // HOOKS
24
+ // =============================================================================
25
+
26
+ export { useImageTransform, useImageLoading } from './hooks';
27
+ export type {
28
+ UseImageTransformOptions,
29
+ UseImageTransformReturn,
30
+ UseImageLoadingOptions,
31
+ UseImageLoadingReturn,
32
+ } from './hooks';
33
+
34
+ // =============================================================================
35
+ // TYPES
36
+ // =============================================================================
37
+
38
+ export type {
39
+ ImageFile,
40
+ ImageViewerProps,
41
+ ImageToolbarProps,
42
+ ImageInfoProps,
43
+ ImageTransform,
44
+ ZoomPreset,
45
+ } from './types';
46
+
47
+ // =============================================================================
48
+ // UTILS
49
+ // =============================================================================
50
+
51
+ export {
52
+ createLQIP,
53
+ MAX_IMAGE_SIZE,
54
+ WARNING_IMAGE_SIZE,
55
+ PROGRESSIVE_LOADING_THRESHOLD,
56
+ MIN_ZOOM,
57
+ MAX_ZOOM,
58
+ ZOOM_PRESETS,
59
+ DEFAULT_TRANSFORM,
60
+ } from './utils';
@@ -0,0 +1,75 @@
1
+ /**
2
+ * ImageViewer type definitions
3
+ */
4
+
5
+ // =============================================================================
6
+ // FILE TYPES
7
+ // =============================================================================
8
+
9
+ export interface ImageFile {
10
+ /** Display name for the image */
11
+ name: string;
12
+ /** File path used for change detection and caching */
13
+ path: string;
14
+ /** Optional MIME type */
15
+ mimeType?: string;
16
+ }
17
+
18
+ // =============================================================================
19
+ // COMPONENT PROPS
20
+ // =============================================================================
21
+
22
+ export interface ImageViewerProps {
23
+ /** File info (name, path, mimeType) */
24
+ file: ImageFile;
25
+ /** Image content as string (data URL or base64) or ArrayBuffer */
26
+ content: string | ArrayBuffer;
27
+ /** Hide expand button when already in dialog */
28
+ inDialog?: boolean;
29
+ }
30
+
31
+ export interface ImageToolbarProps {
32
+ /** Current zoom scale */
33
+ scale: number;
34
+ /** Current transform state */
35
+ transform: ImageTransform;
36
+ /** Rotate image callback */
37
+ onRotate: () => void;
38
+ /** Flip horizontal callback */
39
+ onFlipH: () => void;
40
+ /** Flip vertical callback */
41
+ onFlipV: () => void;
42
+ /** Zoom preset selection callback */
43
+ onZoomPreset: (value: number | 'fit') => void;
44
+ /** Expand to fullscreen callback (undefined hides button) */
45
+ onExpand?: () => void;
46
+ }
47
+
48
+ export interface ImageInfoProps {
49
+ /** Image source URL */
50
+ src: string;
51
+ }
52
+
53
+ // =============================================================================
54
+ // STATE TYPES
55
+ // =============================================================================
56
+
57
+ export interface ImageTransform {
58
+ /** Rotation angle: 0, 90, 180, or 270 degrees */
59
+ rotation: number;
60
+ /** Horizontal flip state */
61
+ flipH: boolean;
62
+ /** Vertical flip state */
63
+ flipV: boolean;
64
+ }
65
+
66
+ // =============================================================================
67
+ // UI TYPES
68
+ // =============================================================================
69
+
70
+ export interface ZoomPreset {
71
+ /** Display label (e.g., "100%", "Fit") */
72
+ label: string;
73
+ /** Zoom value or 'fit' for fit-to-view */
74
+ value: number | 'fit';
75
+ }
@@ -0,0 +1,59 @@
1
+ /**
2
+ * ImageViewer constants
3
+ */
4
+
5
+ import type { ZoomPreset, ImageTransform } from '../types';
6
+
7
+ // =============================================================================
8
+ // SIZE LIMITS
9
+ // =============================================================================
10
+
11
+ /** Maximum image size before blocking (50MB) */
12
+ export const MAX_IMAGE_SIZE = 50 * 1024 * 1024;
13
+
14
+ /** Image size threshold for warning (10MB) */
15
+ export const WARNING_IMAGE_SIZE = 10 * 1024 * 1024;
16
+
17
+ /** Progressive loading threshold - use LQIP for images > 500KB */
18
+ export const PROGRESSIVE_LOADING_THRESHOLD = 500 * 1024;
19
+
20
+ // =============================================================================
21
+ // LQIP CONFIGURATION
22
+ // =============================================================================
23
+
24
+ /** Low-quality placeholder size (32x32) */
25
+ export const LQIP_SIZE = 32;
26
+
27
+ /** LQIP JPEG quality */
28
+ export const LQIP_QUALITY = 0.5;
29
+
30
+ // =============================================================================
31
+ // ZOOM CONFIGURATION
32
+ // =============================================================================
33
+
34
+ /** Minimum zoom level */
35
+ export const MIN_ZOOM = 0.1;
36
+
37
+ /** Maximum zoom level */
38
+ export const MAX_ZOOM = 8;
39
+
40
+ /** Available zoom presets */
41
+ export const ZOOM_PRESETS: readonly ZoomPreset[] = [
42
+ { label: 'Fit', value: 'fit' },
43
+ { label: '25%', value: 0.25 },
44
+ { label: '50%', value: 0.5 },
45
+ { label: '100%', value: 1 },
46
+ { label: '200%', value: 2 },
47
+ { label: '400%', value: 4 },
48
+ ] as const;
49
+
50
+ // =============================================================================
51
+ // DEFAULT VALUES
52
+ // =============================================================================
53
+
54
+ /** Default transform state */
55
+ export const DEFAULT_TRANSFORM: ImageTransform = {
56
+ rotation: 0,
57
+ flipH: false,
58
+ flipV: false,
59
+ };
@@ -0,0 +1,16 @@
1
+ /**
2
+ * ImageViewer utilities - Public API
3
+ */
4
+
5
+ export { createLQIP } from './lqip';
6
+ export {
7
+ MAX_IMAGE_SIZE,
8
+ WARNING_IMAGE_SIZE,
9
+ PROGRESSIVE_LOADING_THRESHOLD,
10
+ LQIP_SIZE,
11
+ LQIP_QUALITY,
12
+ MIN_ZOOM,
13
+ MAX_ZOOM,
14
+ ZOOM_PRESETS,
15
+ DEFAULT_TRANSFORM,
16
+ } from './constants';
@@ -0,0 +1,47 @@
1
+ /**
2
+ * LQIP (Low-Quality Image Placeholder) generator
3
+ *
4
+ * Creates a tiny blurred preview image for progressive loading.
5
+ */
6
+
7
+ import { LQIP_SIZE, LQIP_QUALITY } from './constants';
8
+
9
+ /**
10
+ * Create a low-quality image placeholder from source URL
11
+ *
12
+ * @param imageSrc - Full quality image URL
13
+ * @returns Data URL of tiny preview, or null on error
14
+ */
15
+ export async function createLQIP(imageSrc: string): Promise<string | null> {
16
+ try {
17
+ // Load the full image
18
+ const img = new Image();
19
+ img.crossOrigin = 'anonymous';
20
+
21
+ await new Promise<void>((resolve, reject) => {
22
+ img.onload = () => resolve();
23
+ img.onerror = () => reject(new Error('Failed to load image for LQIP'));
24
+ img.src = imageSrc;
25
+ });
26
+
27
+ // Calculate aspect ratio preserving dimensions
28
+ const aspect = img.naturalWidth / img.naturalHeight;
29
+ const width = aspect >= 1 ? LQIP_SIZE : Math.round(LQIP_SIZE * aspect);
30
+ const height = aspect >= 1 ? Math.round(LQIP_SIZE / aspect) : LQIP_SIZE;
31
+
32
+ // Create canvas for downscaling
33
+ const canvas = document.createElement('canvas');
34
+ canvas.width = width;
35
+ canvas.height = height;
36
+ const ctx = canvas.getContext('2d');
37
+ if (!ctx) return null;
38
+
39
+ // Draw scaled down image
40
+ ctx.drawImage(img, 0, 0, width, height);
41
+
42
+ // Return as data URL (very small, ~1-2KB)
43
+ return canvas.toDataURL('image/jpeg', LQIP_QUALITY);
44
+ } catch {
45
+ return null;
46
+ }
47
+ }
@@ -0,0 +1,91 @@
1
+ # VideoPlayer Refactoring Plan
2
+
3
+ ## Overview
4
+
5
+ The VideoPlayer is already reasonably well-organized with a `providers/` subfolder. This refactoring focuses on incremental improvements rather than major restructuring.
6
+
7
+ **Total: 2,024 lines across 10 files**
8
+
9
+ ## Current Structure (Before)
10
+
11
+ ```
12
+ VideoPlayer/
13
+ ├── index.ts (68 lines) # Public exports
14
+ ├── types.ts (369 lines) # All types + helper functions ⚠️
15
+ ├── VideoPlayer.tsx (202 lines) # Main orchestrator
16
+ ├── VideoPlayerContext.tsx (125 lines) # Streaming context
17
+ ├── VideoControls.tsx (139 lines) # Vidstack controls
18
+ ├── VideoErrorFallback.tsx (174 lines) # Error UI
19
+ ├── README.md
20
+ └── providers/
21
+ ├── index.ts (8 lines)
22
+ ├── VidstackProvider.tsx (332 lines) # YouTube/Vimeo/HLS/DASH
23
+ ├── NativeProvider.tsx (206 lines) # HTML5 <video>
24
+ └── StreamProvider.tsx (401 lines) # HTTP Range + Blob ⚠️
25
+ ```
26
+
27
+ **Issues Identified:**
28
+ 1. `types.ts` (369 lines) - Contains types AND helper functions
29
+ 2. `StreamProvider.tsx` (401 lines) - Largest file, multiple concerns
30
+ 3. Position caching logic duplicated in VidstackProvider & StreamProvider
31
+ 4. No dedicated hooks/ folder
32
+
33
+ ## Target Structure (After)
34
+
35
+ ```
36
+ VideoPlayer/
37
+ ├── index.ts # Public API
38
+ ├── README.md
39
+ ├── types/
40
+ │ ├── index.ts # Re-exports all types
41
+ │ ├── sources.ts # Source type definitions
42
+ │ ├── player.ts # Player props and config types
43
+ │ └── provider.ts # Provider-specific types
44
+ ├── hooks/
45
+ │ ├── index.ts
46
+ │ └── useVideoPositionCache.ts # Extracted caching logic
47
+ ├── utils/
48
+ │ ├── index.ts
49
+ │ ├── resolvers.ts # resolvePlayerMode, resolveFileSource
50
+ │ └── stream.ts # Stream URL generation helpers
51
+ ├── components/
52
+ │ ├── index.ts
53
+ │ ├── VideoPlayer.tsx # Main component
54
+ │ ├── VideoControls.tsx # Vidstack controls
55
+ │ └── VideoErrorFallback.tsx # Error UI
56
+ ├── context/
57
+ │ ├── index.ts
58
+ │ └── VideoPlayerContext.tsx
59
+ └── providers/
60
+ ├── index.ts
61
+ ├── VidstackProvider.tsx
62
+ ├── NativeProvider.tsx
63
+ └── StreamProvider.tsx
64
+ ```
65
+
66
+ ## Benefits
67
+
68
+ 1. **DRY Principle** - Extract duplicated position caching logic
69
+ 2. **Separation of Concerns** - Types split by domain
70
+ 3. **Consistent Structure** - Matches AudioPlayer/ImageViewer patterns
71
+ 4. **Maintainability** - Easier to find and modify specific functionality
72
+ 5. **Testability** - Hooks and utils can be unit tested
73
+
74
+ ## Execution Phases
75
+
76
+ | Phase | Description | Files |
77
+ |-------|-------------|-------|
78
+ | 1 | Create folder structure | types/, hooks/, utils/, components/, context/ |
79
+ | 2 | Split types | sources.ts, player.ts, provider.ts |
80
+ | 3 | Extract utils | resolvers.ts, stream.ts |
81
+ | 4 | Extract hooks | useVideoPositionCache.ts |
82
+ | 5 | Move components | VideoPlayer.tsx, VideoControls.tsx, VideoErrorFallback.tsx |
83
+ | 6 | Move context | VideoPlayerContext.tsx |
84
+ | 7 | Update exports | index.ts |
85
+ | 8 | Cleanup and verify | Delete old files, run pnpm check |
86
+
87
+ ## Risk Assessment
88
+
89
+ - **Low Risk**: Incremental changes, no logic modifications
90
+ - **Testing**: Run `pnpm check` after each phase
91
+ - **Providers**: Already well-organized, minimal changes needed
@@ -0,0 +1,284 @@
1
+ # Phase 1: Types Split
2
+
3
+ ## Goal
4
+
5
+ Split the 369-line `types.ts` into domain-specific files and move helper functions to utils.
6
+
7
+ ## Current Structure
8
+
9
+ ```typescript
10
+ // types.ts (369 lines)
11
+ // Contains:
12
+ // 1. Source types (UrlSource, YouTubeSource, VimeoSource, HLSSource, etc.)
13
+ // 2. Player types (PlayerMode, AspectRatioValue, VideoPlayerProps, etc.)
14
+ // 3. Provider types (VidstackProviderProps, NativeProviderProps, etc.)
15
+ // 4. Helper functions (resolvePlayerMode, resolveFileSource, isSimpleStreamSource)
16
+ ```
17
+
18
+ ## Target Files
19
+
20
+ ### types/sources.ts (~120 lines)
21
+
22
+ All source type definitions:
23
+
24
+ ```typescript
25
+ /**
26
+ * Video source type definitions
27
+ */
28
+
29
+ // URL source (direct video URL)
30
+ export interface UrlSource {
31
+ type: 'url';
32
+ url: string;
33
+ mimeType?: string;
34
+ }
35
+
36
+ // YouTube embed
37
+ export interface YouTubeSource {
38
+ type: 'youtube';
39
+ videoId: string;
40
+ startTime?: number;
41
+ }
42
+
43
+ // Vimeo embed
44
+ export interface VimeoSource {
45
+ type: 'vimeo';
46
+ videoId: string;
47
+ startTime?: number;
48
+ }
49
+
50
+ // HLS streaming
51
+ export interface HLSSource {
52
+ type: 'hls';
53
+ url: string;
54
+ }
55
+
56
+ // DASH streaming
57
+ export interface DASHSource {
58
+ type: 'dash';
59
+ url: string;
60
+ }
61
+
62
+ // HTTP Range streaming with auth
63
+ export interface StreamSource {
64
+ type: 'stream';
65
+ streamKey: string;
66
+ fileName: string;
67
+ fileSize?: number;
68
+ mimeType?: string;
69
+ getStreamUrl: (streamKey: string) => Promise<string>;
70
+ }
71
+
72
+ // Simple stream (resolved via context)
73
+ export interface SimpleStreamSource {
74
+ type: 'stream';
75
+ streamKey: string;
76
+ fileName: string;
77
+ fileSize?: number;
78
+ mimeType?: string;
79
+ }
80
+
81
+ // Blob (ArrayBuffer)
82
+ export interface BlobSource {
83
+ type: 'blob';
84
+ data: ArrayBuffer;
85
+ mimeType?: string;
86
+ fileName?: string;
87
+ }
88
+
89
+ // Data URL (base64)
90
+ export interface DataUrlSource {
91
+ type: 'data-url';
92
+ dataUrl: string;
93
+ mimeType?: string;
94
+ }
95
+
96
+ // Union of all sources
97
+ export type VideoSourceUnion =
98
+ | UrlSource
99
+ | YouTubeSource
100
+ | VimeoSource
101
+ | HLSSource
102
+ | DASHSource
103
+ | StreamSource
104
+ | BlobSource
105
+ | DataUrlSource;
106
+ ```
107
+
108
+ ### types/player.ts (~100 lines)
109
+
110
+ Player configuration and main component types:
111
+
112
+ ```typescript
113
+ /**
114
+ * Player configuration types
115
+ */
116
+
117
+ import type { ReactNode, CSSProperties } from 'react';
118
+ import type { VideoSourceUnion } from './sources';
119
+
120
+ // Player mode
121
+ export type PlayerMode = 'auto' | 'vidstack' | 'native' | 'streaming';
122
+
123
+ // Aspect ratio
124
+ export type AspectRatioValue = number | 'auto' | 'fill';
125
+
126
+ // Common settings
127
+ export interface CommonPlayerSettings {
128
+ autoPlay?: boolean;
129
+ muted?: boolean;
130
+ loop?: boolean;
131
+ playsInline?: boolean;
132
+ controls?: boolean;
133
+ preload?: 'none' | 'metadata' | 'auto';
134
+ }
135
+
136
+ // Common events
137
+ export interface CommonPlayerEvents {
138
+ onPlay?: () => void;
139
+ onPause?: () => void;
140
+ onEnded?: () => void;
141
+ onTimeUpdate?: (currentTime: number) => void;
142
+ onError?: (error: Error) => void;
143
+ onLoadStart?: () => void;
144
+ onCanPlay?: () => void;
145
+ }
146
+
147
+ // Error fallback props
148
+ export interface ErrorFallbackProps {
149
+ error: Error | null;
150
+ source: VideoSourceUnion;
151
+ retry?: () => void;
152
+ }
153
+
154
+ // Main component props
155
+ export interface VideoPlayerProps extends CommonPlayerSettings, CommonPlayerEvents {
156
+ source: VideoSourceUnion;
157
+ mode?: PlayerMode;
158
+ aspectRatio?: AspectRatioValue;
159
+ poster?: string;
160
+ className?: string;
161
+ style?: CSSProperties;
162
+ errorFallback?: (props: ErrorFallbackProps) => ReactNode;
163
+ }
164
+
165
+ // Ref API
166
+ export interface VideoPlayerRef {
167
+ play: () => Promise<void>;
168
+ pause: () => void;
169
+ seek: (time: number) => void;
170
+ setVolume: (volume: number) => void;
171
+ setMuted: (muted: boolean) => void;
172
+ requestFullscreen: () => Promise<void>;
173
+ exitFullscreen: () => Promise<void>;
174
+ readonly currentTime: number;
175
+ readonly duration: number;
176
+ readonly paused: boolean;
177
+ readonly muted: boolean;
178
+ readonly volume: number;
179
+ readonly isFullscreen: boolean;
180
+ }
181
+ ```
182
+
183
+ ### types/provider.ts (~80 lines)
184
+
185
+ Provider-specific types:
186
+
187
+ ```typescript
188
+ /**
189
+ * Provider-specific types
190
+ */
191
+
192
+ import type { ReactNode } from 'react';
193
+ import type { VideoSourceUnion, StreamSource, BlobSource, DataUrlSource } from './sources';
194
+ import type { CommonPlayerSettings, CommonPlayerEvents, AspectRatioValue, ErrorFallbackProps } from './player';
195
+
196
+ // Vidstack provider props
197
+ export interface VidstackProviderProps extends CommonPlayerSettings, CommonPlayerEvents {
198
+ source: VideoSourceUnion;
199
+ aspectRatio?: AspectRatioValue;
200
+ poster?: string;
201
+ className?: string;
202
+ errorFallback?: (props: ErrorFallbackProps) => ReactNode;
203
+ }
204
+
205
+ // Native provider props
206
+ export interface NativeProviderProps extends CommonPlayerSettings, CommonPlayerEvents {
207
+ source: VideoSourceUnion;
208
+ aspectRatio?: AspectRatioValue;
209
+ poster?: string;
210
+ className?: string;
211
+ disableContextMenu?: boolean;
212
+ }
213
+
214
+ // Stream provider props
215
+ export interface StreamProviderProps extends CommonPlayerSettings, CommonPlayerEvents {
216
+ source: StreamSource | BlobSource | DataUrlSource;
217
+ aspectRatio?: AspectRatioValue;
218
+ poster?: string;
219
+ className?: string;
220
+ errorFallback?: (props: ErrorFallbackProps) => ReactNode;
221
+ }
222
+
223
+ // File source resolution options
224
+ export interface ResolveFileSourceOptions {
225
+ fileName: string;
226
+ content: string | ArrayBuffer;
227
+ mimeType?: string;
228
+ }
229
+
230
+ // Context value
231
+ export interface VideoPlayerContextValue {
232
+ getStreamUrl?: (streamKey: string) => Promise<string>;
233
+ }
234
+
235
+ export interface VideoPlayerProviderProps {
236
+ getStreamUrl: (streamKey: string) => Promise<string>;
237
+ children: ReactNode;
238
+ }
239
+ ```
240
+
241
+ ### types/index.ts
242
+
243
+ Re-export all types:
244
+
245
+ ```typescript
246
+ /**
247
+ * VideoPlayer types - Public API
248
+ */
249
+
250
+ // Source types
251
+ export type {
252
+ UrlSource,
253
+ YouTubeSource,
254
+ VimeoSource,
255
+ HLSSource,
256
+ DASHSource,
257
+ StreamSource,
258
+ SimpleStreamSource,
259
+ BlobSource,
260
+ DataUrlSource,
261
+ VideoSourceUnion,
262
+ } from './sources';
263
+
264
+ // Player types
265
+ export type {
266
+ PlayerMode,
267
+ AspectRatioValue,
268
+ CommonPlayerSettings,
269
+ CommonPlayerEvents,
270
+ ErrorFallbackProps,
271
+ VideoPlayerProps,
272
+ VideoPlayerRef,
273
+ } from './player';
274
+
275
+ // Provider types
276
+ export type {
277
+ VidstackProviderProps,
278
+ NativeProviderProps,
279
+ StreamProviderProps,
280
+ ResolveFileSourceOptions,
281
+ VideoPlayerContextValue,
282
+ VideoPlayerProviderProps,
283
+ } from './provider';
284
+ ```