@djangocfg/ui-nextjs 2.1.89 → 2.1.91

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 (161) hide show
  1. package/README.md +6 -15
  2. package/package.json +6 -25
  3. package/src/blocks/SplitHero/SplitHeroMedia.tsx +1 -1
  4. package/src/components/index.ts +0 -40
  5. package/src/hooks/index.ts +0 -6
  6. package/src/index.ts +2 -11
  7. package/src/components/button-download.tsx +0 -277
  8. package/src/components/markdown/MarkdownMessage.tsx +0 -340
  9. package/src/components/markdown/index.ts +0 -5
  10. package/src/components/menubar.tsx +0 -275
  11. package/src/components/multi-select-pro/async.tsx +0 -598
  12. package/src/components/multi-select-pro/helpers.tsx +0 -84
  13. package/src/components/multi-select-pro/index.tsx +0 -612
  14. package/src/components/navigation-menu.tsx +0 -154
  15. package/src/components/otp/index.tsx +0 -197
  16. package/src/components/otp/types.ts +0 -133
  17. package/src/components/otp/use-otp-input.ts +0 -225
  18. package/src/components/phone-input.tsx +0 -277
  19. package/src/components/sonner.tsx +0 -32
  20. package/src/hooks/useLocalStorage.ts +0 -300
  21. package/src/hooks/useSessionStorage.ts +0 -290
  22. package/src/lib/index.ts +0 -5
  23. package/src/lib/logger/index.ts +0 -10
  24. package/src/lib/logger/logStore.ts +0 -122
  25. package/src/lib/logger/logger.ts +0 -175
  26. package/src/lib/logger/types.ts +0 -82
  27. package/src/stores/index.ts +0 -8
  28. package/src/stores/mediaCache.ts +0 -534
  29. package/src/tools/AudioPlayer/README.md +0 -206
  30. package/src/tools/AudioPlayer/components/HybridAudioPlayer.tsx +0 -216
  31. package/src/tools/AudioPlayer/components/HybridSimplePlayer.tsx +0 -280
  32. package/src/tools/AudioPlayer/components/HybridWaveform.tsx +0 -279
  33. package/src/tools/AudioPlayer/components/ReactiveCover/AudioReactiveCover.tsx +0 -149
  34. package/src/tools/AudioPlayer/components/ReactiveCover/effects/GlowEffect.tsx +0 -110
  35. package/src/tools/AudioPlayer/components/ReactiveCover/effects/MeshEffect.tsx +0 -58
  36. package/src/tools/AudioPlayer/components/ReactiveCover/effects/OrbsEffect.tsx +0 -45
  37. package/src/tools/AudioPlayer/components/ReactiveCover/effects/SpotlightEffect.tsx +0 -82
  38. package/src/tools/AudioPlayer/components/ReactiveCover/effects/index.ts +0 -8
  39. package/src/tools/AudioPlayer/components/ReactiveCover/index.ts +0 -6
  40. package/src/tools/AudioPlayer/components/index.ts +0 -22
  41. package/src/tools/AudioPlayer/context/HybridAudioProvider.tsx +0 -158
  42. package/src/tools/AudioPlayer/context/index.ts +0 -16
  43. package/src/tools/AudioPlayer/effects/index.ts +0 -412
  44. package/src/tools/AudioPlayer/hooks/index.ts +0 -35
  45. package/src/tools/AudioPlayer/hooks/useHybridAudio.ts +0 -387
  46. package/src/tools/AudioPlayer/hooks/useHybridAudioAnalysis.ts +0 -95
  47. package/src/tools/AudioPlayer/hooks/useVisualization.tsx +0 -207
  48. package/src/tools/AudioPlayer/index.ts +0 -133
  49. package/src/tools/AudioPlayer/types/effects.ts +0 -73
  50. package/src/tools/AudioPlayer/types/index.ts +0 -27
  51. package/src/tools/AudioPlayer/utils/debug.ts +0 -14
  52. package/src/tools/AudioPlayer/utils/formatTime.ts +0 -10
  53. package/src/tools/AudioPlayer/utils/index.ts +0 -6
  54. package/src/tools/ImageViewer/@refactoring/00-PLAN.md +0 -71
  55. package/src/tools/ImageViewer/@refactoring/01-TYPES.md +0 -121
  56. package/src/tools/ImageViewer/@refactoring/02-UTILS.md +0 -143
  57. package/src/tools/ImageViewer/@refactoring/03-HOOKS.md +0 -261
  58. package/src/tools/ImageViewer/@refactoring/04-COMPONENTS.md +0 -427
  59. package/src/tools/ImageViewer/@refactoring/05-EXECUTION-CHECKLIST.md +0 -126
  60. package/src/tools/ImageViewer/README.md +0 -200
  61. package/src/tools/ImageViewer/components/ImageInfo.tsx +0 -44
  62. package/src/tools/ImageViewer/components/ImageToolbar.tsx +0 -150
  63. package/src/tools/ImageViewer/components/ImageViewer.tsx +0 -241
  64. package/src/tools/ImageViewer/components/index.ts +0 -7
  65. package/src/tools/ImageViewer/hooks/index.ts +0 -9
  66. package/src/tools/ImageViewer/hooks/useImageLoading.ts +0 -204
  67. package/src/tools/ImageViewer/hooks/useImageTransform.ts +0 -101
  68. package/src/tools/ImageViewer/index.ts +0 -60
  69. package/src/tools/ImageViewer/types.ts +0 -81
  70. package/src/tools/ImageViewer/utils/constants.ts +0 -59
  71. package/src/tools/ImageViewer/utils/debug.ts +0 -14
  72. package/src/tools/ImageViewer/utils/index.ts +0 -17
  73. package/src/tools/ImageViewer/utils/lqip.ts +0 -47
  74. package/src/tools/JsonForm/JsonSchemaForm.tsx +0 -197
  75. package/src/tools/JsonForm/examples/BotConfigExample.tsx +0 -249
  76. package/src/tools/JsonForm/examples/RealBotConfigExample.tsx +0 -161
  77. package/src/tools/JsonForm/index.ts +0 -46
  78. package/src/tools/JsonForm/templates/ArrayFieldItemTemplate.tsx +0 -47
  79. package/src/tools/JsonForm/templates/ArrayFieldTemplate.tsx +0 -74
  80. package/src/tools/JsonForm/templates/BaseInputTemplate.tsx +0 -107
  81. package/src/tools/JsonForm/templates/ErrorListTemplate.tsx +0 -35
  82. package/src/tools/JsonForm/templates/FieldTemplate.tsx +0 -62
  83. package/src/tools/JsonForm/templates/ObjectFieldTemplate.tsx +0 -116
  84. package/src/tools/JsonForm/templates/index.ts +0 -12
  85. package/src/tools/JsonForm/types.ts +0 -83
  86. package/src/tools/JsonForm/utils.ts +0 -213
  87. package/src/tools/JsonForm/widgets/CheckboxWidget.tsx +0 -37
  88. package/src/tools/JsonForm/widgets/ColorWidget.tsx +0 -219
  89. package/src/tools/JsonForm/widgets/NumberWidget.tsx +0 -89
  90. package/src/tools/JsonForm/widgets/SelectWidget.tsx +0 -97
  91. package/src/tools/JsonForm/widgets/SliderWidget.tsx +0 -148
  92. package/src/tools/JsonForm/widgets/SwitchWidget.tsx +0 -35
  93. package/src/tools/JsonForm/widgets/TextWidget.tsx +0 -96
  94. package/src/tools/JsonForm/widgets/index.ts +0 -14
  95. package/src/tools/JsonTree/index.tsx +0 -243
  96. package/src/tools/LottiePlayer/LottiePlayer.client.tsx +0 -213
  97. package/src/tools/LottiePlayer/index.tsx +0 -55
  98. package/src/tools/LottiePlayer/types.ts +0 -108
  99. package/src/tools/LottiePlayer/useLottie.ts +0 -164
  100. package/src/tools/Mermaid/Mermaid.client.tsx +0 -82
  101. package/src/tools/Mermaid/components/MermaidCodeViewer.tsx +0 -95
  102. package/src/tools/Mermaid/components/MermaidFullscreenModal.tsx +0 -103
  103. package/src/tools/Mermaid/hooks/index.ts +0 -4
  104. package/src/tools/Mermaid/hooks/useMermaidCleanup.ts +0 -73
  105. package/src/tools/Mermaid/hooks/useMermaidFullscreen.ts +0 -46
  106. package/src/tools/Mermaid/hooks/useMermaidRenderer.ts +0 -226
  107. package/src/tools/Mermaid/hooks/useMermaidValidation.ts +0 -29
  108. package/src/tools/Mermaid/index.tsx +0 -41
  109. package/src/tools/Mermaid/utils/mermaid-helpers.ts +0 -33
  110. package/src/tools/OpenapiViewer/components/EndpointInfo.tsx +0 -149
  111. package/src/tools/OpenapiViewer/components/EndpointsLibrary.tsx +0 -263
  112. package/src/tools/OpenapiViewer/components/PlaygroundLayout.tsx +0 -125
  113. package/src/tools/OpenapiViewer/components/PlaygroundStepper.tsx +0 -100
  114. package/src/tools/OpenapiViewer/components/RequestBuilder.tsx +0 -157
  115. package/src/tools/OpenapiViewer/components/RequestParametersForm.tsx +0 -253
  116. package/src/tools/OpenapiViewer/components/ResponseViewer.tsx +0 -173
  117. package/src/tools/OpenapiViewer/components/VersionSelector.tsx +0 -68
  118. package/src/tools/OpenapiViewer/components/index.ts +0 -14
  119. package/src/tools/OpenapiViewer/constants.ts +0 -39
  120. package/src/tools/OpenapiViewer/context/PlaygroundContext.tsx +0 -337
  121. package/src/tools/OpenapiViewer/hooks/index.ts +0 -8
  122. package/src/tools/OpenapiViewer/hooks/useMobile.ts +0 -10
  123. package/src/tools/OpenapiViewer/hooks/useOpenApiSchema.ts +0 -199
  124. package/src/tools/OpenapiViewer/index.tsx +0 -38
  125. package/src/tools/OpenapiViewer/types.ts +0 -151
  126. package/src/tools/OpenapiViewer/utils/apiKeyManager.ts +0 -149
  127. package/src/tools/OpenapiViewer/utils/formatters.ts +0 -71
  128. package/src/tools/OpenapiViewer/utils/index.ts +0 -9
  129. package/src/tools/OpenapiViewer/utils/versionManager.ts +0 -161
  130. package/src/tools/PrettyCode/PrettyCode.client.tsx +0 -208
  131. package/src/tools/PrettyCode/index.tsx +0 -45
  132. package/src/tools/VideoPlayer/@refactoring/00-PLAN.md +0 -91
  133. package/src/tools/VideoPlayer/@refactoring/01-TYPES.md +0 -284
  134. package/src/tools/VideoPlayer/@refactoring/02-UTILS.md +0 -141
  135. package/src/tools/VideoPlayer/@refactoring/03-HOOKS.md +0 -178
  136. package/src/tools/VideoPlayer/@refactoring/04-COMPONENTS.md +0 -95
  137. package/src/tools/VideoPlayer/@refactoring/05-EXECUTION-CHECKLIST.md +0 -139
  138. package/src/tools/VideoPlayer/README.md +0 -264
  139. package/src/tools/VideoPlayer/components/VideoControls.tsx +0 -138
  140. package/src/tools/VideoPlayer/components/VideoErrorFallback.tsx +0 -174
  141. package/src/tools/VideoPlayer/components/VideoPlayer.tsx +0 -201
  142. package/src/tools/VideoPlayer/components/index.ts +0 -14
  143. package/src/tools/VideoPlayer/context/VideoPlayerContext.tsx +0 -52
  144. package/src/tools/VideoPlayer/context/index.ts +0 -8
  145. package/src/tools/VideoPlayer/hooks/index.ts +0 -12
  146. package/src/tools/VideoPlayer/hooks/useVideoPlayerSettings.ts +0 -70
  147. package/src/tools/VideoPlayer/hooks/useVideoPositionCache.ts +0 -116
  148. package/src/tools/VideoPlayer/index.ts +0 -77
  149. package/src/tools/VideoPlayer/providers/NativeProvider.tsx +0 -284
  150. package/src/tools/VideoPlayer/providers/StreamProvider.tsx +0 -505
  151. package/src/tools/VideoPlayer/providers/VidstackProvider.tsx +0 -400
  152. package/src/tools/VideoPlayer/providers/index.ts +0 -8
  153. package/src/tools/VideoPlayer/types/index.ts +0 -38
  154. package/src/tools/VideoPlayer/types/player.ts +0 -116
  155. package/src/tools/VideoPlayer/types/provider.ts +0 -93
  156. package/src/tools/VideoPlayer/types/sources.ts +0 -97
  157. package/src/tools/VideoPlayer/utils/debug.ts +0 -14
  158. package/src/tools/VideoPlayer/utils/fileSource.ts +0 -78
  159. package/src/tools/VideoPlayer/utils/index.ts +0 -12
  160. package/src/tools/VideoPlayer/utils/resolvers.ts +0 -75
  161. package/src/tools/index.ts +0 -170
