@djangocfg/ui-nextjs 2.1.66 → 2.1.68

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 +474 -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
@@ -0,0 +1,427 @@
1
+ # Phase 6: Effects Refactoring
2
+
3
+ ## Source: `effects/index.ts` (413 lines)
4
+
5
+ Split into 3 files by concern.
6
+
7
+ ---
8
+
9
+ ## `effects/constants.ts`
10
+
11
+ Configuration constants (~60 lines).
12
+
13
+ ```typescript
14
+ import type { EffectIntensity, EffectColorScheme, EffectConfig } from '../types';
15
+
16
+ // =============================================================================
17
+ // INTENSITY CONFIGURATION
18
+ // =============================================================================
19
+
20
+ export const INTENSITY_CONFIG: Record<EffectIntensity, EffectConfig> = {
21
+ subtle: { opacity: 0.3, scale: 0.02, blur: 'blur-2xl' },
22
+ medium: { opacity: 0.5, scale: 0.04, blur: 'blur-xl' },
23
+ strong: { opacity: 0.7, scale: 0.06, blur: 'blur-lg' },
24
+ };
25
+
26
+ // =============================================================================
27
+ // COLOR SCHEMES
28
+ // =============================================================================
29
+
30
+ export const COLOR_SCHEMES: Record<EffectColorScheme, string[]> = {
31
+ primary: ['217 91% 60%'],
32
+ vibrant: ['217 91% 60%', '142 76% 36%', '262 83% 58%', '25 95% 53%'],
33
+ cool: ['217 91% 60%', '262 83% 58%', '199 89% 48%'],
34
+ warm: ['25 95% 53%', '0 84% 60%', '38 92% 50%'],
35
+ };
36
+
37
+ // Default multi-color palette
38
+ export const DEFAULT_GLOW_COLORS = [
39
+ '217 91% 60%', // Blue
40
+ '262 83% 58%', // Purple
41
+ '330 81% 60%', // Pink
42
+ '25 95% 53%', // Orange
43
+ ];
44
+
45
+ // =============================================================================
46
+ // HELPERS
47
+ // =============================================================================
48
+
49
+ export function getEffectConfig(intensity: EffectIntensity): EffectConfig {
50
+ return INTENSITY_CONFIG[intensity];
51
+ }
52
+
53
+ export function getColors(colorScheme: EffectColorScheme): string[] {
54
+ return COLOR_SCHEMES[colorScheme];
55
+ }
56
+ ```
57
+
58
+ ---
59
+
60
+ ## `effects/calculations.ts`
61
+
62
+ Effect calculation functions (~250 lines).
63
+
64
+ ```typescript
65
+ import type {
66
+ AudioLevels,
67
+ EffectConfig,
68
+ EffectColors,
69
+ EffectLayer,
70
+ Orb,
71
+ MeshGradient,
72
+ SpotlightData,
73
+ EffectColorScheme,
74
+ } from '../types';
75
+ import { COLOR_SCHEMES, DEFAULT_GLOW_COLORS } from './constants';
76
+
77
+ // =============================================================================
78
+ // PREPARE EFFECT COLORS
79
+ // =============================================================================
80
+
81
+ export function prepareEffectColors(
82
+ colorScheme: EffectColorScheme,
83
+ levels: AudioLevels
84
+ ): EffectColors {
85
+ const baseColors = COLOR_SCHEMES[colorScheme];
86
+ const colors = baseColors.length > 1 ? baseColors : DEFAULT_GLOW_COLORS;
87
+ const hueShift = Math.floor(
88
+ (levels.bass * 30) + (levels.mid * 20) + (levels.high * 10)
89
+ );
90
+
91
+ return { colors, hueShift };
92
+ }
93
+
94
+ // =============================================================================
95
+ // GLOW LAYERS
96
+ // =============================================================================
97
+
98
+ export function calculateGlowLayers(
99
+ levels: AudioLevels,
100
+ config: EffectConfig,
101
+ colors: string[]
102
+ ): EffectLayer[] {
103
+ const { bass, mid, high } = levels;
104
+
105
+ return [
106
+ // Layer 1: Bass glow - bottom
107
+ {
108
+ inset: 60 + bass * 90,
109
+ opacity: 1,
110
+ scale: 1 + bass * 0.5,
111
+ background: `radial-gradient(ellipse 80% 60% at 50% 100%, hsl(${colors[0]} / ${0.4 + bass * 0.4}) 0%, transparent 70%)`,
112
+ blur: 'blur-3xl',
113
+ },
114
+ // Layer 2: Mid glow - top
115
+ {
116
+ inset: 45 + mid * 75,
117
+ opacity: 1,
118
+ scale: 1 + mid * 0.4,
119
+ background: `radial-gradient(ellipse 70% 50% at 50% 0%, hsl(${colors[1] || colors[0]} / ${0.3 + mid * 0.5}) 0%, transparent 70%)`,
120
+ blur: 'blur-2xl',
121
+ },
122
+ // Layer 3: High glow - left
123
+ {
124
+ inset: 30 + high * 60,
125
+ opacity: 1,
126
+ scale: 1 + high * 0.3,
127
+ background: `radial-gradient(ellipse 50% 80% at 0% 50%, hsl(${colors[2] || colors[0]} / ${0.3 + high * 0.4}) 0%, transparent 60%)`,
128
+ blur: 'blur-2xl',
129
+ },
130
+ // Layer 4: High glow - right
131
+ {
132
+ inset: 30 + high * 60,
133
+ opacity: 1,
134
+ scale: 1 + high * 0.3,
135
+ background: `radial-gradient(ellipse 50% 80% at 100% 50%, hsl(${colors[3] || colors[0]} / ${0.3 + high * 0.4}) 0%, transparent 60%)`,
136
+ blur: 'blur-2xl',
137
+ },
138
+ // Layer 5: Center pulsing glow
139
+ {
140
+ inset: 24 + bass * 45,
141
+ opacity: 1,
142
+ scale: 1 + bass * 0.2,
143
+ background: `radial-gradient(circle at 50% 50%, hsl(${colors[0]} / ${0.2 + bass * 0.3}) 0%, hsl(${colors[1] || colors[0]} / ${0.1 + mid * 0.2}) 40%, transparent 70%)`,
144
+ blur: 'blur-xl',
145
+ animation: 'glow-breathe 2s ease-in-out infinite',
146
+ },
147
+ ];
148
+ }
149
+
150
+ // =============================================================================
151
+ // ORBS
152
+ // =============================================================================
153
+
154
+ export function calculateOrbs(
155
+ levels: AudioLevels,
156
+ config: EffectConfig,
157
+ colors: string[],
158
+ baseSize: number = 50
159
+ ): Orb[] {
160
+ const { bass, mid, high, overall } = levels;
161
+ const size = baseSize * 3;
162
+
163
+ const bassMove = bass * 30;
164
+ const midMove = mid * 25;
165
+ const highMove = high * 20;
166
+
167
+ return [
168
+ {
169
+ x: -40 + bassMove,
170
+ y: -40 - bassMove * 0.5,
171
+ size: size * (1 + bass * 1.2),
172
+ color: colors[0],
173
+ opacity: 0.5 + bass * 0.5,
174
+ scale: 1 + bass * 0.6,
175
+ },
176
+ {
177
+ x: 130 - midMove * 0.5,
178
+ y: -30 + midMove,
179
+ size: size * (0.9 + mid * 1.0),
180
+ color: colors[1] || colors[0],
181
+ opacity: 0.5 + mid * 0.5,
182
+ scale: 1 + mid * 0.5,
183
+ },
184
+ {
185
+ x: 140 + highMove * 0.3,
186
+ y: 120 - highMove,
187
+ size: size * (0.8 + high * 0.8),
188
+ color: colors[2] || colors[0],
189
+ opacity: 0.4 + high * 0.6,
190
+ scale: 1 + high * 0.45,
191
+ },
192
+ {
193
+ x: -30 - midMove * 0.4,
194
+ y: 130 + midMove * 0.3,
195
+ size: size * (0.9 + mid * 0.9),
196
+ color: colors[3] || colors[0],
197
+ opacity: 0.45 + mid * 0.55,
198
+ scale: 1 + mid * 0.5,
199
+ },
200
+ {
201
+ x: 50,
202
+ y: 50,
203
+ size: size * (0.6 + overall * 1.5),
204
+ color: colors[0],
205
+ opacity: 0.3 + overall * 0.5,
206
+ scale: 1 + overall * 0.7,
207
+ },
208
+ ];
209
+ }
210
+
211
+ // =============================================================================
212
+ // MESH GRADIENTS
213
+ // =============================================================================
214
+
215
+ export function calculateMeshGradients(
216
+ levels: AudioLevels,
217
+ config: EffectConfig,
218
+ colors: string[]
219
+ ): MeshGradient[] {
220
+ const { bass, mid, high, overall } = levels;
221
+
222
+ const bassOffset = bass * 40;
223
+ const midOffset = mid * 30;
224
+ const highOffset = high * 25;
225
+
226
+ return [
227
+ {
228
+ width: `${200 + bass * 150}%`,
229
+ height: `${200 + bass * 150}%`,
230
+ top: `${-80 + bassOffset}%`,
231
+ right: `${-80 - bassOffset}%`,
232
+ color: colors[0],
233
+ opacity: 0.4 + bass * 0.6,
234
+ scale: 1 + bass * 0.5,
235
+ rotation: bass * 45,
236
+ blur: 'blur-2xl',
237
+ },
238
+ {
239
+ width: `${180 + mid * 120}%`,
240
+ height: `${180 + mid * 120}%`,
241
+ bottom: `${-60 + midOffset}%`,
242
+ left: `${-60 - midOffset}%`,
243
+ color: colors[1] || colors[0],
244
+ opacity: 0.4 + mid * 0.6,
245
+ scale: 1 + mid * 0.4,
246
+ rotation: -mid * 40,
247
+ blur: 'blur-2xl',
248
+ },
249
+ {
250
+ width: `${140 + high * 100}%`,
251
+ height: `${140 + high * 100}%`,
252
+ top: `${70 - highOffset}%`,
253
+ right: `${-50 + highOffset}%`,
254
+ color: colors[2] || colors[0],
255
+ opacity: 0.35 + high * 0.65,
256
+ scale: 1 + high * 0.35,
257
+ rotation: high * 35,
258
+ blur: 'blur-xl',
259
+ },
260
+ {
261
+ width: `${160 + bass * 140}%`,
262
+ height: `${160 + bass * 140}%`,
263
+ top: `${-60 - bassOffset * 0.8}%`,
264
+ left: `${-60 + bassOffset * 0.8}%`,
265
+ color: colors[3] || colors[1] || colors[0],
266
+ opacity: 0.35 + bass * 0.65,
267
+ scale: 1 + bass * 0.55,
268
+ rotation: -bass * 50,
269
+ blur: 'blur-2xl',
270
+ },
271
+ {
272
+ width: `${80 + overall * 150}%`,
273
+ height: `${80 + overall * 150}%`,
274
+ top: '50%',
275
+ left: '50%',
276
+ color: colors[0],
277
+ opacity: 0.3 + overall * 0.5,
278
+ scale: 1 + overall * 0.4,
279
+ rotation: 0,
280
+ isCenter: true,
281
+ blur: 'blur-3xl',
282
+ },
283
+ ];
284
+ }
285
+
286
+ // =============================================================================
287
+ // SPOTLIGHT
288
+ // =============================================================================
289
+
290
+ export function calculateSpotlight(
291
+ levels: AudioLevels,
292
+ config: EffectConfig,
293
+ colors: string[],
294
+ rotation: number
295
+ ): SpotlightData {
296
+ const { bass, mid, high, overall } = levels;
297
+
298
+ return {
299
+ rotation: rotation + mid * 180,
300
+ inset: 12 + bass * 30,
301
+ colors: colors.map((c, i) => ({
302
+ color: c,
303
+ opacity: i === 0 ? 0.3 + bass * 0.7 : i === 1 ? 0.3 + mid * 0.7 : 0.3 + high * 0.7,
304
+ })),
305
+ pulseInset: 24 + bass * 50,
306
+ pulseOpacity: 0.3 + bass * 0.7,
307
+ pulseScale: 1 + bass * 0.4,
308
+ ringOpacity: 0.2 + overall * 0.6,
309
+ ringScale: 1 + overall * 0.3,
310
+ };
311
+ }
312
+ ```
313
+
314
+ ---
315
+
316
+ ## `effects/animations.ts`
317
+
318
+ CSS keyframes (~80 lines).
319
+
320
+ ```typescript
321
+ /**
322
+ * CSS keyframes for audio-reactive effects.
323
+ * Injected once via <style> tag.
324
+ */
325
+ export const EFFECT_ANIMATIONS = `
326
+ @keyframes spotlight-spin {
327
+ 0% { transform: rotate(0deg); }
328
+ 100% { transform: rotate(360deg); }
329
+ }
330
+
331
+ @keyframes orb-float-1 {
332
+ 0%, 100% { transform: translate(-50%, -50%) translateY(0); }
333
+ 50% { transform: translate(-50%, -50%) translateY(-15px); }
334
+ }
335
+
336
+ @keyframes orb-float-2 {
337
+ 0%, 100% { transform: translate(-50%, -50%) translateX(0); }
338
+ 50% { transform: translate(-50%, -50%) translateX(15px); }
339
+ }
340
+
341
+ @keyframes orb-float-3 {
342
+ 0%, 100% { transform: translate(-50%, -50%) translate(0, 0); }
343
+ 33% { transform: translate(-50%, -50%) translate(10px, -10px); }
344
+ 66% { transform: translate(-50%, -50%) translate(-10px, 10px); }
345
+ }
346
+
347
+ @keyframes orb-float-4 {
348
+ 0%, 100% { transform: translate(-50%, -50%) translate(0, 0); }
349
+ 50% { transform: translate(-50%, -50%) translate(-15px, -10px); }
350
+ }
351
+
352
+ @keyframes mesh-float-1 {
353
+ 0%, 100% { transform: translate(0, 0) scale(1); }
354
+ 25% { transform: translate(-5%, 10%) scale(1.05); }
355
+ 50% { transform: translate(5%, 5%) scale(0.95); }
356
+ 75% { transform: translate(-3%, -5%) scale(1.02); }
357
+ }
358
+
359
+ @keyframes mesh-float-2 {
360
+ 0%, 100% { transform: translate(0, 0) scale(1); }
361
+ 33% { transform: translate(8%, -8%) scale(1.08); }
362
+ 66% { transform: translate(-6%, 6%) scale(0.92); }
363
+ }
364
+
365
+ @keyframes mesh-float-3 {
366
+ 0%, 100% { transform: translate(0, 0) scale(1); }
367
+ 50% { transform: translate(10%, 10%) scale(1.1); }
368
+ }
369
+
370
+ @keyframes mesh-float-4 {
371
+ 0%, 100% { transform: translate(0, 0) scale(1) rotate(0deg); }
372
+ 25% { transform: translate(10%, -5%) scale(1.1) rotate(5deg); }
373
+ 50% { transform: translate(-5%, 10%) scale(0.95) rotate(-5deg); }
374
+ 75% { transform: translate(-10%, -10%) scale(1.05) rotate(3deg); }
375
+ }
376
+
377
+ @keyframes mesh-pulse {
378
+ 0%, 100% { transform: translate(-50%, -50%) scale(1); opacity: 0.3; }
379
+ 50% { transform: translate(-50%, -50%) scale(1.2); opacity: 0.5; }
380
+ }
381
+
382
+ @keyframes glow-breathe {
383
+ 0%, 100% { opacity: 0.6; transform: scale(1); }
384
+ 50% { opacity: 1; transform: scale(1.05); }
385
+ }
386
+
387
+ @keyframes glow-rotate {
388
+ 0% { transform: rotate(0deg); }
389
+ 100% { transform: rotate(360deg); }
390
+ }
391
+
392
+ @keyframes sparkle-move {
393
+ 0% { opacity: 0; transform: scale(0.8); }
394
+ 50% { opacity: 1; }
395
+ 100% { opacity: 0; transform: scale(1.2); }
396
+ }
397
+ `;
398
+ ```
399
+
400
+ ---
401
+
402
+ ## `effects/index.ts`
403
+
404
+ Re-export all.
405
+
406
+ ```typescript
407
+ // Constants
408
+ export {
409
+ INTENSITY_CONFIG,
410
+ COLOR_SCHEMES,
411
+ DEFAULT_GLOW_COLORS,
412
+ getEffectConfig,
413
+ getColors,
414
+ } from './constants';
415
+
416
+ // Calculations
417
+ export {
418
+ prepareEffectColors,
419
+ calculateGlowLayers,
420
+ calculateOrbs,
421
+ calculateMeshGradients,
422
+ calculateSpotlight,
423
+ } from './calculations';
424
+
425
+ // Animations
426
+ export { EFFECT_ANIMATIONS } from './animations';
427
+ ```
@@ -0,0 +1,193 @@
1
+ # Phase 7-8: Utils and Main Index
2
+
3
+ ## `utils/formatTime.ts`
4
+
5
+ Extract from `AudioPlayer.tsx`.
6
+
7
+ ```typescript
8
+ /**
9
+ * Format seconds to mm:ss display format.
10
+ */
11
+ export function formatTime(seconds: number): string {
12
+ if (!seconds || !isFinite(seconds) || seconds < 0) return '0:00';
13
+ const mins = Math.floor(seconds / 60);
14
+ const secs = Math.floor(seconds % 60);
15
+ return `${mins}:${secs.toString().padStart(2, '0')}`;
16
+ }
17
+ ```
18
+
19
+ ---
20
+
21
+ ## `utils/index.ts`
22
+
23
+ ```typescript
24
+ export { formatTime } from './formatTime';
25
+ ```
26
+
27
+ ---
28
+
29
+ ## Main `index.ts` (Final Public API)
30
+
31
+ ```typescript
32
+ /**
33
+ * AudioPlayer - Audio playback with waveform visualization
34
+ *
35
+ * Built on WaveSurfer.js with audio-reactive effects
36
+ */
37
+
38
+ // =============================================================================
39
+ // COMPONENTS
40
+ // =============================================================================
41
+
42
+ // Simple wrapper (recommended)
43
+ export { SimpleAudioPlayer } from './components';
44
+ export type { SimpleAudioPlayerProps } from './components';
45
+
46
+ // Core components
47
+ export { AudioPlayer } from './components';
48
+ export { AudioEqualizer } from './components';
49
+ export { AudioReactiveCover } from './components';
50
+ export { AudioShortcutsPopover } from './components';
51
+ export { VisualizationToggle } from './components';
52
+
53
+ // =============================================================================
54
+ // CONTEXT & HOOKS
55
+ // =============================================================================
56
+
57
+ // Provider and hooks
58
+ export {
59
+ AudioProvider,
60
+ useAudio,
61
+ useAudioControls,
62
+ useAudioState,
63
+ useAudioElement,
64
+ } from './context';
65
+
66
+ // Hotkeys
67
+ export { useAudioHotkeys, AUDIO_SHORTCUTS } from './hooks';
68
+
69
+ // Visualization settings
70
+ export {
71
+ useAudioVisualization,
72
+ VisualizationProvider,
73
+ VARIANT_INFO,
74
+ INTENSITY_INFO,
75
+ COLOR_SCHEME_INFO,
76
+ } from './hooks';
77
+
78
+ // =============================================================================
79
+ // EFFECTS
80
+ // =============================================================================
81
+
82
+ export {
83
+ INTENSITY_CONFIG,
84
+ COLOR_SCHEMES,
85
+ getEffectConfig,
86
+ getColors,
87
+ prepareEffectColors,
88
+ calculateGlowLayers,
89
+ calculateOrbs,
90
+ calculateMeshGradients,
91
+ calculateSpotlight,
92
+ EFFECT_ANIMATIONS,
93
+ } from './effects';
94
+
95
+ // =============================================================================
96
+ // TYPES
97
+ // =============================================================================
98
+
99
+ export type {
100
+ // Audio types
101
+ AudioSource,
102
+ PlaybackStatus,
103
+ WaveformOptions,
104
+ EqualizerOptions,
105
+ SharedWebAudioContext,
106
+ AudioContextState,
107
+ // Component props
108
+ AudioPlayerProps,
109
+ AudioEqualizerProps,
110
+ AudioReactiveCoverProps,
111
+ AudioViewerProps,
112
+ // Effect types
113
+ EffectVariant,
114
+ EffectIntensity,
115
+ EffectColorScheme,
116
+ AudioLevels,
117
+ EffectConfig,
118
+ EffectColors,
119
+ EffectLayer,
120
+ } from './types';
121
+
122
+ // Visualization types
123
+ export type {
124
+ VisualizationSettings,
125
+ VisualizationVariant,
126
+ VisualizationIntensity,
127
+ VisualizationColorScheme,
128
+ UseAudioVisualizationReturn,
129
+ VisualizationProviderProps,
130
+ } from './hooks';
131
+
132
+ // Hotkey types
133
+ export type {
134
+ AudioHotkeyOptions,
135
+ ShortcutItem,
136
+ ShortcutGroup,
137
+ } from './hooks';
138
+ ```
139
+
140
+ ---
141
+
142
+ ## Folder Structure Summary
143
+
144
+ After refactoring:
145
+
146
+ ```
147
+ AudioPlayer/
148
+ ├── index.ts # ~80 lines (exports only)
149
+
150
+ ├── types/
151
+ │ ├── index.ts # ~30 lines
152
+ │ ├── audio.ts # ~80 lines
153
+ │ ├── components.ts # ~50 lines
154
+ │ └── effects.ts # ~60 lines
155
+
156
+ ├── hooks/
157
+ │ ├── index.ts # ~30 lines
158
+ │ ├── useSharedWebAudio.ts # ~90 lines
159
+ │ ├── useAudioAnalysis.ts # ~100 lines
160
+ │ ├── useAudioHotkeys.ts # ~150 lines
161
+ │ └── useVisualization.tsx # ~200 lines
162
+
163
+ ├── context/
164
+ │ ├── index.ts # ~5 lines
165
+ │ ├── AudioProvider.tsx # ~180 lines
166
+ │ └── selectors.ts # ~60 lines
167
+
168
+ ├── components/
169
+ │ ├── index.ts # ~15 lines
170
+ │ ├── AudioPlayer.tsx # ~200 lines
171
+ │ ├── AudioEqualizer.tsx # ~200 lines
172
+ │ ├── SimpleAudioPlayer.tsx # ~280 lines
173
+ │ ├── ShortcutsPopover.tsx # ~95 lines
174
+ │ ├── VisualizationToggle.tsx # ~70 lines
175
+ │ └── ReactiveCover/
176
+ │ ├── index.tsx # ~100 lines
177
+ │ ├── GlowEffect.tsx # ~80 lines
178
+ │ ├── OrbsEffect.tsx # ~40 lines
179
+ │ ├── SpotlightEffect.tsx # ~60 lines
180
+ │ └── MeshEffect.tsx # ~50 lines
181
+
182
+ ├── effects/
183
+ │ ├── index.ts # ~20 lines
184
+ │ ├── constants.ts # ~50 lines
185
+ │ ├── calculations.ts # ~250 lines
186
+ │ └── animations.ts # ~80 lines
187
+
188
+ └── utils/
189
+ ├── index.ts # ~3 lines
190
+ └── formatTime.ts # ~10 lines
191
+
192
+ Total: ~23 files, avg ~85 lines per file (vs current 12 files, avg ~240 lines)
193
+ ```