@djangocfg/ui-nextjs 2.1.65 → 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 (92) hide show
  1. package/package.json +13 -8
  2. package/src/blocks/SplitHero/SplitHeroMedia.tsx +2 -1
  3. package/src/stores/index.ts +8 -0
  4. package/src/stores/mediaCache.ts +464 -0
  5. package/src/tools/AudioPlayer/@refactoring/00-PLAN.md +148 -0
  6. package/src/tools/AudioPlayer/@refactoring/01-TYPES.md +301 -0
  7. package/src/tools/AudioPlayer/@refactoring/02-HOOKS.md +281 -0
  8. package/src/tools/AudioPlayer/@refactoring/03-CONTEXT.md +328 -0
  9. package/src/tools/AudioPlayer/@refactoring/04-COMPONENTS.md +251 -0
  10. package/src/tools/AudioPlayer/@refactoring/05-EFFECTS.md +427 -0
  11. package/src/tools/AudioPlayer/@refactoring/06-UTILS-AND-INDEX.md +193 -0
  12. package/src/tools/AudioPlayer/@refactoring/07-EXECUTION-CHECKLIST.md +146 -0
  13. package/src/tools/AudioPlayer/README.md +325 -0
  14. package/src/tools/AudioPlayer/components/AudioEqualizer.tsx +200 -0
  15. package/src/tools/AudioPlayer/components/AudioPlayer.tsx +231 -0
  16. package/src/tools/AudioPlayer/components/AudioShortcutsPopover.tsx +99 -0
  17. package/src/tools/AudioPlayer/components/ReactiveCover/AudioReactiveCover.tsx +147 -0
  18. package/src/tools/AudioPlayer/components/ReactiveCover/effects/GlowEffect.tsx +110 -0
  19. package/src/tools/AudioPlayer/components/ReactiveCover/effects/MeshEffect.tsx +58 -0
  20. package/src/tools/AudioPlayer/components/ReactiveCover/effects/OrbsEffect.tsx +45 -0
  21. package/src/tools/AudioPlayer/components/ReactiveCover/effects/SpotlightEffect.tsx +82 -0
  22. package/src/tools/AudioPlayer/components/ReactiveCover/effects/index.ts +8 -0
  23. package/src/tools/AudioPlayer/components/ReactiveCover/index.ts +6 -0
  24. package/src/tools/AudioPlayer/components/SimpleAudioPlayer.tsx +280 -0
  25. package/src/tools/AudioPlayer/components/VisualizationToggle.tsx +64 -0
  26. package/src/tools/AudioPlayer/components/index.ts +21 -0
  27. package/src/tools/AudioPlayer/context/AudioProvider.tsx +292 -0
  28. package/src/tools/AudioPlayer/context/index.ts +11 -0
  29. package/src/tools/AudioPlayer/context/selectors.ts +96 -0
  30. package/src/tools/AudioPlayer/effects/index.ts +412 -0
  31. package/src/tools/AudioPlayer/hooks/index.ts +29 -0
  32. package/src/tools/AudioPlayer/hooks/useAudioAnalysis.ts +110 -0
  33. package/src/tools/AudioPlayer/hooks/useAudioHotkeys.ts +149 -0
  34. package/src/tools/AudioPlayer/hooks/useSharedWebAudio.ts +106 -0
  35. package/src/tools/AudioPlayer/hooks/useVisualization.tsx +201 -0
  36. package/src/tools/AudioPlayer/index.ts +139 -0
  37. package/src/tools/AudioPlayer/types/audio.ts +107 -0
  38. package/src/tools/AudioPlayer/types/components.ts +98 -0
  39. package/src/tools/AudioPlayer/types/effects.ts +73 -0
  40. package/src/tools/AudioPlayer/types/index.ts +35 -0
  41. package/src/tools/AudioPlayer/utils/formatTime.ts +10 -0
  42. package/src/tools/AudioPlayer/utils/index.ts +5 -0
  43. package/src/tools/ImageViewer/@refactoring/00-PLAN.md +71 -0
  44. package/src/tools/ImageViewer/@refactoring/01-TYPES.md +121 -0
  45. package/src/tools/ImageViewer/@refactoring/02-UTILS.md +143 -0
  46. package/src/tools/ImageViewer/@refactoring/03-HOOKS.md +261 -0
  47. package/src/tools/ImageViewer/@refactoring/04-COMPONENTS.md +427 -0
  48. package/src/tools/ImageViewer/@refactoring/05-EXECUTION-CHECKLIST.md +126 -0
  49. package/src/tools/ImageViewer/README.md +174 -0
  50. package/src/tools/ImageViewer/components/ImageInfo.tsx +44 -0
  51. package/src/tools/ImageViewer/components/ImageToolbar.tsx +150 -0
  52. package/src/tools/ImageViewer/components/ImageViewer.tsx +235 -0
  53. package/src/tools/ImageViewer/components/index.ts +7 -0
  54. package/src/tools/ImageViewer/hooks/index.ts +9 -0
  55. package/src/tools/ImageViewer/hooks/useImageLoading.ts +153 -0
  56. package/src/tools/ImageViewer/hooks/useImageTransform.ts +101 -0
  57. package/src/tools/ImageViewer/index.ts +60 -0
  58. package/src/tools/ImageViewer/types.ts +75 -0
  59. package/src/tools/ImageViewer/utils/constants.ts +59 -0
  60. package/src/tools/ImageViewer/utils/index.ts +16 -0
  61. package/src/tools/ImageViewer/utils/lqip.ts +47 -0
  62. package/src/tools/VideoPlayer/@refactoring/00-PLAN.md +91 -0
  63. package/src/tools/VideoPlayer/@refactoring/01-TYPES.md +284 -0
  64. package/src/tools/VideoPlayer/@refactoring/02-UTILS.md +141 -0
  65. package/src/tools/VideoPlayer/@refactoring/03-HOOKS.md +178 -0
  66. package/src/tools/VideoPlayer/@refactoring/04-COMPONENTS.md +95 -0
  67. package/src/tools/VideoPlayer/@refactoring/05-EXECUTION-CHECKLIST.md +139 -0
  68. package/src/tools/VideoPlayer/README.md +212 -187
  69. package/src/tools/VideoPlayer/{VideoControls.tsx → components/VideoControls.tsx} +8 -9
  70. package/src/tools/VideoPlayer/components/VideoErrorFallback.tsx +174 -0
  71. package/src/tools/VideoPlayer/components/VideoPlayer.tsx +201 -0
  72. package/src/tools/VideoPlayer/components/index.ts +14 -0
  73. package/src/tools/VideoPlayer/context/VideoPlayerContext.tsx +52 -0
  74. package/src/tools/VideoPlayer/context/index.ts +8 -0
  75. package/src/tools/VideoPlayer/hooks/index.ts +9 -0
  76. package/src/tools/VideoPlayer/hooks/useVideoPositionCache.ts +109 -0
  77. package/src/tools/VideoPlayer/index.ts +70 -9
  78. package/src/tools/VideoPlayer/providers/NativeProvider.tsx +206 -0
  79. package/src/tools/VideoPlayer/providers/StreamProvider.tsx +401 -0
  80. package/src/tools/VideoPlayer/providers/VidstackProvider.tsx +332 -0
  81. package/src/tools/VideoPlayer/providers/index.ts +8 -0
  82. package/src/tools/VideoPlayer/types/index.ts +38 -0
  83. package/src/tools/VideoPlayer/types/player.ts +116 -0
  84. package/src/tools/VideoPlayer/types/provider.ts +93 -0
  85. package/src/tools/VideoPlayer/types/sources.ts +97 -0
  86. package/src/tools/VideoPlayer/utils/fileSource.ts +78 -0
  87. package/src/tools/VideoPlayer/utils/index.ts +11 -0
  88. package/src/tools/VideoPlayer/utils/resolvers.ts +75 -0
  89. package/src/tools/index.ts +92 -4
  90. package/src/tools/VideoPlayer/NativePlayer.tsx +0 -141
  91. package/src/tools/VideoPlayer/VideoPlayer.tsx +0 -231
  92. package/src/tools/VideoPlayer/types.ts +0 -118