@@ -1,35 +0,0 @@
1
- /**
2
- * AudioPlayer hooks - Public API
3
- */
4
-
5
- // Core hybrid audio hook
6
- export { useHybridAudio } from './useHybridAudio';
7
- export type {
8
- UseHybridAudioOptions,
9
- HybridAudioState,
10
- HybridAudioControls,
11
- HybridWebAudioAPI,
12
- UseHybridAudioReturn,
13
- } from './useHybridAudio';
14
-
15
- // Frequency analysis hook
16
- export { useHybridAudioAnalysis } from './useHybridAudioAnalysis';
17
-
18
- // Visualization settings (localStorage persistence)
19
- export {
20
- useVisualization,
21
- useAudioVisualization,
22
- VisualizationProvider,
23
- VARIANT_INFO,
24
- INTENSITY_INFO,
25
- COLOR_SCHEME_INFO,
26
- } from './useVisualization';
27
- export type {
28
- VisualizationSettings,
29
- VisualizationVariant,
30
- VisualizationIntensity,
31
- VisualizationColorScheme,
32
- UseVisualizationReturn,
33
- UseAudioVisualizationReturn,
34
- VisualizationProviderProps,
35
- } from './useVisualization';
@@ -1,387 +0,0 @@
1
- 'use client';
2
-
3
- /**
4
- * useHybridAudio - Hybrid audio hook combining HTML5 audio + Web Audio API
5
- *
6
- * Uses native HTML5 <audio> for playback (no crackling, native streaming)
7
- * and Web Audio API only for visualization (AnalyserNode).
8
- *
9
- * Audio routing:
10
- * source -> destination (single path for playback)
11
- * source -> analyser (parallel path for visualization only, no output)
12
- */
13
-
14
- import { useRef, useState, useCallback, useEffect } from 'react';
15
-
16
- // =============================================================================
17
- // TYPES
18
- // =============================================================================
19
-
20
- export interface UseHybridAudioOptions {
21
- src: string;
22
- autoPlay?: boolean;
23
- initialVolume?: number;
24
- loop?: boolean;
25
- crossOrigin?: 'anonymous' | 'use-credentials';
26
- onPlay?: () => void;
27
- onPause?: () => void;
28
- onEnded?: () => void;
29
- onTimeUpdate?: (time: number) => void;
30
- onError?: (error: Error) => void;
31
- onReady?: () => void;
32
- }
33
-
34
- export interface HybridAudioState {
35
- isReady: boolean;
36
- isPlaying: boolean;
37
- currentTime: number;
38
- duration: number;
39
- volume: number;
40
- isMuted: boolean;
41
- isLooping: boolean;
42
- buffered: TimeRanges | null;
43
- error: Error | null;
44
- }
45
-
46
- export interface HybridAudioControls {
47
- play: () => Promise<void>;
48
- pause: () => void;
49
- togglePlay: () => void;
50
- seek: (time: number) => void;
51
- seekTo: (progress: number) => void;
52
- skip: (seconds: number) => void;
53
- setVolume: (vol: number) => void;
54
- toggleMute: () => void;
55
- toggleLoop: () => void;
56
- setLoop: (enabled: boolean) => void;
57
- restart: () => void;
58
- }
59
-
60
- export interface HybridWebAudioAPI {
61
- context: AudioContext | null;
62
- analyser: AnalyserNode | null;
63
- sourceNode: MediaElementAudioSourceNode | null;
64
- }
65
-
66
- export interface UseHybridAudioReturn {
67
- audioRef: React.RefObject<HTMLAudioElement | null>;
68
- state: HybridAudioState;
69
- controls: HybridAudioControls;
70
- webAudio: HybridWebAudioAPI;
71
- }
72
-
73
- // =============================================================================
74
- // HOOK
75
- // =============================================================================
76
-
77
- export function useHybridAudio(options: UseHybridAudioOptions): UseHybridAudioReturn {
78
- const {
79
- src,
80
- autoPlay = false,
81
- initialVolume = 1,
82
- loop = false,
83
- crossOrigin = 'anonymous',
84
- onPlay,
85
- onPause,
86
- onEnded,
87
- onTimeUpdate,
88
- onError,
89
- onReady,
90
- } = options;
91
-
92
- // Refs
93
- const audioRef = useRef<HTMLAudioElement | null>(null);
94
- const audioContextRef = useRef<AudioContext | null>(null);
95
- const sourceNodeRef = useRef<MediaElementAudioSourceNode | null>(null);
96
- const analyserRef = useRef<AnalyserNode | null>(null);
97
- const connectedElementRef = useRef<HTMLMediaElement | null>(null);
98
-
99
- // State
100
- const [state, setState] = useState<HybridAudioState>({
101
- isReady: false,
102
- isPlaying: false,
103
- currentTime: 0,
104
- duration: 0,
105
- volume: initialVolume,
106
- isMuted: false,
107
- isLooping: loop,
108
- buffered: null,
109
- error: null,
110
- });
111
-
112
- // Initialize Web Audio for visualization (lazy, on first play)
113
- const initWebAudio = useCallback(() => {
114
- const audio = audioRef.current;
115
- if (!audio) return;
116
-
117
- // Already connected to this element
118
- if (connectedElementRef.current === audio && audioContextRef.current) {
119
- return;
120
- }
121
-
122
- try {
123
- // Create AudioContext if needed
124
- if (!audioContextRef.current) {
125
- const AudioContextClass =
126
- window.AudioContext ||
127
- (window as unknown as { webkitAudioContext: typeof AudioContext }).webkitAudioContext;
128
- audioContextRef.current = new AudioContextClass();
129
- }
130
-
131
- const ctx = audioContextRef.current;
132
-
133
- // Disconnect old source if any
134
- if (sourceNodeRef.current) {
135
- try {
136
- sourceNodeRef.current.disconnect();
137
- } catch {
138
- /* ignore */
139
- }
140
- }
141
-
142
- // Create source from audio element
143
- const source = ctx.createMediaElementSource(audio);
144
- sourceNodeRef.current = source;
145
-
146
- // Create analyser for visualization
147
- const analyser = ctx.createAnalyser();
148
- analyser.fftSize = 256;
149
- analyser.smoothingTimeConstant = 0.85;
150
- analyserRef.current = analyser;
151
-
152
- // Audio routing:
153
- // 1. source -> destination (for playback)
154
- // 2. source -> analyser (for visualization only - NO output!)
155
- source.connect(ctx.destination);
156
- source.connect(analyser);
157
- // NOTE: analyser does NOT connect to destination - prevents double audio!
158
-
159
- connectedElementRef.current = audio;
160
- } catch (error) {
161
- console.warn('[useHybridAudio] Web Audio init failed:', error);
162
- }
163
- }, []);
164
-
165
- // Resume AudioContext on user interaction
166
- const resumeAudioContext = useCallback(async () => {
167
- const ctx = audioContextRef.current;
168
- if (ctx && ctx.state === 'suspended') {
169
- await ctx.resume();
170
- }
171
- }, []);
172
-
173
- // Controls
174
- const play = useCallback(async () => {
175
- const audio = audioRef.current;
176
- if (!audio) return;
177
-
178
- try {
179
- initWebAudio();
180
- await resumeAudioContext();
181
- await audio.play();
182
- } catch (error) {
183
- console.error('[useHybridAudio] Play failed:', error);
184
- onError?.(error as Error);
185
- }
186
- }, [initWebAudio, resumeAudioContext, onError]);
187
-
188
- const pause = useCallback(() => {
189
- audioRef.current?.pause();
190
- }, []);
191
-
192
- const togglePlay = useCallback(() => {
193
- if (state.isPlaying) {
194
- pause();
195
- } else {
196
- play();
197
- }
198
- }, [state.isPlaying, play, pause]);
199
-
200
- const seek = useCallback(
201
- (time: number) => {
202
- const audio = audioRef.current;
203
- if (audio && isFinite(time)) {
204
- audio.currentTime = Math.max(0, Math.min(time, state.duration || audio.duration || 0));
205
- }
206
- },
207
- [state.duration]
208
- );
209
-
210
- const seekTo = useCallback(
211
- (progress: number) => {
212
- const duration = state.duration || audioRef.current?.duration || 0;
213
- seek(duration * Math.max(0, Math.min(1, progress)));
214
- },
215
- [state.duration, seek]
216
- );
217
-
218
- const skip = useCallback(
219
- (seconds: number) => {
220
- seek(state.currentTime + seconds);
221
- },
222
- [state.currentTime, seek]
223
- );
224
-
225
- const setVolume = useCallback((vol: number) => {
226
- const audio = audioRef.current;
227
- if (audio) {
228
- const clampedVol = Math.max(0, Math.min(1, vol));
229
- audio.volume = clampedVol;
230
- setState((prev) => ({ ...prev, volume: clampedVol }));
231
- }
232
- }, []);
233
-
234
- const toggleMute = useCallback(() => {
235
- const audio = audioRef.current;
236
- if (audio) {
237
- audio.muted = !audio.muted;
238
- setState((prev) => ({ ...prev, isMuted: audio.muted }));
239
- }
240
- }, []);
241
-
242
- const toggleLoop = useCallback(() => {
243
- const audio = audioRef.current;
244
- if (audio) {
245
- audio.loop = !audio.loop;
246
- setState((prev) => ({ ...prev, isLooping: audio.loop }));
247
- }
248
- }, []);
249
-
250
- const setLoop = useCallback((enabled: boolean) => {
251
- const audio = audioRef.current;
252
- if (audio) {
253
- audio.loop = enabled;
254
- setState((prev) => ({ ...prev, isLooping: enabled }));
255
- }
256
- }, []);
257
-
258
- const restart = useCallback(() => {
259
- seek(0);
260
- play();
261
- }, [seek, play]);
262
-
263
- const controls: HybridAudioControls = {
264
- play,
265
- pause,
266
- togglePlay,
267
- seek,
268
- seekTo,
269
- skip,
270
- setVolume,
271
- toggleMute,
272
- toggleLoop,
273
- setLoop,
274
- restart,
275
- };
276
-
277
- // Create audio element on mount
278
- useEffect(() => {
279
- const audio = document.createElement('audio');
280
- audio.preload = 'metadata';
281
- audio.crossOrigin = crossOrigin;
282
- audio.volume = initialVolume;
283
- audio.loop = loop;
284
- audioRef.current = audio;
285
-
286
- return () => {
287
- audio.pause();
288
- audio.src = '';
289
- if (audioContextRef.current) {
290
- audioContextRef.current.close().catch(() => {});
291
- }
292
- };
293
- // eslint-disable-next-line react-hooks/exhaustive-deps
294
- }, []);
295
-
296
- // Event handlers
297
- useEffect(() => {
298
- const audio = audioRef.current;
299
- if (!audio) return;
300
-
301
- const handlers = {
302
- loadedmetadata: () => {
303
- setState((prev) => ({
304
- ...prev,
305
- duration: audio.duration,
306
- isReady: true,
307
- }));
308
- onReady?.();
309
- },
310
- canplay: () => {
311
- setState((prev) => ({ ...prev, isReady: true }));
312
- if (autoPlay) {
313
- play();
314
- }
315
- },
316
- play: () => {
317
- setState((prev) => ({ ...prev, isPlaying: true }));
318
- onPlay?.();
319
- },
320
- pause: () => {
321
- setState((prev) => ({ ...prev, isPlaying: false }));
322
- onPause?.();
323
- },
324
- ended: () => {
325
- setState((prev) => ({ ...prev, isPlaying: false }));
326
- onEnded?.();
327
- },
328
- timeupdate: () => {
329
- setState((prev) => ({ ...prev, currentTime: audio.currentTime }));
330
- onTimeUpdate?.(audio.currentTime);
331
- },
332
- progress: () => {
333
- setState((prev) => ({ ...prev, buffered: audio.buffered }));
334
- },
335
- error: () => {
336
- const error = new Error(audio.error?.message || 'Audio error');
337
- setState((prev) => ({ ...prev, error }));
338
- onError?.(error);
339
- },
340
- volumechange: () => {
341
- setState((prev) => ({
342
- ...prev,
343
- volume: audio.volume,
344
- isMuted: audio.muted,
345
- }));
346
- },
347
- };
348
-
349
- Object.entries(handlers).forEach(([event, handler]) => {
350
- audio.addEventListener(event, handler);
351
- });
352
-
353
- return () => {
354
- Object.entries(handlers).forEach(([event, handler]) => {
355
- audio.removeEventListener(event, handler);
356
- });
357
- };
358
- }, [autoPlay, onPlay, onPause, onEnded, onTimeUpdate, onError, onReady, play]);
359
-
360
- // Load new source
361
- useEffect(() => {
362
- const audio = audioRef.current;
363
- if (!audio || !src) return;
364
-
365
- setState((prev) => ({
366
- ...prev,
367
- isReady: false,
368
- currentTime: 0,
369
- duration: 0,
370
- error: null,
371
- }));
372
-
373
- audio.src = src;
374
- audio.load();
375
- }, [src]);
376
-
377
- return {
378
- audioRef,
379
- state,
380
- controls,
381
- webAudio: {
382
- context: audioContextRef.current,
383
- analyser: analyserRef.current,
384
- sourceNode: sourceNodeRef.current,
385
- },
386
- };
387
- }
@@ -1,95 +0,0 @@
1
- 'use client';
2
-
3
- /**
4
- * useHybridAudioAnalysis - Audio frequency analysis for hybrid player.
5
- *
6
- * Simplified version of useAudioAnalysis that works directly with AnalyserNode
7
- * instead of SharedWebAudioContext.
8
- */
9
-
10
- import { useState, useRef, useEffect, useCallback } from 'react';
11
- import type { AudioLevels } from '../effects';
12
-
13
- export function useHybridAudioAnalysis(
14
- analyser: AnalyserNode | null,
15
- isPlaying: boolean
16
- ): AudioLevels {
17
- const [levels, setLevels] = useState<AudioLevels>({ bass: 0, mid: 0, high: 0, overall: 0 });
18
- const animationRef = useRef<number | null>(null);
19
- const dataArrayRef = useRef<Uint8Array<ArrayBuffer> | null>(null);
20
-
21
- const cleanup = useCallback(() => {
22
- if (animationRef.current) {
23
- cancelAnimationFrame(animationRef.current);
24
- animationRef.current = null;
25
- }
26
- }, []);
27
-
28
- // Initialize data array when analyser is available
29
- useEffect(() => {
30
- if (analyser && !dataArrayRef.current) {
31
- dataArrayRef.current = new Uint8Array(analyser.frequencyBinCount) as Uint8Array<ArrayBuffer>;
32
- }
33
- }, [analyser]);
34
-
35
- // Animation loop
36
- useEffect(() => {
37
- if (!isPlaying || !analyser || !dataArrayRef.current) {
38
- cleanup();
39
- // Smooth fade out when stopped
40
- setLevels((prev) => ({
41
- bass: prev.bass * 0.95 < 0.01 ? 0 : prev.bass * 0.95,
42
- mid: prev.mid * 0.95 < 0.01 ? 0 : prev.mid * 0.95,
43
- high: prev.high * 0.95 < 0.01 ? 0 : prev.high * 0.95,
44
- overall: prev.overall * 0.95 < 0.01 ? 0 : prev.overall * 0.95,
45
- }));
46
- return;
47
- }
48
-
49
- const dataArray = dataArrayRef.current;
50
-
51
- const animate = () => {
52
- analyser.getByteFrequencyData(dataArray);
53
- const binCount = dataArray.length;
54
-
55
- // Bass (0-15% of frequency range)
56
- const bassEnd = Math.floor(binCount * 0.15);
57
- let bassSum = 0;
58
- for (let i = 0; i < bassEnd; i++) bassSum += dataArray[i];
59
- const bass = bassSum / bassEnd / 255;
60
-
61
- // Mids (15-50% of frequency range)
62
- const midStart = bassEnd;
63
- const midEnd = Math.floor(binCount * 0.5);
64
- let midSum = 0;
65
- for (let i = midStart; i < midEnd; i++) midSum += dataArray[i];
66
- const mid = midSum / (midEnd - midStart) / 255;
67
-
68
- // Highs (50-100% of frequency range)
69
- const highStart = midEnd;
70
- let highSum = 0;
71
- for (let i = highStart; i < binCount; i++) highSum += dataArray[i];
72
- const high = highSum / (binCount - highStart) / 255;
73
-
74
- // Overall
75
- let totalSum = 0;
76
- for (let i = 0; i < binCount; i++) totalSum += dataArray[i];
77
- const overall = totalSum / binCount / 255;
78
-
79
- // Smooth with lerp for natural feel
80
- setLevels((prev) => ({
81
- bass: prev.bass * 0.7 + bass * 0.3,
82
- mid: prev.mid * 0.7 + mid * 0.3,
83
- high: prev.high * 0.7 + high * 0.3,
84
- overall: prev.overall * 0.7 + overall * 0.3,
85
- }));
86
-
87
- animationRef.current = requestAnimationFrame(animate);
88
- };
89
-
90
- animationRef.current = requestAnimationFrame(animate);
91
- return cleanup;
92
- }, [analyser, isPlaying, cleanup]);
93
-
94
- return levels;
95
- }