@@ -0,0 +1,106 @@
1
+ 'use client';
2
+
3
+ /**
4
+ * useSharedWebAudio - Manages a shared Web Audio context and source node.
5
+ *
6
+ * This prevents the "InvalidStateError" from creating multiple MediaElementSourceNodes
7
+ * for the same audio element. All analyzers share the same source.
8
+ */
9
+
10
+ import { useRef, useEffect, useCallback } from 'react';
11
+ import type { SharedWebAudioContext } from '../types';
12
+
13
+ export function useSharedWebAudio(audioElement: HTMLMediaElement | null): SharedWebAudioContext {
14
+ const audioContextRef = useRef<AudioContext | null>(null);
15
+ const sourceRef = useRef<MediaElementAudioSourceNode | null>(null);
16
+ const connectedElementRef = useRef<HTMLMediaElement | null>(null);
17
+ const analyserNodesRef = useRef<Set<AnalyserNode>>(new Set());
18
+
19
+ // Initialize Web Audio on first play
20
+ useEffect(() => {
21
+ if (!audioElement) return;
22
+
23
+ // Already connected to this element
24
+ if (connectedElementRef.current === audioElement && audioContextRef.current) {
25
+ return;
26
+ }
27
+
28
+ const initAudio = () => {
29
+ try {
30
+ if (!audioContextRef.current) {
31
+ const AudioContextClass = window.AudioContext ||
32
+ (window as unknown as { webkitAudioContext: typeof AudioContext }).webkitAudioContext;
33
+ audioContextRef.current = new AudioContextClass();
34
+ }
35
+
36
+ const audioContext = audioContextRef.current;
37
+
38
+ // Only create source node once per audio element
39
+ if (connectedElementRef.current !== audioElement) {
40
+ if (sourceRef.current) {
41
+ try { sourceRef.current.disconnect(); } catch { /* ignore */ }
42
+ }
43
+
44
+ sourceRef.current = audioContext.createMediaElementSource(audioElement);
45
+ // Connect directly to destination (analysers will be inserted in between)
46
+ sourceRef.current.connect(audioContext.destination);
47
+ connectedElementRef.current = audioElement;
48
+ }
49
+ } catch (error) {
50
+ console.warn('[SharedWebAudio] Could not initialize:', error);
51
+ }
52
+ };
53
+
54
+ const handlePlay = () => {
55
+ initAudio();
56
+ if (audioContextRef.current?.state === 'suspended') {
57
+ audioContextRef.current.resume();
58
+ }
59
+ };
60
+
61
+ audioElement.addEventListener('play', handlePlay);
62
+ if (!audioElement.paused) {
63
+ handlePlay();
64
+ }
65
+
66
+ return () => {
67
+ audioElement.removeEventListener('play', handlePlay);
68
+ };
69
+ }, [audioElement]);
70
+
71
+ // Create an analyser connected to the shared source
72
+ const createAnalyser = useCallback((options?: { fftSize?: number; smoothing?: number }): AnalyserNode | null => {
73
+ if (!audioContextRef.current || !sourceRef.current) return null;
74
+
75
+ try {
76
+ const analyser = audioContextRef.current.createAnalyser();
77
+ analyser.fftSize = options?.fftSize ?? 256;
78
+ analyser.smoothingTimeConstant = options?.smoothing ?? 0.85;
79
+
80
+ // Connect: source -> analyser -> destination
81
+ sourceRef.current.connect(analyser);
82
+ analyser.connect(audioContextRef.current.destination);
83
+
84
+ analyserNodesRef.current.add(analyser);
85
+ return analyser;
86
+ } catch (error) {
87
+ console.warn('[SharedWebAudio] Could not create analyser:', error);
88
+ return null;
89
+ }
90
+ }, []);
91
+
92
+ // Disconnect an analyser
93
+ const disconnectAnalyser = useCallback((analyser: AnalyserNode) => {
94
+ try {
95
+ analyser.disconnect();
96
+ analyserNodesRef.current.delete(analyser);
97
+ } catch { /* ignore */ }
98
+ }, []);
99
+
100
+ return {
101
+ audioContext: audioContextRef.current,
102
+ sourceNode: sourceRef.current,
103
+ createAnalyser,
104
+ disconnectAnalyser,
105
+ };
106
+ }
@@ -0,0 +1,201 @@
1
+ 'use client';
2
+
3
+ /**
4
+ * useVisualization - Hook for managing audio visualization settings
5
+ *
6
+ * Persists settings in localStorage for user preferences
7
+ * Uses React Context for shared state between components
8
+ */
9
+
10
+ import { createContext, useContext, useCallback, useMemo, type ReactNode } from 'react';
11
+ import { useLocalStorage } from '@djangocfg/ui-nextjs';
12
+
13
+ // =============================================================================
14
+ // TYPES
15
+ // =============================================================================
16
+
17
+ export type VisualizationVariant = 'glow' | 'orbs' | 'spotlight' | 'mesh' | 'none';
18
+ export type VisualizationIntensity = 'subtle' | 'medium' | 'strong';
19
+ export type VisualizationColorScheme = 'primary' | 'vibrant' | 'cool' | 'warm';
20
+
21
+ export interface VisualizationSettings {
22
+ /** Enable reactive cover animation */
23
+ enabled: boolean;
24
+ /** Visual effect variant */
25
+ variant: VisualizationVariant;
26
+ /** Effect intensity */
27
+ intensity: VisualizationIntensity;
28
+ /** Color scheme */
29
+ colorScheme: VisualizationColorScheme;
30
+ }
31
+
32
+ export interface UseVisualizationReturn {
33
+ /** Current settings */
34
+ settings: VisualizationSettings;
35
+ /** Toggle visualization on/off */
36
+ toggle: () => void;
37
+ /** Set specific setting */
38
+ setSetting: <K extends keyof VisualizationSettings>(
39
+ key: K,
40
+ value: VisualizationSettings[K]
41
+ ) => void;
42
+ /** Cycle to next variant */
43
+ nextVariant: () => void;
44
+ /** Cycle to next intensity */
45
+ nextIntensity: () => void;
46
+ /** Cycle to next color scheme */
47
+ nextColorScheme: () => void;
48
+ /** Reset to defaults */
49
+ reset: () => void;
50
+ }
51
+
52
+ // Backward compatibility alias
53
+ export type UseAudioVisualizationReturn = UseVisualizationReturn;
54
+
55
+ // =============================================================================
56
+ // CONSTANTS
57
+ // =============================================================================
58
+
59
+ const STORAGE_KEY = 'audio-visualization-settings';
60
+
61
+ const DEFAULT_SETTINGS: VisualizationSettings = {
62
+ enabled: true,
63
+ variant: 'spotlight',
64
+ intensity: 'medium',
65
+ colorScheme: 'primary',
66
+ };
67
+
68
+ const VARIANTS: VisualizationVariant[] = ['spotlight', 'glow', 'orbs', 'mesh', 'none'];
69
+ const INTENSITIES: VisualizationIntensity[] = ['subtle', 'medium', 'strong'];
70
+ const COLOR_SCHEMES: VisualizationColorScheme[] = ['primary', 'vibrant', 'cool', 'warm'];
71
+
72
+ // =============================================================================
73
+ // CONTEXT
74
+ // =============================================================================
75
+
76
+ const VisualizationContext = createContext<UseVisualizationReturn | null>(null);
77
+
78
+ // =============================================================================
79
+ // PROVIDER
80
+ // =============================================================================
81
+
82
+ export interface VisualizationProviderProps {
83
+ children: ReactNode;
84
+ }
85
+
86
+ export function VisualizationProvider({ children }: VisualizationProviderProps) {
87
+ const value = useVisualizationState();
88
+ return (
89
+ <VisualizationContext.Provider value={value}>
90
+ {children}
91
+ </VisualizationContext.Provider>
92
+ );
93
+ }
94
+
95
+ // =============================================================================
96
+ // INTERNAL HOOK (creates the actual state)
97
+ // =============================================================================
98
+
99
+ function useVisualizationState(): UseVisualizationReturn {
100
+ const [settings, setSettings] = useLocalStorage<VisualizationSettings>(
101
+ STORAGE_KEY,
102
+ DEFAULT_SETTINGS
103
+ );
104
+
105
+ const toggle = useCallback(() => {
106
+ setSettings((prev) => ({ ...prev, enabled: !prev.enabled }));
107
+ }, [setSettings]);
108
+
109
+ const setSetting = useCallback(
110
+ <K extends keyof VisualizationSettings>(
111
+ key: K,
112
+ value: VisualizationSettings[K]
113
+ ) => {
114
+ setSettings((prev) => ({ ...prev, [key]: value }));
115
+ },
116
+ [setSettings]
117
+ );
118
+
119
+ const nextVariant = useCallback(() => {
120
+ setSettings((prev) => {
121
+ const currentIndex = VARIANTS.indexOf(prev.variant);
122
+ const nextIndex = (currentIndex + 1) % VARIANTS.length;
123
+ return { ...prev, variant: VARIANTS[nextIndex] };
124
+ });
125
+ }, [setSettings]);
126
+
127
+ const nextIntensity = useCallback(() => {
128
+ setSettings((prev) => {
129
+ const currentIndex = INTENSITIES.indexOf(prev.intensity);
130
+ const nextIndex = (currentIndex + 1) % INTENSITIES.length;
131
+ return { ...prev, intensity: INTENSITIES[nextIndex] };
132
+ });
133
+ }, [setSettings]);
134
+
135
+ const nextColorScheme = useCallback(() => {
136
+ setSettings((prev) => {
137
+ const currentIndex = COLOR_SCHEMES.indexOf(prev.colorScheme);
138
+ const nextIndex = (currentIndex + 1) % COLOR_SCHEMES.length;
139
+ return { ...prev, colorScheme: COLOR_SCHEMES[nextIndex] };
140
+ });
141
+ }, [setSettings]);
142
+
143
+ const reset = useCallback(() => {
144
+ setSettings(DEFAULT_SETTINGS);
145
+ }, [setSettings]);
146
+
147
+ return useMemo(
148
+ () => ({
149
+ settings,
150
+ toggle,
151
+ setSetting,
152
+ nextVariant,
153
+ nextIntensity,
154
+ nextColorScheme,
155
+ reset,
156
+ }),
157
+ [settings, toggle, setSetting, nextVariant, nextIntensity, nextColorScheme, reset]
158
+ );
159
+ }
160
+
161
+ // =============================================================================
162
+ // HOOK (uses context when available)
163
+ // =============================================================================
164
+
165
+ export function useVisualization(): UseVisualizationReturn {
166
+ const context = useContext(VisualizationContext);
167
+
168
+ // Always call the fallback hooks (React hooks rules require consistent calls)
169
+ const fallbackState = useVisualizationState();
170
+
171
+ // If inside a provider, use shared context; otherwise use fallback
172
+ return context ?? fallbackState;
173
+ }
174
+
175
+ // Backward compatibility alias
176
+ export const useAudioVisualization = useVisualization;
177
+
178
+ // =============================================================================
179
+ // VARIANT INFO
180
+ // =============================================================================
181
+
182
+ export const VARIANT_INFO: Record<VisualizationVariant, { label: string; icon: string }> = {
183
+ spotlight: { label: 'Spotlight', icon: '💫' },
184
+ glow: { label: 'Glow', icon: '✨' },
185
+ orbs: { label: 'Orbs', icon: '🔮' },
186
+ mesh: { label: 'Mesh', icon: '🌈' },
187
+ none: { label: 'Off', icon: '⭕' },
188
+ };
189
+
190
+ export const INTENSITY_INFO: Record<VisualizationIntensity, { label: string }> = {
191
+ subtle: { label: 'Subtle' },
192
+ medium: { label: 'Medium' },
193
+ strong: { label: 'Strong' },
194
+ };
195
+
196
+ export const COLOR_SCHEME_INFO: Record<VisualizationColorScheme, { label: string; preview: string }> = {
197
+ primary: { label: 'Primary', preview: '🔵' },
198
+ vibrant: { label: 'Vibrant', preview: '🌈' },
199
+ cool: { label: 'Cool', preview: '💙' },
200
+ warm: { label: 'Warm', preview: '🔥' },
201
+ };
@@ -0,0 +1,139 @@
1
+ /**
2
+ * AudioPlayer - Complete audio playback solution with reactive visualizations
3
+ *
4
+ * @example
5
+ * // Simple usage
6
+ * import { SimpleAudioPlayer } from '@djangocfg/ui-nextjs';
7
+ * <SimpleAudioPlayer src="/audio.mp3" title="Track Title" />
8
+ *
9
+ * @example
10
+ * // Custom setup with context
11
+ * import { AudioProvider, AudioPlayer, useAudio } from '@djangocfg/ui-nextjs';
12
+ * <AudioProvider source={{ uri: audioUrl }} containerRef={ref}>
13
+ * <AudioPlayer ref={ref} />
14
+ * </AudioProvider>
15
+ */
16
+
17
+ // =============================================================================
18
+ // COMPONENTS
19
+ // =============================================================================
20
+
21
+ export {
22
+ AudioPlayer,
23
+ SimpleAudioPlayer,
24
+ AudioEqualizer,
25
+ AudioShortcutsPopover,
26
+ VisualizationToggle,
27
+ AudioReactiveCover,
28
+ // Effect components (for custom implementations)
29
+ GlowEffect,
30
+ OrbsEffect,
31
+ SpotlightEffect,
32
+ MeshEffect,
33
+ } from './components';
34
+
35
+ export type {
36
+ SimpleAudioPlayerProps,
37
+ VisualizationToggleProps,
38
+ AudioReactiveCoverProps,
39
+ GlowEffectData,
40
+ } from './components';
41
+
42
+ // =============================================================================
43
+ // CONTEXT
44
+ // =============================================================================
45
+
46
+ export {
47
+ AudioProvider,
48
+ AudioPlayerContext,
49
+ useAudio,
50
+ useAudioControls,
51
+ useAudioState,
52
+ useAudioElement,
53
+ } from './context';
54
+
55
+ // =============================================================================
56
+ // HOOKS
57
+ // =============================================================================
58
+
59
+ export {
60
+ // Internal hooks (for custom implementations)
61
+ useSharedWebAudio,
62
+ useAudioAnalysis,
63
+ // Public hooks
64
+ useAudioHotkeys,
65
+ AUDIO_SHORTCUTS,
66
+ // Visualization
67
+ useVisualization,
68
+ useAudioVisualization, // backward compat alias
69
+ VisualizationProvider,
70
+ VARIANT_INFO,
71
+ INTENSITY_INFO,
72
+ COLOR_SCHEME_INFO,
73
+ } from './hooks';
74
+
75
+ export type {
76
+ AudioHotkeyOptions,
77
+ ShortcutItem,
78
+ ShortcutGroup,
79
+ VisualizationSettings,
80
+ VisualizationVariant,
81
+ VisualizationIntensity,
82
+ VisualizationColorScheme,
83
+ UseVisualizationReturn,
84
+ UseAudioVisualizationReturn,
85
+ VisualizationProviderProps,
86
+ } from './hooks';
87
+
88
+ // =============================================================================
89
+ // TYPES
90
+ // =============================================================================
91
+
92
+ export type {
93
+ // Audio types
94
+ AudioSource,
95
+ AudioContextState,
96
+ SharedWebAudioContext,
97
+ WaveformOptions,
98
+ PlaybackStatus,
99
+ // Component types
100
+ AudioPlayerProps,
101
+ AudioEqualizerProps,
102
+ AudioViewerProps,
103
+ EqualizerOptions,
104
+ } from './types';
105
+
106
+ // =============================================================================
107
+ // EFFECTS
108
+ // =============================================================================
109
+
110
+ export {
111
+ // Utilities
112
+ getEffectConfig,
113
+ getColors,
114
+ prepareEffectColors,
115
+ calculateGlowLayers,
116
+ calculateOrbs,
117
+ calculateMeshGradients,
118
+ calculateSpotlight,
119
+ // Constants
120
+ INTENSITY_CONFIG,
121
+ COLOR_SCHEMES,
122
+ EFFECT_ANIMATIONS,
123
+ } from './effects';
124
+
125
+ export type {
126
+ EffectVariant,
127
+ EffectIntensity,
128
+ EffectColorScheme,
129
+ AudioLevels,
130
+ EffectConfig,
131
+ EffectColors,
132
+ EffectLayer,
133
+ } from './effects';
134
+
135
+ // =============================================================================
136
+ // UTILITIES
137
+ // =============================================================================
138
+
139
+ export { formatTime } from './utils';
@@ -0,0 +1,107 @@
1
+ /**
2
+ * Core audio-related types
3
+ */
4
+
5
+ import type WaveSurfer from 'wavesurfer.js';
6
+ import type { AudioLevels } from './effects';
7
+
8
+ // =============================================================================
9
+ // AUDIO SOURCE
10
+ // =============================================================================
11
+
12
+ export interface AudioSource {
13
+ uri: string;
14
+ }
15
+
16
+ // =============================================================================
17
+ // PLAYBACK STATE
18
+ // =============================================================================
19
+
20
+ export interface PlaybackStatus {
21
+ isLoaded: boolean;
22
+ isPlaying: boolean;
23
+ duration: number;
24
+ currentTime: number;
25
+ volume: number;
26
+ isMuted: boolean;
27
+ }
28
+
29
+ // =============================================================================
30
+ // WAVEFORM OPTIONS
31
+ // =============================================================================
32
+
33
+ export interface WaveformOptions {
34
+ waveColor?: string;
35
+ progressColor?: string;
36
+ height?: number;
37
+ barWidth?: number;
38
+ barRadius?: number;
39
+ barGap?: number;
40
+ cursorWidth?: number;
41
+ cursorColor?: string;
42
+ }
43
+
44
+ // =============================================================================
45
+ // EQUALIZER OPTIONS
46
+ // =============================================================================
47
+
48
+ export interface EqualizerOptions {
49
+ barCount?: number;
50
+ height?: number;
51
+ gap?: number;
52
+ showPeaks?: boolean;
53
+ barColor?: string;
54
+ peakColor?: string;
55
+ }
56
+
57
+ // =============================================================================
58
+ // SHARED WEB AUDIO CONTEXT
59
+ // =============================================================================
60
+
61
+ export interface SharedWebAudioContext {
62
+ /** The Web Audio AudioContext instance */
63
+ audioContext: AudioContext | null;
64
+ /** The MediaElementSourceNode connected to the audio element */
65
+ sourceNode: MediaElementAudioSourceNode | null;
66
+ /** Create an AnalyserNode connected to the shared source */
67
+ createAnalyser: (options?: { fftSize?: number; smoothing?: number }) => AnalyserNode | null;
68
+ /** Disconnect and cleanup an AnalyserNode */
69
+ disconnectAnalyser: (analyser: AnalyserNode) => void;
70
+ }
71
+
72
+ // =============================================================================
73
+ // AUDIO CONTEXT STATE
74
+ // =============================================================================
75
+
76
+ export interface AudioContextState {
77
+ // Core instances
78
+ wavesurfer: WaveSurfer | null;
79
+ audioElement: HTMLMediaElement | null;
80
+ /** Shared Web Audio context for analyzers */
81
+ sharedAudio: SharedWebAudioContext;
82
+
83
+ // Playback state
84
+ isReady: boolean;
85
+ isPlaying: boolean;
86
+ currentTime: number;
87
+ duration: number;
88
+ volume: number;
89
+ isMuted: boolean;
90
+ isLooping: boolean;
91
+
92
+ // Audio analysis (for reactive effects)
93
+ audioLevels: AudioLevels;
94
+
95
+ // Actions
96
+ play: () => Promise<void>;
97
+ pause: () => void;
98
+ togglePlay: () => void;
99
+ seek: (time: number) => void;
100
+ seekTo: (progress: number) => void;
101
+ skip: (seconds: number) => void;
102
+ setVolume: (volume: number) => void;
103
+ toggleMute: () => void;
104
+ toggleLoop: () => void;
105
+ setLoop: (enabled: boolean) => void;
106
+ restart: () => void;
107
+ }
@@ -0,0 +1,98 @@
1
+ /**
2
+ * Component props types
3
+ */
4
+
5
+ import type { CSSProperties } from 'react';
6
+ import type { WaveformOptions, EqualizerOptions, AudioSource, PlaybackStatus } from './audio';
7
+
8
+ // =============================================================================
9
+ // AUDIO PLAYER PROPS
10
+ // =============================================================================
11
+
12
+ export interface AudioPlayerProps {
13
+ /** Show playback controls */
14
+ showControls?: boolean;
15
+ /** Show waveform visualization */
16
+ showWaveform?: boolean;
17
+ /** Show equalizer animation */
18
+ showEqualizer?: boolean;
19
+ /** Show timer (position/duration) */
20
+ showTimer?: boolean;
21
+ /** Show volume control */
22
+ showVolume?: boolean;
23
+ /** Show loop/repeat button */
24
+ showLoop?: boolean;
25
+ /** WaveSurfer options override */
26
+ waveformOptions?: WaveformOptions;
27
+ /** Equalizer options */
28
+ equalizerOptions?: EqualizerOptions;
29
+ /** Additional class name */
30
+ className?: string;
31
+ /** Additional styles */
32
+ style?: CSSProperties;
33
+ }
34
+
35
+ // =============================================================================
36
+ // AUDIO EQUALIZER PROPS
37
+ // =============================================================================
38
+
39
+ export interface AudioEqualizerProps {
40
+ /** Number of frequency bars */
41
+ barCount?: number;
42
+ /** Height of the equalizer in pixels */
43
+ height?: number;
44
+ /** Gap between bars in pixels */
45
+ gap?: number;
46
+ /** Show peak indicators */
47
+ showPeaks?: boolean;
48
+ /** Bar color (CSS color) */
49
+ barColor?: string;
50
+ /** Peak indicator color */
51
+ peakColor?: string;
52
+ /** Additional class name */
53
+ className?: string;
54
+ }
55
+
56
+ // =============================================================================
57
+ // AUDIO REACTIVE COVER PROPS
58
+ // =============================================================================
59
+
60
+ export interface AudioReactiveCoverProps {
61
+ /** Visual variant */
62
+ variant?: 'glow' | 'orbs' | 'spotlight' | 'mesh';
63
+ /** Intensity of effects */
64
+ intensity?: 'subtle' | 'medium' | 'strong';
65
+ /** Color scheme */
66
+ colorScheme?: 'primary' | 'vibrant' | 'cool' | 'warm';
67
+ }
68
+
69
+ // =============================================================================
70
+ // AUDIO VIEWER PROPS (legacy)
71
+ // =============================================================================
72
+
73
+ export interface AudioViewerProps {
74
+ /** Audio source URL */
75
+ source: AudioSource;
76
+ /** Auto-play when loaded */
77
+ autoPlay?: boolean;
78
+ /** Show playback controls */
79
+ showControls?: boolean;
80
+ /** Show waveform visualization */
81
+ showWaveform?: boolean;
82
+ /** Show equalizer animation */
83
+ showEqualizer?: boolean;
84
+ /** Show timer */
85
+ showTimer?: boolean;
86
+ /** Show volume control */
87
+ showVolume?: boolean;
88
+ /** Waveform options */
89
+ waveformOptions?: WaveformOptions;
90
+ /** Equalizer options */
91
+ equalizerOptions?: EqualizerOptions;
92
+ /** Callback on playback status change */
93
+ onPlaybackStatusUpdate?: (status: PlaybackStatus) => void;
94
+ /** Additional class name */
95
+ className?: string;
96
+ /** Additional styles */
97
+ style?: CSSProperties;
98
+ }