@djangocfg/ui-tools 2.1.110 → 2.1.111

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 (159) hide show
  1. package/README.md +242 -49
  2. package/dist/JsonSchemaForm-65NLLK56.mjs +4 -0
  3. package/dist/JsonSchemaForm-65NLLK56.mjs.map +1 -0
  4. package/dist/JsonSchemaForm-PY6DH3HE.cjs +13 -0
  5. package/dist/JsonSchemaForm-PY6DH3HE.cjs.map +1 -0
  6. package/dist/JsonTree-6RYAOPSS.mjs +4 -0
  7. package/dist/JsonTree-6RYAOPSS.mjs.map +1 -0
  8. package/dist/JsonTree-7OH6CIHT.cjs +10 -0
  9. package/dist/JsonTree-7OH6CIHT.cjs.map +1 -0
  10. package/dist/MapContainer-GXQLP5WY.mjs +214 -0
  11. package/dist/MapContainer-GXQLP5WY.mjs.map +1 -0
  12. package/dist/MapContainer-RYG4HPH4.cjs +221 -0
  13. package/dist/MapContainer-RYG4HPH4.cjs.map +1 -0
  14. package/dist/{Mermaid.client-4OCKJ6QD.mjs → Mermaid.client-OKACITCW.mjs} +16 -7
  15. package/dist/Mermaid.client-OKACITCW.mjs.map +1 -0
  16. package/dist/{Mermaid.client-ZP6OE46Z.cjs → Mermaid.client-PNXEC6YL.cjs} +16 -7
  17. package/dist/Mermaid.client-PNXEC6YL.cjs.map +1 -0
  18. package/dist/{PlaygroundLayout-XXVBU4WZ.cjs → PlaygroundLayout-SYMEAG3J.cjs} +25 -24
  19. package/dist/PlaygroundLayout-SYMEAG3J.cjs.map +1 -0
  20. package/dist/{PlaygroundLayout-LMQTVXSP.mjs → PlaygroundLayout-UQRBU5RH.mjs} +4 -3
  21. package/dist/PlaygroundLayout-UQRBU5RH.mjs.map +1 -0
  22. package/dist/{PrettyCode.client-2CLSV2VD.cjs → PrettyCode.client-DANYYQYO.cjs} +11 -4
  23. package/dist/PrettyCode.client-DANYYQYO.cjs.map +1 -0
  24. package/dist/{PrettyCode.client-Y2BVON7R.mjs → PrettyCode.client-RS5ZTNBT.mjs} +11 -4
  25. package/dist/PrettyCode.client-RS5ZTNBT.mjs.map +1 -0
  26. package/dist/chunk-2DSR7V2L.mjs +561 -0
  27. package/dist/chunk-2DSR7V2L.mjs.map +1 -0
  28. package/dist/chunk-47T5ECYV.cjs +1357 -0
  29. package/dist/chunk-47T5ECYV.cjs.map +1 -0
  30. package/dist/chunk-5QT3QYFZ.cjs +189 -0
  31. package/dist/chunk-5QT3QYFZ.cjs.map +1 -0
  32. package/dist/chunk-7IIRYG4S.mjs +1057 -0
  33. package/dist/chunk-7IIRYG4S.mjs.map +1 -0
  34. package/dist/{chunk-FB5QBSI3.cjs → chunk-DI3HUXHK.cjs} +15 -195
  35. package/dist/chunk-DI3HUXHK.cjs.map +1 -0
  36. package/dist/chunk-EVGWYASL.cjs +1528 -0
  37. package/dist/chunk-EVGWYASL.cjs.map +1 -0
  38. package/dist/chunk-F2N7P5XU.cjs +30 -0
  39. package/dist/chunk-F2N7P5XU.cjs.map +1 -0
  40. package/dist/{chunk-L6UHASYQ.mjs → chunk-G6PRZP5I.mjs} +7 -186
  41. package/dist/chunk-G6PRZP5I.mjs.map +1 -0
  42. package/dist/chunk-JWB2EWQO.mjs +5 -0
  43. package/dist/chunk-JWB2EWQO.mjs.map +1 -0
  44. package/dist/chunk-LTJX2JXE.mjs +338 -0
  45. package/dist/chunk-LTJX2JXE.mjs.map +1 -0
  46. package/dist/chunk-OVNC4KW6.mjs +1494 -0
  47. package/dist/chunk-OVNC4KW6.mjs.map +1 -0
  48. package/dist/chunk-PNZSJN6T.cjs +1086 -0
  49. package/dist/chunk-PNZSJN6T.cjs.map +1 -0
  50. package/dist/chunk-TEFRA7GW.cjs +565 -0
  51. package/dist/chunk-TEFRA7GW.cjs.map +1 -0
  52. package/dist/chunk-UOMPPIED.mjs +1343 -0
  53. package/dist/chunk-UOMPPIED.mjs.map +1 -0
  54. package/dist/chunk-W6YHQI4F.mjs +187 -0
  55. package/dist/chunk-W6YHQI4F.mjs.map +1 -0
  56. package/dist/chunk-XTBRWVIV.cjs +346 -0
  57. package/dist/chunk-XTBRWVIV.cjs.map +1 -0
  58. package/dist/components-C7ZL7OMY.mjs +5 -0
  59. package/dist/components-C7ZL7OMY.mjs.map +1 -0
  60. package/dist/components-CJ2IB65O.cjs +27 -0
  61. package/dist/components-CJ2IB65O.cjs.map +1 -0
  62. package/dist/components-EASJYK45.mjs +6 -0
  63. package/dist/components-EASJYK45.mjs.map +1 -0
  64. package/dist/components-LDRFDV4A.cjs +22 -0
  65. package/dist/components-LDRFDV4A.cjs.map +1 -0
  66. package/dist/components-VZKUTDJK.mjs +5 -0
  67. package/dist/components-VZKUTDJK.mjs.map +1 -0
  68. package/dist/components-Y64GTIMQ.cjs +42 -0
  69. package/dist/components-Y64GTIMQ.cjs.map +1 -0
  70. package/dist/index.cjs +701 -4813
  71. package/dist/index.cjs.map +1 -1
  72. package/dist/index.d.cts +1274 -1026
  73. package/dist/index.d.ts +1274 -1026
  74. package/dist/index.mjs +358 -4730
  75. package/dist/index.mjs.map +1 -1
  76. package/package.json +27 -4
  77. package/src/components/index.ts +17 -0
  78. package/src/components/lazy-wrapper.tsx +281 -0
  79. package/src/index.ts +92 -7
  80. package/src/tools/AudioPlayer/components/HybridAudioPlayer.tsx +14 -5
  81. package/src/tools/AudioPlayer/lazy.tsx +85 -0
  82. package/src/tools/Gallery/components/Gallery.tsx +182 -0
  83. package/src/tools/Gallery/components/GalleryCarousel.tsx +251 -0
  84. package/src/tools/Gallery/components/GalleryCompact.tsx +173 -0
  85. package/src/tools/Gallery/components/GalleryGrid.tsx +493 -0
  86. package/src/tools/Gallery/components/GalleryImage.tsx +66 -0
  87. package/src/tools/Gallery/components/GalleryLightbox.tsx +331 -0
  88. package/src/tools/Gallery/components/GalleryMedia.tsx +66 -0
  89. package/src/tools/Gallery/components/GalleryThumbnails.tsx +173 -0
  90. package/src/tools/Gallery/components/GalleryThumbnailsVirtual.tsx +138 -0
  91. package/src/tools/Gallery/components/GalleryVideo.tsx +222 -0
  92. package/src/tools/Gallery/components/index.ts +13 -0
  93. package/src/tools/Gallery/hooks/index.ts +23 -0
  94. package/src/tools/Gallery/hooks/useGallery.ts +137 -0
  95. package/src/tools/Gallery/hooks/useImageDimensions.ts +223 -0
  96. package/src/tools/Gallery/hooks/usePinchZoom.ts +234 -0
  97. package/src/tools/Gallery/hooks/usePreloadImages.ts +71 -0
  98. package/src/tools/Gallery/hooks/useSwipe.ts +86 -0
  99. package/src/tools/Gallery/hooks/useVirtualList.ts +129 -0
  100. package/src/tools/Gallery/hooks/useZoom.ts +316 -0
  101. package/src/tools/Gallery/index.ts +66 -0
  102. package/src/tools/Gallery/types.ts +183 -0
  103. package/src/tools/Gallery/utils/imageAnalysis.ts +52 -0
  104. package/src/tools/Gallery/utils/index.ts +11 -0
  105. package/src/tools/ImageViewer/components/ImageToolbar.tsx +20 -8
  106. package/src/tools/ImageViewer/components/ImageViewer.tsx +12 -4
  107. package/src/tools/ImageViewer/lazy.tsx +37 -0
  108. package/src/tools/JsonForm/lazy.tsx +43 -0
  109. package/src/tools/JsonForm/widgets/ColorWidget.tsx +4 -1
  110. package/src/tools/JsonTree/lazy.tsx +45 -0
  111. package/src/tools/LottiePlayer/lazy.tsx +57 -0
  112. package/src/tools/Map/components/CustomOverlay.tsx +54 -0
  113. package/src/tools/Map/components/DrawControl.tsx +36 -0
  114. package/src/tools/Map/components/GeocoderControl.tsx +70 -0
  115. package/src/tools/Map/components/LayerSwitcher.tsx +225 -0
  116. package/src/tools/Map/components/MapCluster.tsx +273 -0
  117. package/src/tools/Map/components/MapContainer.tsx +191 -0
  118. package/src/tools/Map/components/MapControls.tsx +44 -0
  119. package/src/tools/Map/components/MapLegend.tsx +161 -0
  120. package/src/tools/Map/components/MapMarker.tsx +102 -0
  121. package/src/tools/Map/components/MapPopup.tsx +46 -0
  122. package/src/tools/Map/components/MapSource.tsx +30 -0
  123. package/src/tools/Map/components/index.ts +20 -0
  124. package/src/tools/Map/context/MapContext.tsx +89 -0
  125. package/src/tools/Map/context/index.ts +2 -0
  126. package/src/tools/Map/hooks/index.ts +9 -0
  127. package/src/tools/Map/hooks/useMap.ts +11 -0
  128. package/src/tools/Map/hooks/useMapControl.ts +99 -0
  129. package/src/tools/Map/hooks/useMapEvents.ts +147 -0
  130. package/src/tools/Map/hooks/useMapLayers.ts +83 -0
  131. package/src/tools/Map/hooks/useMapViewport.ts +62 -0
  132. package/src/tools/Map/hooks/useMarkers.ts +85 -0
  133. package/src/tools/Map/index.ts +116 -0
  134. package/src/tools/Map/layers/cluster.ts +94 -0
  135. package/src/tools/Map/layers/index.ts +15 -0
  136. package/src/tools/Map/layers/line.ts +93 -0
  137. package/src/tools/Map/layers/point.ts +61 -0
  138. package/src/tools/Map/layers/polygon.ts +73 -0
  139. package/src/tools/Map/lazy.tsx +56 -0
  140. package/src/tools/Map/styles/index.ts +15 -0
  141. package/src/tools/Map/types.ts +259 -0
  142. package/src/tools/Map/utils/geo.ts +88 -0
  143. package/src/tools/Map/utils/index.ts +16 -0
  144. package/src/tools/Map/utils/transform.ts +107 -0
  145. package/src/tools/Mermaid/Mermaid.client.tsx +12 -4
  146. package/src/tools/Mermaid/components/MermaidFullscreenModal.tsx +6 -2
  147. package/src/tools/Mermaid/lazy.tsx +46 -0
  148. package/src/tools/OpenapiViewer/lazy.tsx +72 -0
  149. package/src/tools/PrettyCode/PrettyCode.client.tsx +10 -3
  150. package/src/tools/PrettyCode/lazy.tsx +64 -0
  151. package/src/tools/VideoPlayer/lazy.tsx +63 -0
  152. package/dist/Mermaid.client-4OCKJ6QD.mjs.map +0 -1
  153. package/dist/Mermaid.client-ZP6OE46Z.cjs.map +0 -1
  154. package/dist/PlaygroundLayout-LMQTVXSP.mjs.map +0 -1
  155. package/dist/PlaygroundLayout-XXVBU4WZ.cjs.map +0 -1
  156. package/dist/PrettyCode.client-2CLSV2VD.cjs.map +0 -1
  157. package/dist/PrettyCode.client-Y2BVON7R.mjs.map +0 -1
  158. package/dist/chunk-FB5QBSI3.cjs.map +0 -1
  159. package/dist/chunk-L6UHASYQ.mjs.map +0 -1
@@ -0,0 +1,1528 @@
1
+ 'use strict';
2
+
3
+ var chunkF2N7P5XU_cjs = require('./chunk-F2N7P5XU.cjs');
4
+ var chunkWGEGR3DF_cjs = require('./chunk-WGEGR3DF.cjs');
5
+ var react = require('react');
6
+ var lucideReact = require('lucide-react');
7
+ var i18n = require('@djangocfg/i18n');
8
+ var jsxRuntime = require('react/jsx-runtime');
9
+ var lib = require('@djangocfg/ui-core/lib');
10
+ var uiCore = require('@djangocfg/ui-core');
11
+
12
+ function useHybridAudio(options) {
13
+ const {
14
+ src,
15
+ autoPlay = false,
16
+ initialVolume = 1,
17
+ loop = false,
18
+ crossOrigin = "anonymous",
19
+ onPlay,
20
+ onPause,
21
+ onEnded,
22
+ onTimeUpdate,
23
+ onError,
24
+ onReady
25
+ } = options;
26
+ const audioRef = react.useRef(null);
27
+ const audioContextRef = react.useRef(null);
28
+ const sourceNodeRef = react.useRef(null);
29
+ const analyserRef = react.useRef(null);
30
+ const connectedElementRef = react.useRef(null);
31
+ const [state, setState] = react.useState({
32
+ isReady: false,
33
+ isPlaying: false,
34
+ currentTime: 0,
35
+ duration: 0,
36
+ volume: initialVolume,
37
+ isMuted: false,
38
+ isLooping: loop,
39
+ buffered: null,
40
+ error: null
41
+ });
42
+ const initWebAudio = react.useCallback(() => {
43
+ const audio = audioRef.current;
44
+ if (!audio) return;
45
+ if (connectedElementRef.current === audio && audioContextRef.current) {
46
+ return;
47
+ }
48
+ try {
49
+ if (!audioContextRef.current) {
50
+ const AudioContextClass = window.AudioContext || window.webkitAudioContext;
51
+ audioContextRef.current = new AudioContextClass();
52
+ }
53
+ const ctx = audioContextRef.current;
54
+ if (sourceNodeRef.current) {
55
+ try {
56
+ sourceNodeRef.current.disconnect();
57
+ } catch {
58
+ }
59
+ }
60
+ const source = ctx.createMediaElementSource(audio);
61
+ sourceNodeRef.current = source;
62
+ const analyser = ctx.createAnalyser();
63
+ analyser.fftSize = 256;
64
+ analyser.smoothingTimeConstant = 0.85;
65
+ analyserRef.current = analyser;
66
+ source.connect(ctx.destination);
67
+ source.connect(analyser);
68
+ connectedElementRef.current = audio;
69
+ } catch (error) {
70
+ console.warn("[useHybridAudio] Web Audio init failed:", error);
71
+ }
72
+ }, []);
73
+ const resumeAudioContext = react.useCallback(async () => {
74
+ const ctx = audioContextRef.current;
75
+ if (ctx && ctx.state === "suspended") {
76
+ await ctx.resume();
77
+ }
78
+ }, []);
79
+ const play = react.useCallback(async () => {
80
+ const audio = audioRef.current;
81
+ if (!audio) return;
82
+ try {
83
+ initWebAudio();
84
+ await resumeAudioContext();
85
+ await audio.play();
86
+ } catch (error) {
87
+ console.error("[useHybridAudio] Play failed:", error);
88
+ onError?.(error);
89
+ }
90
+ }, [initWebAudio, resumeAudioContext, onError]);
91
+ const pause = react.useCallback(() => {
92
+ audioRef.current?.pause();
93
+ }, []);
94
+ const togglePlay = react.useCallback(() => {
95
+ if (state.isPlaying) {
96
+ pause();
97
+ } else {
98
+ play();
99
+ }
100
+ }, [state.isPlaying, play, pause]);
101
+ const seek = react.useCallback(
102
+ (time) => {
103
+ const audio = audioRef.current;
104
+ if (audio && isFinite(time)) {
105
+ audio.currentTime = Math.max(0, Math.min(time, state.duration || audio.duration || 0));
106
+ }
107
+ },
108
+ [state.duration]
109
+ );
110
+ const seekTo = react.useCallback(
111
+ (progress) => {
112
+ const duration = state.duration || audioRef.current?.duration || 0;
113
+ seek(duration * Math.max(0, Math.min(1, progress)));
114
+ },
115
+ [state.duration, seek]
116
+ );
117
+ const skip = react.useCallback(
118
+ (seconds) => {
119
+ seek(state.currentTime + seconds);
120
+ },
121
+ [state.currentTime, seek]
122
+ );
123
+ const setVolume = react.useCallback((vol) => {
124
+ const audio = audioRef.current;
125
+ if (audio) {
126
+ const clampedVol = Math.max(0, Math.min(1, vol));
127
+ audio.volume = clampedVol;
128
+ setState((prev) => ({ ...prev, volume: clampedVol }));
129
+ }
130
+ }, []);
131
+ const toggleMute = react.useCallback(() => {
132
+ const audio = audioRef.current;
133
+ if (audio) {
134
+ audio.muted = !audio.muted;
135
+ setState((prev) => ({ ...prev, isMuted: audio.muted }));
136
+ }
137
+ }, []);
138
+ const toggleLoop = react.useCallback(() => {
139
+ const audio = audioRef.current;
140
+ if (audio) {
141
+ audio.loop = !audio.loop;
142
+ setState((prev) => ({ ...prev, isLooping: audio.loop }));
143
+ }
144
+ }, []);
145
+ const setLoop = react.useCallback((enabled) => {
146
+ const audio = audioRef.current;
147
+ if (audio) {
148
+ audio.loop = enabled;
149
+ setState((prev) => ({ ...prev, isLooping: enabled }));
150
+ }
151
+ }, []);
152
+ const restart = react.useCallback(() => {
153
+ seek(0);
154
+ play();
155
+ }, [seek, play]);
156
+ const controls = {
157
+ play,
158
+ pause,
159
+ togglePlay,
160
+ seek,
161
+ seekTo,
162
+ skip,
163
+ setVolume,
164
+ toggleMute,
165
+ toggleLoop,
166
+ setLoop,
167
+ restart
168
+ };
169
+ react.useEffect(() => {
170
+ const audio = document.createElement("audio");
171
+ audio.preload = "metadata";
172
+ audio.crossOrigin = crossOrigin;
173
+ audio.volume = initialVolume;
174
+ audio.loop = loop;
175
+ audioRef.current = audio;
176
+ return () => {
177
+ audio.pause();
178
+ audio.src = "";
179
+ if (audioContextRef.current) {
180
+ audioContextRef.current.close().catch(() => {
181
+ });
182
+ }
183
+ };
184
+ }, []);
185
+ react.useEffect(() => {
186
+ const audio = audioRef.current;
187
+ if (!audio) return;
188
+ const handlers = {
189
+ loadedmetadata: /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(() => {
190
+ setState((prev) => ({
191
+ ...prev,
192
+ duration: audio.duration,
193
+ isReady: true
194
+ }));
195
+ onReady?.();
196
+ }, "loadedmetadata"),
197
+ canplay: /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(() => {
198
+ setState((prev) => ({ ...prev, isReady: true }));
199
+ if (autoPlay) {
200
+ play();
201
+ }
202
+ }, "canplay"),
203
+ play: /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(() => {
204
+ setState((prev) => ({ ...prev, isPlaying: true }));
205
+ onPlay?.();
206
+ }, "play"),
207
+ pause: /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(() => {
208
+ setState((prev) => ({ ...prev, isPlaying: false }));
209
+ onPause?.();
210
+ }, "pause"),
211
+ ended: /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(() => {
212
+ setState((prev) => ({ ...prev, isPlaying: false }));
213
+ onEnded?.();
214
+ }, "ended"),
215
+ timeupdate: /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(() => {
216
+ setState((prev) => ({ ...prev, currentTime: audio.currentTime }));
217
+ onTimeUpdate?.(audio.currentTime);
218
+ }, "timeupdate"),
219
+ progress: /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(() => {
220
+ setState((prev) => ({ ...prev, buffered: audio.buffered }));
221
+ }, "progress"),
222
+ error: /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(() => {
223
+ const error = new Error(audio.error?.message || "Audio error");
224
+ setState((prev) => ({ ...prev, error }));
225
+ onError?.(error);
226
+ }, "error"),
227
+ volumechange: /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(() => {
228
+ setState((prev) => ({
229
+ ...prev,
230
+ volume: audio.volume,
231
+ isMuted: audio.muted
232
+ }));
233
+ }, "volumechange")
234
+ };
235
+ Object.entries(handlers).forEach(([event, handler]) => {
236
+ audio.addEventListener(event, handler);
237
+ });
238
+ return () => {
239
+ Object.entries(handlers).forEach(([event, handler]) => {
240
+ audio.removeEventListener(event, handler);
241
+ });
242
+ };
243
+ }, [autoPlay, onPlay, onPause, onEnded, onTimeUpdate, onError, onReady, play]);
244
+ react.useEffect(() => {
245
+ const audio = audioRef.current;
246
+ if (!audio || !src) return;
247
+ setState((prev) => ({
248
+ ...prev,
249
+ isReady: false,
250
+ currentTime: 0,
251
+ duration: 0,
252
+ error: null
253
+ }));
254
+ audio.src = src;
255
+ audio.load();
256
+ }, [src]);
257
+ return {
258
+ audioRef,
259
+ state,
260
+ controls,
261
+ webAudio: {
262
+ context: audioContextRef.current,
263
+ analyser: analyserRef.current,
264
+ sourceNode: sourceNodeRef.current
265
+ }
266
+ };
267
+ }
268
+ chunkWGEGR3DF_cjs.__name(useHybridAudio, "useHybridAudio");
269
+ function useHybridAudioAnalysis(analyser, isPlaying) {
270
+ const [levels, setLevels] = react.useState({ bass: 0, mid: 0, high: 0, overall: 0 });
271
+ const animationRef = react.useRef(null);
272
+ const dataArrayRef = react.useRef(null);
273
+ const cleanup = react.useCallback(() => {
274
+ if (animationRef.current) {
275
+ cancelAnimationFrame(animationRef.current);
276
+ animationRef.current = null;
277
+ }
278
+ }, []);
279
+ react.useEffect(() => {
280
+ if (analyser && !dataArrayRef.current) {
281
+ dataArrayRef.current = new Uint8Array(analyser.frequencyBinCount);
282
+ }
283
+ }, [analyser]);
284
+ react.useEffect(() => {
285
+ if (!isPlaying || !analyser || !dataArrayRef.current) {
286
+ cleanup();
287
+ setLevels((prev) => ({
288
+ bass: prev.bass * 0.95 < 0.01 ? 0 : prev.bass * 0.95,
289
+ mid: prev.mid * 0.95 < 0.01 ? 0 : prev.mid * 0.95,
290
+ high: prev.high * 0.95 < 0.01 ? 0 : prev.high * 0.95,
291
+ overall: prev.overall * 0.95 < 0.01 ? 0 : prev.overall * 0.95
292
+ }));
293
+ return;
294
+ }
295
+ const dataArray = dataArrayRef.current;
296
+ const animate = /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(() => {
297
+ analyser.getByteFrequencyData(dataArray);
298
+ const binCount = dataArray.length;
299
+ const bassEnd = Math.floor(binCount * 0.15);
300
+ let bassSum = 0;
301
+ for (let i = 0; i < bassEnd; i++) bassSum += dataArray[i];
302
+ const bass = bassSum / bassEnd / 255;
303
+ const midStart = bassEnd;
304
+ const midEnd = Math.floor(binCount * 0.5);
305
+ let midSum = 0;
306
+ for (let i = midStart; i < midEnd; i++) midSum += dataArray[i];
307
+ const mid = midSum / (midEnd - midStart) / 255;
308
+ const highStart = midEnd;
309
+ let highSum = 0;
310
+ for (let i = highStart; i < binCount; i++) highSum += dataArray[i];
311
+ const high = highSum / (binCount - highStart) / 255;
312
+ let totalSum = 0;
313
+ for (let i = 0; i < binCount; i++) totalSum += dataArray[i];
314
+ const overall = totalSum / binCount / 255;
315
+ setLevels((prev) => ({
316
+ bass: prev.bass * 0.7 + bass * 0.3,
317
+ mid: prev.mid * 0.7 + mid * 0.3,
318
+ high: prev.high * 0.7 + high * 0.3,
319
+ overall: prev.overall * 0.7 + overall * 0.3
320
+ }));
321
+ animationRef.current = requestAnimationFrame(animate);
322
+ }, "animate");
323
+ animationRef.current = requestAnimationFrame(animate);
324
+ return cleanup;
325
+ }, [analyser, isPlaying, cleanup]);
326
+ return levels;
327
+ }
328
+ chunkWGEGR3DF_cjs.__name(useHybridAudioAnalysis, "useHybridAudioAnalysis");
329
+ var STORAGE_KEY = "audio-player-settings";
330
+ var DEFAULT_SETTINGS = {
331
+ enabled: true,
332
+ variant: "spotlight",
333
+ intensity: "medium",
334
+ colorScheme: "primary",
335
+ volume: 1,
336
+ isLooping: false
337
+ };
338
+ var VARIANTS = ["spotlight", "glow", "orbs", "mesh", "none"];
339
+ var INTENSITIES = ["subtle", "medium", "strong"];
340
+ var COLOR_SCHEMES = ["primary", "vibrant", "cool", "warm"];
341
+ var VisualizationContext = react.createContext(null);
342
+ function VisualizationProvider({ children }) {
343
+ const value = useVisualizationState();
344
+ return /* @__PURE__ */ jsxRuntime.jsx(VisualizationContext.Provider, { value, children });
345
+ }
346
+ chunkWGEGR3DF_cjs.__name(VisualizationProvider, "VisualizationProvider");
347
+ function useVisualizationState() {
348
+ const [settings, setSettings] = chunkF2N7P5XU_cjs.useLocalStorage(
349
+ STORAGE_KEY,
350
+ DEFAULT_SETTINGS
351
+ );
352
+ const toggle = react.useCallback(() => {
353
+ setSettings((prev) => ({ ...prev, enabled: !prev.enabled }));
354
+ }, [setSettings]);
355
+ const setSetting = react.useCallback(
356
+ (key, value) => {
357
+ setSettings((prev) => ({ ...prev, [key]: value }));
358
+ },
359
+ [setSettings]
360
+ );
361
+ const nextVariant = react.useCallback(() => {
362
+ setSettings((prev) => {
363
+ const currentIndex = VARIANTS.indexOf(prev.variant);
364
+ const nextIndex = (currentIndex + 1) % VARIANTS.length;
365
+ return { ...prev, variant: VARIANTS[nextIndex] };
366
+ });
367
+ }, [setSettings]);
368
+ const nextIntensity = react.useCallback(() => {
369
+ setSettings((prev) => {
370
+ const currentIndex = INTENSITIES.indexOf(prev.intensity);
371
+ const nextIndex = (currentIndex + 1) % INTENSITIES.length;
372
+ return { ...prev, intensity: INTENSITIES[nextIndex] };
373
+ });
374
+ }, [setSettings]);
375
+ const nextColorScheme = react.useCallback(() => {
376
+ setSettings((prev) => {
377
+ const currentIndex = COLOR_SCHEMES.indexOf(prev.colorScheme);
378
+ const nextIndex = (currentIndex + 1) % COLOR_SCHEMES.length;
379
+ return { ...prev, colorScheme: COLOR_SCHEMES[nextIndex] };
380
+ });
381
+ }, [setSettings]);
382
+ const reset = react.useCallback(() => {
383
+ setSettings(DEFAULT_SETTINGS);
384
+ }, [setSettings]);
385
+ return react.useMemo(
386
+ () => ({
387
+ settings,
388
+ toggle,
389
+ setSetting,
390
+ nextVariant,
391
+ nextIntensity,
392
+ nextColorScheme,
393
+ reset
394
+ }),
395
+ [settings, toggle, setSetting, nextVariant, nextIntensity, nextColorScheme, reset]
396
+ );
397
+ }
398
+ chunkWGEGR3DF_cjs.__name(useVisualizationState, "useVisualizationState");
399
+ function useVisualization() {
400
+ const context = react.useContext(VisualizationContext);
401
+ const fallbackState = useVisualizationState();
402
+ return context ?? fallbackState;
403
+ }
404
+ chunkWGEGR3DF_cjs.__name(useVisualization, "useVisualization");
405
+ var useAudioVisualization = useVisualization;
406
+ var VARIANT_INFO = {
407
+ spotlight: { label: "Spotlight", icon: "\u{1F4AB}" },
408
+ glow: { label: "Glow", icon: "\u2728" },
409
+ orbs: { label: "Orbs", icon: "\u{1F52E}" },
410
+ mesh: { label: "Mesh", icon: "\u{1F308}" },
411
+ none: { label: "Off", icon: "\u2B55" }
412
+ };
413
+ var INTENSITY_INFO = {
414
+ subtle: { label: "Subtle" },
415
+ medium: { label: "Medium" },
416
+ strong: { label: "Strong" }
417
+ };
418
+ var COLOR_SCHEME_INFO = {
419
+ primary: { label: "Primary", preview: "\u{1F535}" },
420
+ vibrant: { label: "Vibrant", preview: "\u{1F308}" },
421
+ cool: { label: "Cool", preview: "\u{1F499}" },
422
+ warm: { label: "Warm", preview: "\u{1F525}" }
423
+ };
424
+ var HybridAudioContext = react.createContext(null);
425
+ function HybridAudioProvider({ children, ...options }) {
426
+ const { settings: savedSettings, setSetting } = useVisualization();
427
+ const effectiveOptions = {
428
+ ...options,
429
+ initialVolume: savedSettings.volume,
430
+ loop: savedSettings.isLooping
431
+ };
432
+ const { audioRef, state, controls, webAudio } = useHybridAudio(effectiveOptions);
433
+ const hasAppliedInitialSettings = react.useRef(false);
434
+ react.useEffect(() => {
435
+ if (!state.isReady || hasAppliedInitialSettings.current) return;
436
+ hasAppliedInitialSettings.current = true;
437
+ controls.setVolume(savedSettings.volume);
438
+ controls.setLoop(savedSettings.isLooping);
439
+ }, [state.isReady, savedSettings, controls]);
440
+ react.useEffect(() => {
441
+ if (!state.isReady) return;
442
+ if (state.volume !== savedSettings.volume) {
443
+ setSetting("volume", state.volume);
444
+ }
445
+ if (state.isLooping !== savedSettings.isLooping) {
446
+ setSetting("isLooping", state.isLooping);
447
+ }
448
+ }, [state.isReady, state.volume, state.isLooping, savedSettings, setSetting]);
449
+ const audioLevels = useHybridAudioAnalysis(webAudio.analyser, state.isPlaying);
450
+ const value = react.useMemo(
451
+ () => ({
452
+ state,
453
+ controls,
454
+ webAudio,
455
+ audioLevels,
456
+ audioRef
457
+ }),
458
+ [state, controls, webAudio, audioLevels, audioRef]
459
+ );
460
+ return /* @__PURE__ */ jsxRuntime.jsx(HybridAudioContext.Provider, { value, children });
461
+ }
462
+ chunkWGEGR3DF_cjs.__name(HybridAudioProvider, "HybridAudioProvider");
463
+ function useHybridAudioContext() {
464
+ const context = react.useContext(HybridAudioContext);
465
+ if (!context) {
466
+ throw new Error("useHybridAudioContext must be used within HybridAudioProvider");
467
+ }
468
+ return context;
469
+ }
470
+ chunkWGEGR3DF_cjs.__name(useHybridAudioContext, "useHybridAudioContext");
471
+ function useHybridAudioState() {
472
+ const { state } = useHybridAudioContext();
473
+ return state;
474
+ }
475
+ chunkWGEGR3DF_cjs.__name(useHybridAudioState, "useHybridAudioState");
476
+ function useHybridAudioControls() {
477
+ const { controls } = useHybridAudioContext();
478
+ return controls;
479
+ }
480
+ chunkWGEGR3DF_cjs.__name(useHybridAudioControls, "useHybridAudioControls");
481
+ function useHybridAudioLevels() {
482
+ const { audioLevels } = useHybridAudioContext();
483
+ return audioLevels;
484
+ }
485
+ chunkWGEGR3DF_cjs.__name(useHybridAudioLevels, "useHybridAudioLevels");
486
+ function useHybridWebAudio() {
487
+ const { webAudio } = useHybridAudioContext();
488
+ return webAudio;
489
+ }
490
+ chunkWGEGR3DF_cjs.__name(useHybridWebAudio, "useHybridWebAudio");
491
+ var HybridWaveform = react.memo(/* @__PURE__ */ chunkWGEGR3DF_cjs.__name(function HybridWaveform2({
492
+ mode = "frequency",
493
+ height = 64,
494
+ barWidth = 3,
495
+ barGap = 2,
496
+ barRadius = 2,
497
+ progressColor = "hsl(217 91% 60%)",
498
+ waveColor = "hsl(217 91% 60% / 0.3)",
499
+ bufferedColor = "hsl(217 91% 60% / 0.15)",
500
+ className,
501
+ onSeek
502
+ }) {
503
+ const canvasRef = react.useRef(null);
504
+ const containerRef = react.useRef(null);
505
+ const animationRef = react.useRef(null);
506
+ const { state, controls, webAudio } = useHybridAudioContext();
507
+ const handleClick = react.useCallback(
508
+ (e) => {
509
+ const canvas = canvasRef.current;
510
+ if (!canvas || !state.duration) return;
511
+ const rect = canvas.getBoundingClientRect();
512
+ const x = e.clientX - rect.left;
513
+ const progress = x / rect.width;
514
+ const time = state.duration * progress;
515
+ controls.seek(time);
516
+ onSeek?.(time);
517
+ },
518
+ [state.duration, controls, onSeek]
519
+ );
520
+ const renderFrequency = react.useCallback(() => {
521
+ const canvas = canvasRef.current;
522
+ const analyser = webAudio.analyser;
523
+ if (!canvas) return;
524
+ const ctx = canvas.getContext("2d");
525
+ if (!ctx) return;
526
+ const { width, height: canvasHeight } = canvas;
527
+ const dpr = window.devicePixelRatio || 1;
528
+ const displayWidth = width / dpr;
529
+ let dataArray = null;
530
+ if (analyser) {
531
+ dataArray = new Uint8Array(analyser.frequencyBinCount);
532
+ analyser.getByteFrequencyData(dataArray);
533
+ }
534
+ ctx.clearRect(0, 0, width, canvasHeight);
535
+ if (state.buffered && state.duration > 0) {
536
+ ctx.fillStyle = bufferedColor;
537
+ for (let i = 0; i < state.buffered.length; i++) {
538
+ const start = state.buffered.start(i) / state.duration * width;
539
+ const end = state.buffered.end(i) / state.duration * width;
540
+ ctx.fillRect(start, canvasHeight - 3 * dpr, end - start, 3 * dpr);
541
+ }
542
+ }
543
+ const barCount = Math.floor(displayWidth / (barWidth + barGap));
544
+ const progress = state.duration > 0 ? state.currentTime / state.duration : 0;
545
+ const progressX = width * progress;
546
+ for (let i = 0; i < barCount; i++) {
547
+ let barHeight;
548
+ if (dataArray && state.isPlaying) {
549
+ const step = Math.floor(dataArray.length / barCount);
550
+ const value = dataArray[i * step] / 255;
551
+ barHeight = Math.max(4 * dpr, value * (canvasHeight - 6 * dpr) * 0.9);
552
+ } else {
553
+ barHeight = 8 * dpr;
554
+ }
555
+ const x = i * (barWidth + barGap) * dpr;
556
+ const y = (canvasHeight - barHeight) / 2;
557
+ ctx.fillStyle = x < progressX ? progressColor : waveColor;
558
+ const radius = barRadius * dpr;
559
+ const rectWidth = barWidth * dpr;
560
+ ctx.beginPath();
561
+ ctx.roundRect(x, y, rectWidth, barHeight, radius);
562
+ ctx.fill();
563
+ }
564
+ if (state.isPlaying) {
565
+ animationRef.current = requestAnimationFrame(renderFrequency);
566
+ }
567
+ }, [
568
+ webAudio.analyser,
569
+ state.buffered,
570
+ state.duration,
571
+ state.currentTime,
572
+ state.isPlaying,
573
+ barWidth,
574
+ barGap,
575
+ barRadius,
576
+ progressColor,
577
+ waveColor,
578
+ bufferedColor
579
+ ]);
580
+ const renderStatic = react.useCallback(() => {
581
+ const canvas = canvasRef.current;
582
+ if (!canvas) return;
583
+ const ctx = canvas.getContext("2d");
584
+ if (!ctx) return;
585
+ const { width, height: canvasHeight } = canvas;
586
+ const dpr = window.devicePixelRatio || 1;
587
+ ctx.clearRect(0, 0, width, canvasHeight);
588
+ if (state.buffered && state.duration > 0) {
589
+ ctx.fillStyle = bufferedColor;
590
+ for (let i = 0; i < state.buffered.length; i++) {
591
+ const start = state.buffered.start(i) / state.duration * width;
592
+ const end = state.buffered.end(i) / state.duration * width;
593
+ ctx.fillRect(start, 0, end - start, canvasHeight);
594
+ }
595
+ }
596
+ const progress = state.duration > 0 ? state.currentTime / state.duration : 0;
597
+ const progressWidth = width * progress;
598
+ ctx.fillStyle = waveColor;
599
+ ctx.fillRect(0, canvasHeight / 2 - 2 * dpr, width, 4 * dpr);
600
+ ctx.fillStyle = progressColor;
601
+ ctx.fillRect(0, canvasHeight / 2 - 2 * dpr, progressWidth, 4 * dpr);
602
+ if (progress > 0) {
603
+ ctx.beginPath();
604
+ ctx.arc(progressWidth, canvasHeight / 2, 6 * dpr, 0, Math.PI * 2);
605
+ ctx.fill();
606
+ }
607
+ }, [state.buffered, state.duration, state.currentTime, progressColor, waveColor, bufferedColor]);
608
+ react.useEffect(() => {
609
+ const container = containerRef.current;
610
+ const canvas = canvasRef.current;
611
+ if (!container || !canvas) return;
612
+ const resizeObserver = new ResizeObserver((entries) => {
613
+ const entry = entries[0];
614
+ if (!entry) return;
615
+ const dpr = window.devicePixelRatio || 1;
616
+ const displayWidth = entry.contentRect.width;
617
+ const displayHeight = height;
618
+ canvas.width = displayWidth * dpr;
619
+ canvas.height = displayHeight * dpr;
620
+ canvas.style.width = `${displayWidth}px`;
621
+ canvas.style.height = `${displayHeight}px`;
622
+ if (mode === "frequency") {
623
+ renderFrequency();
624
+ } else {
625
+ renderStatic();
626
+ }
627
+ });
628
+ resizeObserver.observe(container);
629
+ return () => resizeObserver.disconnect();
630
+ }, [height, mode, renderFrequency, renderStatic]);
631
+ react.useEffect(() => {
632
+ if (mode === "frequency") {
633
+ renderFrequency();
634
+ }
635
+ return () => {
636
+ if (animationRef.current) {
637
+ cancelAnimationFrame(animationRef.current);
638
+ }
639
+ };
640
+ }, [mode, renderFrequency]);
641
+ react.useEffect(() => {
642
+ if (mode === "static") {
643
+ renderStatic();
644
+ }
645
+ }, [mode, state.currentTime, renderStatic]);
646
+ react.useEffect(() => {
647
+ if (mode === "frequency" && !state.isPlaying) {
648
+ renderFrequency();
649
+ }
650
+ }, [mode, state.isPlaying, renderFrequency]);
651
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { ref: containerRef, className: lib.cn("w-full", className), children: /* @__PURE__ */ jsxRuntime.jsx(
652
+ "canvas",
653
+ {
654
+ ref: canvasRef,
655
+ onClick: handleClick,
656
+ className: "cursor-pointer",
657
+ style: { width: "100%", height }
658
+ }
659
+ ) });
660
+ }, "HybridWaveform"));
661
+
662
+ // src/tools/AudioPlayer/utils/formatTime.ts
663
+ function formatTime(seconds) {
664
+ if (!seconds || !isFinite(seconds) || seconds < 0) return "0:00";
665
+ const mins = Math.floor(seconds / 60);
666
+ const secs = Math.floor(seconds % 60);
667
+ return `${mins}:${secs.toString().padStart(2, "0")}`;
668
+ }
669
+ chunkWGEGR3DF_cjs.__name(formatTime, "formatTime");
670
+ lib.createMediaLogger("AudioPlayer");
671
+ var HybridAudioPlayer = react.memo(/* @__PURE__ */ chunkWGEGR3DF_cjs.__name(function HybridAudioPlayer2({
672
+ showControls = true,
673
+ showWaveform = true,
674
+ waveformMode = "frequency",
675
+ waveformHeight = 64,
676
+ showTimer = true,
677
+ showVolume = true,
678
+ showLoop = true,
679
+ className,
680
+ style
681
+ }) {
682
+ const t = i18n.useTypedT();
683
+ const { state, controls } = useHybridAudioContext();
684
+ const labels = react.useMemo(() => ({
685
+ restart: t("tools.audio.restart"),
686
+ back: t("tools.audio.back"),
687
+ forward: t("tools.audio.forward"),
688
+ volume: t("tools.audio.volume")
689
+ }), [t]);
690
+ const isLoading = !state.isReady;
691
+ const handleVolumeChange = /* @__PURE__ */ chunkWGEGR3DF_cjs.__name((value) => {
692
+ controls.setVolume(value[0] / 100);
693
+ }, "handleVolumeChange");
694
+ return /* @__PURE__ */ jsxRuntime.jsxs(
695
+ "div",
696
+ {
697
+ className: chunkF2N7P5XU_cjs.cn("flex flex-col gap-3 p-4 rounded-lg bg-card border", className),
698
+ style,
699
+ children: [
700
+ showWaveform && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
701
+ /* @__PURE__ */ jsxRuntime.jsx(
702
+ HybridWaveform,
703
+ {
704
+ mode: waveformMode,
705
+ height: waveformHeight,
706
+ className: chunkF2N7P5XU_cjs.cn(isLoading && "opacity-50")
707
+ }
708
+ ),
709
+ isLoading && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0 flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "h-6 w-6 animate-spin text-primary" }) })
710
+ ] }),
711
+ showTimer && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-between text-xs text-muted-foreground tabular-nums px-1", children: [
712
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: formatTime(state.currentTime) }),
713
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: formatTime(state.duration) })
714
+ ] }),
715
+ showControls && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-center gap-1", children: [
716
+ /* @__PURE__ */ jsxRuntime.jsx(
717
+ chunkF2N7P5XU_cjs.Button,
718
+ {
719
+ variant: "ghost",
720
+ size: "icon",
721
+ className: "h-9 w-9",
722
+ onClick: controls.restart,
723
+ disabled: !state.isReady,
724
+ title: labels.restart,
725
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.RotateCcw, { className: "h-4 w-4" })
726
+ }
727
+ ),
728
+ /* @__PURE__ */ jsxRuntime.jsx(
729
+ chunkF2N7P5XU_cjs.Button,
730
+ {
731
+ variant: "ghost",
732
+ size: "icon",
733
+ className: "h-9 w-9",
734
+ onClick: () => controls.skip(-5),
735
+ disabled: !state.isReady,
736
+ title: labels.back,
737
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.SkipBack, { className: "h-4 w-4" })
738
+ }
739
+ ),
740
+ /* @__PURE__ */ jsxRuntime.jsx(
741
+ chunkF2N7P5XU_cjs.Button,
742
+ {
743
+ variant: "default",
744
+ size: "icon",
745
+ className: "h-12 w-12 rounded-full",
746
+ onClick: controls.togglePlay,
747
+ disabled: !state.isReady && !isLoading,
748
+ title: state.isPlaying ? "Pause" : "Play",
749
+ children: isLoading ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "h-5 w-5 animate-spin" }) : state.isPlaying ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Pause, { className: "h-5 w-5" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Play, { className: "h-5 w-5 ml-0.5" })
750
+ }
751
+ ),
752
+ /* @__PURE__ */ jsxRuntime.jsx(
753
+ chunkF2N7P5XU_cjs.Button,
754
+ {
755
+ variant: "ghost",
756
+ size: "icon",
757
+ className: "h-9 w-9",
758
+ onClick: () => controls.skip(5),
759
+ disabled: !state.isReady,
760
+ title: labels.forward,
761
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.SkipForward, { className: "h-4 w-4" })
762
+ }
763
+ ),
764
+ showVolume && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
765
+ /* @__PURE__ */ jsxRuntime.jsx(
766
+ chunkF2N7P5XU_cjs.Button,
767
+ {
768
+ variant: "ghost",
769
+ size: "icon",
770
+ className: "h-9 w-9",
771
+ onClick: controls.toggleMute,
772
+ title: state.isMuted ? "Unmute" : "Mute",
773
+ children: state.isMuted || state.volume === 0 ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.VolumeX, { className: "h-4 w-4" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Volume2, { className: "h-4 w-4" })
774
+ }
775
+ ),
776
+ /* @__PURE__ */ jsxRuntime.jsx(
777
+ chunkF2N7P5XU_cjs.Slider,
778
+ {
779
+ value: [state.isMuted ? 0 : state.volume * 100],
780
+ max: 100,
781
+ step: 1,
782
+ onValueChange: handleVolumeChange,
783
+ className: "w-20",
784
+ "aria-label": labels.volume
785
+ }
786
+ )
787
+ ] }),
788
+ showLoop && /* @__PURE__ */ jsxRuntime.jsx(
789
+ chunkF2N7P5XU_cjs.Button,
790
+ {
791
+ variant: "ghost",
792
+ size: "icon",
793
+ className: chunkF2N7P5XU_cjs.cn("h-9 w-9", state.isLooping && "text-primary"),
794
+ onClick: controls.toggleLoop,
795
+ disabled: !state.isReady,
796
+ title: state.isLooping ? "Disable loop" : "Enable loop",
797
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Repeat, { className: "h-4 w-4" })
798
+ }
799
+ )
800
+ ] })
801
+ ]
802
+ }
803
+ );
804
+ }, "HybridAudioPlayer"));
805
+
806
+ // src/tools/AudioPlayer/effects/index.ts
807
+ var INTENSITY_CONFIG = {
808
+ subtle: { opacity: 0.3, scale: 0.02, blur: "blur-2xl" },
809
+ medium: { opacity: 0.5, scale: 0.04, blur: "blur-xl" },
810
+ strong: { opacity: 0.7, scale: 0.06, blur: "blur-lg" }
811
+ };
812
+ var COLOR_SCHEMES2 = {
813
+ primary: ["217 91% 60%"],
814
+ vibrant: ["217 91% 60%", "142 76% 36%", "262 83% 58%", "25 95% 53%"],
815
+ cool: ["217 91% 60%", "262 83% 58%", "199 89% 48%"],
816
+ warm: ["25 95% 53%", "0 84% 60%", "38 92% 50%"]
817
+ };
818
+ var DEFAULT_GLOW_COLORS = [
819
+ "217 91% 60%",
820
+ // Blue
821
+ "262 83% 58%",
822
+ // Purple
823
+ "330 81% 60%",
824
+ // Pink
825
+ "25 95% 53%"
826
+ // Orange
827
+ ];
828
+ function getEffectConfig(intensity) {
829
+ return INTENSITY_CONFIG[intensity];
830
+ }
831
+ chunkWGEGR3DF_cjs.__name(getEffectConfig, "getEffectConfig");
832
+ function getColors(colorScheme) {
833
+ return COLOR_SCHEMES2[colorScheme];
834
+ }
835
+ chunkWGEGR3DF_cjs.__name(getColors, "getColors");
836
+ function prepareEffectColors(colorScheme, levels) {
837
+ const baseColors = COLOR_SCHEMES2[colorScheme];
838
+ const colors = baseColors.length > 1 ? baseColors : DEFAULT_GLOW_COLORS;
839
+ const hueShift = Math.floor(
840
+ levels.bass * 30 + levels.mid * 20 + levels.high * 10
841
+ );
842
+ return { colors, hueShift };
843
+ }
844
+ chunkWGEGR3DF_cjs.__name(prepareEffectColors, "prepareEffectColors");
845
+ function calculateGlowLayers(levels, config, colors) {
846
+ const { bass, mid, high } = levels;
847
+ return [
848
+ // Layer 1: Bass glow - bottom
849
+ {
850
+ inset: 60 + bass * 90,
851
+ opacity: 1,
852
+ scale: 1 + bass * 0.5,
853
+ background: `radial-gradient(ellipse 80% 60% at 50% 100%, hsl(${colors[0]} / ${0.4 + bass * 0.4}) 0%, transparent 70%)`,
854
+ blur: "blur-3xl"
855
+ },
856
+ // Layer 2: Mid glow - top
857
+ {
858
+ inset: 45 + mid * 75,
859
+ opacity: 1,
860
+ scale: 1 + mid * 0.4,
861
+ background: `radial-gradient(ellipse 70% 50% at 50% 0%, hsl(${colors[1] || colors[0]} / ${0.3 + mid * 0.5}) 0%, transparent 70%)`,
862
+ blur: "blur-2xl"
863
+ },
864
+ // Layer 3: High glow - left
865
+ {
866
+ inset: 30 + high * 60,
867
+ opacity: 1,
868
+ scale: 1 + high * 0.3,
869
+ background: `radial-gradient(ellipse 50% 80% at 0% 50%, hsl(${colors[2] || colors[0]} / ${0.3 + high * 0.4}) 0%, transparent 60%)`,
870
+ blur: "blur-2xl"
871
+ },
872
+ // Layer 4: High glow - right
873
+ {
874
+ inset: 30 + high * 60,
875
+ opacity: 1,
876
+ scale: 1 + high * 0.3,
877
+ background: `radial-gradient(ellipse 50% 80% at 100% 50%, hsl(${colors[3] || colors[0]} / ${0.3 + high * 0.4}) 0%, transparent 60%)`,
878
+ blur: "blur-2xl"
879
+ },
880
+ // Layer 5: Center pulsing glow
881
+ {
882
+ inset: 24 + bass * 45,
883
+ opacity: 1,
884
+ scale: 1 + bass * 0.2,
885
+ 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%)`,
886
+ blur: "blur-xl",
887
+ animation: "glow-breathe 2s ease-in-out infinite"
888
+ }
889
+ ];
890
+ }
891
+ chunkWGEGR3DF_cjs.__name(calculateGlowLayers, "calculateGlowLayers");
892
+ function calculateOrbs(levels, config, colors, baseSize = 50) {
893
+ const { bass, mid, high, overall } = levels;
894
+ const size = baseSize * 3;
895
+ const bassMove = bass * 30;
896
+ const midMove = mid * 25;
897
+ const highMove = high * 20;
898
+ return [
899
+ // Bass orb - top left, big pulses
900
+ {
901
+ x: -40 + bassMove,
902
+ y: -40 - bassMove * 0.5,
903
+ size: size * (1 + bass * 1.2),
904
+ color: colors[0],
905
+ opacity: 0.5 + bass * 0.5,
906
+ scale: 1 + bass * 0.6
907
+ },
908
+ // Mid orb - top right
909
+ {
910
+ x: 130 - midMove * 0.5,
911
+ y: -30 + midMove,
912
+ size: size * (0.9 + mid * 1),
913
+ color: colors[1] || colors[0],
914
+ opacity: 0.5 + mid * 0.5,
915
+ scale: 1 + mid * 0.5
916
+ },
917
+ // High orb - bottom right
918
+ {
919
+ x: 140 + highMove * 0.3,
920
+ y: 120 - highMove,
921
+ size: size * (0.8 + high * 0.8),
922
+ color: colors[2] || colors[0],
923
+ opacity: 0.4 + high * 0.6,
924
+ scale: 1 + high * 0.45
925
+ },
926
+ // Mid orb 2 - bottom left
927
+ {
928
+ x: -30 - midMove * 0.4,
929
+ y: 130 + midMove * 0.3,
930
+ size: size * (0.9 + mid * 0.9),
931
+ color: colors[3] || colors[0],
932
+ opacity: 0.45 + mid * 0.55,
933
+ scale: 1 + mid * 0.5
934
+ },
935
+ // Center overall orb
936
+ {
937
+ x: 50,
938
+ y: 50,
939
+ size: size * (0.6 + overall * 1.5),
940
+ color: colors[0],
941
+ opacity: 0.3 + overall * 0.5,
942
+ scale: 1 + overall * 0.7
943
+ }
944
+ ];
945
+ }
946
+ chunkWGEGR3DF_cjs.__name(calculateOrbs, "calculateOrbs");
947
+ function calculateMeshGradients(levels, config, colors) {
948
+ const { bass, mid, high, overall } = levels;
949
+ const bassOffset = bass * 40;
950
+ const midOffset = mid * 30;
951
+ const highOffset = high * 25;
952
+ return [
953
+ // Large bass blob - top right, pulses hard
954
+ {
955
+ width: `${200 + bass * 150}%`,
956
+ height: `${200 + bass * 150}%`,
957
+ top: `${ -80 + bassOffset}%`,
958
+ right: `${ -80 - bassOffset}%`,
959
+ color: colors[0],
960
+ opacity: 0.4 + bass * 0.6,
961
+ scale: 1 + bass * 0.5,
962
+ rotation: bass * 45,
963
+ blur: "blur-2xl"
964
+ },
965
+ // Mid blob - bottom left
966
+ {
967
+ width: `${180 + mid * 120}%`,
968
+ height: `${180 + mid * 120}%`,
969
+ bottom: `${ -60 + midOffset}%`,
970
+ left: `${ -60 - midOffset}%`,
971
+ color: colors[1] || colors[0],
972
+ opacity: 0.4 + mid * 0.6,
973
+ scale: 1 + mid * 0.4,
974
+ rotation: -mid * 40,
975
+ blur: "blur-2xl"
976
+ },
977
+ // High blob - bottom right
978
+ {
979
+ width: `${140 + high * 100}%`,
980
+ height: `${140 + high * 100}%`,
981
+ top: `${70 - highOffset}%`,
982
+ right: `${ -50 + highOffset}%`,
983
+ color: colors[2] || colors[0],
984
+ opacity: 0.35 + high * 0.65,
985
+ scale: 1 + high * 0.35,
986
+ rotation: high * 35,
987
+ blur: "blur-xl"
988
+ },
989
+ // Extra bass reactive blob - top left
990
+ {
991
+ width: `${160 + bass * 140}%`,
992
+ height: `${160 + bass * 140}%`,
993
+ top: `${ -60 - bassOffset * 0.8}%`,
994
+ left: `${ -60 + bassOffset * 0.8}%`,
995
+ color: colors[3] || colors[1] || colors[0],
996
+ opacity: 0.35 + bass * 0.65,
997
+ scale: 1 + bass * 0.55,
998
+ rotation: -bass * 50,
999
+ blur: "blur-2xl"
1000
+ },
1001
+ // Center glow - pulses with overall
1002
+ {
1003
+ width: `${80 + overall * 150}%`,
1004
+ height: `${80 + overall * 150}%`,
1005
+ top: "50%",
1006
+ left: "50%",
1007
+ color: colors[0],
1008
+ opacity: 0.3 + overall * 0.5,
1009
+ scale: 1 + overall * 0.4,
1010
+ rotation: 0,
1011
+ isCenter: true,
1012
+ blur: "blur-3xl"
1013
+ }
1014
+ ];
1015
+ }
1016
+ chunkWGEGR3DF_cjs.__name(calculateMeshGradients, "calculateMeshGradients");
1017
+ function calculateSpotlight(levels, config, colors, rotation) {
1018
+ const { bass, mid, high, overall } = levels;
1019
+ return {
1020
+ // Rotation speed increases with mid frequencies
1021
+ rotation: rotation + mid * 180,
1022
+ // Border expands with bass
1023
+ inset: 12 + bass * 30,
1024
+ // Color intensities react to different frequencies
1025
+ colors: colors.map((c, i) => ({
1026
+ color: c,
1027
+ opacity: i === 0 ? 0.3 + bass * 0.7 : i === 1 ? 0.3 + mid * 0.7 : 0.3 + high * 0.7
1028
+ })),
1029
+ // Pulse glow - big and reactive
1030
+ pulseInset: 24 + bass * 50,
1031
+ pulseOpacity: 0.3 + bass * 0.7,
1032
+ pulseScale: 1 + bass * 0.4,
1033
+ // Extra glow ring
1034
+ ringOpacity: 0.2 + overall * 0.6,
1035
+ ringScale: 1 + overall * 0.3
1036
+ };
1037
+ }
1038
+ chunkWGEGR3DF_cjs.__name(calculateSpotlight, "calculateSpotlight");
1039
+ var EFFECT_ANIMATIONS = `
1040
+ @keyframes spotlight-spin {
1041
+ 0% { transform: rotate(0deg); }
1042
+ 100% { transform: rotate(360deg); }
1043
+ }
1044
+
1045
+ @keyframes orb-float-1 {
1046
+ 0%, 100% { transform: translate(-50%, -50%) translateY(0); }
1047
+ 50% { transform: translate(-50%, -50%) translateY(-15px); }
1048
+ }
1049
+
1050
+ @keyframes orb-float-2 {
1051
+ 0%, 100% { transform: translate(-50%, -50%) translateX(0); }
1052
+ 50% { transform: translate(-50%, -50%) translateX(15px); }
1053
+ }
1054
+
1055
+ @keyframes orb-float-3 {
1056
+ 0%, 100% { transform: translate(-50%, -50%) translate(0, 0); }
1057
+ 33% { transform: translate(-50%, -50%) translate(10px, -10px); }
1058
+ 66% { transform: translate(-50%, -50%) translate(-10px, 10px); }
1059
+ }
1060
+
1061
+ @keyframes orb-float-4 {
1062
+ 0%, 100% { transform: translate(-50%, -50%) translate(0, 0); }
1063
+ 50% { transform: translate(-50%, -50%) translate(-15px, -10px); }
1064
+ }
1065
+
1066
+ @keyframes mesh-float-1 {
1067
+ 0%, 100% { transform: translate(0, 0) scale(1); }
1068
+ 25% { transform: translate(-5%, 10%) scale(1.05); }
1069
+ 50% { transform: translate(5%, 5%) scale(0.95); }
1070
+ 75% { transform: translate(-3%, -5%) scale(1.02); }
1071
+ }
1072
+
1073
+ @keyframes mesh-float-2 {
1074
+ 0%, 100% { transform: translate(0, 0) scale(1); }
1075
+ 33% { transform: translate(8%, -8%) scale(1.08); }
1076
+ 66% { transform: translate(-6%, 6%) scale(0.92); }
1077
+ }
1078
+
1079
+ @keyframes mesh-float-3 {
1080
+ 0%, 100% { transform: translate(0, 0) scale(1); }
1081
+ 50% { transform: translate(10%, 10%) scale(1.1); }
1082
+ }
1083
+
1084
+ @keyframes mesh-float-4 {
1085
+ 0%, 100% { transform: translate(0, 0) scale(1) rotate(0deg); }
1086
+ 25% { transform: translate(10%, -5%) scale(1.1) rotate(5deg); }
1087
+ 50% { transform: translate(-5%, 10%) scale(0.95) rotate(-5deg); }
1088
+ 75% { transform: translate(-10%, -10%) scale(1.05) rotate(3deg); }
1089
+ }
1090
+
1091
+ @keyframes mesh-pulse {
1092
+ 0%, 100% { transform: translate(-50%, -50%) scale(1); opacity: 0.3; }
1093
+ 50% { transform: translate(-50%, -50%) scale(1.2); opacity: 0.5; }
1094
+ }
1095
+
1096
+ @keyframes glow-breathe {
1097
+ 0%, 100% { opacity: 0.6; transform: scale(1); }
1098
+ 50% { opacity: 1; transform: scale(1.05); }
1099
+ }
1100
+
1101
+ @keyframes glow-rotate {
1102
+ 0% { transform: rotate(0deg); }
1103
+ 100% { transform: rotate(360deg); }
1104
+ }
1105
+
1106
+ @keyframes sparkle-move {
1107
+ 0% { opacity: 0; transform: scale(0.8); }
1108
+ 50% { opacity: 1; }
1109
+ 100% { opacity: 0; transform: scale(1.2); }
1110
+ }
1111
+ `;
1112
+ function GlowEffect({ data, colors, isPlaying }) {
1113
+ const { layers, hueShift, showPulseRings, showSparkle } = data;
1114
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1115
+ layers.map((layer, i) => /* @__PURE__ */ jsxRuntime.jsx(
1116
+ "div",
1117
+ {
1118
+ className: chunkF2N7P5XU_cjs.cn("absolute rounded-2xl -z-10", layer.blur),
1119
+ style: {
1120
+ inset: `-${layer.inset}px`,
1121
+ background: layer.background,
1122
+ opacity: isPlaying ? layer.opacity : 0,
1123
+ transform: i < 2 ? `scaleY(${layer.scale})` : `scale(${layer.scale})`,
1124
+ animation: isPlaying && layer.animation ? layer.animation : "none",
1125
+ transition: "opacity 0.3s"
1126
+ }
1127
+ },
1128
+ i
1129
+ )),
1130
+ /* @__PURE__ */ jsxRuntime.jsx(
1131
+ "div",
1132
+ {
1133
+ className: "absolute rounded-2xl blur-xl overflow-hidden -z-10",
1134
+ style: {
1135
+ inset: "-75px",
1136
+ opacity: isPlaying ? 0.6 : 0,
1137
+ transition: "opacity 0.5s"
1138
+ },
1139
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1140
+ "div",
1141
+ {
1142
+ className: "absolute inset-0",
1143
+ style: {
1144
+ background: `conic-gradient(
1145
+ from ${hueShift}deg at 50% 50%,
1146
+ hsl(${colors[0]} / 0.4) 0deg,
1147
+ hsl(${colors[1] || colors[0]} / 0.3) 90deg,
1148
+ hsl(${colors[2] || colors[0]} / 0.3) 180deg,
1149
+ hsl(${colors[3] || colors[0]} / 0.3) 270deg,
1150
+ hsl(${colors[0]} / 0.4) 360deg
1151
+ )`,
1152
+ animation: isPlaying ? "glow-rotate 6s linear infinite" : "none"
1153
+ }
1154
+ }
1155
+ )
1156
+ }
1157
+ ),
1158
+ showPulseRings && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1159
+ /* @__PURE__ */ jsxRuntime.jsx(
1160
+ "div",
1161
+ {
1162
+ className: "absolute -inset-6 rounded-xl border-2 animate-ping -z-10",
1163
+ style: {
1164
+ borderColor: `hsl(${colors[0]} / 0.4)`,
1165
+ animationDuration: "1s"
1166
+ }
1167
+ }
1168
+ ),
1169
+ /* @__PURE__ */ jsxRuntime.jsx(
1170
+ "div",
1171
+ {
1172
+ className: "absolute -inset-12 rounded-2xl border animate-ping -z-10",
1173
+ style: {
1174
+ borderColor: `hsl(${colors[1] || colors[0]} / 0.3)`,
1175
+ animationDuration: "1.5s",
1176
+ animationDelay: "0.2s"
1177
+ }
1178
+ }
1179
+ )
1180
+ ] }),
1181
+ showSparkle && /* @__PURE__ */ jsxRuntime.jsx(
1182
+ "div",
1183
+ {
1184
+ className: "absolute -inset-18 rounded-3xl -z-10",
1185
+ style: {
1186
+ background: `radial-gradient(circle at 50% 30%, hsl(${colors[2] || colors[0]} / 0.5) 0%, transparent 30%)`,
1187
+ animation: "sparkle-move 0.5s ease-out"
1188
+ }
1189
+ }
1190
+ )
1191
+ ] });
1192
+ }
1193
+ chunkWGEGR3DF_cjs.__name(GlowEffect, "GlowEffect");
1194
+ function OrbsEffect({ orbs, blur, isPlaying }) {
1195
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: orbs.map((orb, i) => /* @__PURE__ */ jsxRuntime.jsx(
1196
+ "div",
1197
+ {
1198
+ className: chunkF2N7P5XU_cjs.cn("absolute rounded-full -z-10", blur),
1199
+ style: {
1200
+ width: orb.size,
1201
+ height: orb.size,
1202
+ left: `${orb.x}%`,
1203
+ top: `${orb.y}%`,
1204
+ background: `radial-gradient(circle at 30% 30%, hsl(${orb.color}) 0%, hsl(${orb.color} / 0.5) 40%, transparent 70%)`,
1205
+ opacity: isPlaying ? orb.opacity : 0,
1206
+ transform: `translate(-50%, -50%) scale(${orb.scale})`,
1207
+ transition: "all 0.08s ease-out"
1208
+ }
1209
+ },
1210
+ i
1211
+ )) });
1212
+ }
1213
+ chunkWGEGR3DF_cjs.__name(OrbsEffect, "OrbsEffect");
1214
+ function SpotlightEffect({ data, colors, blur, isPlaying }) {
1215
+ const inset = "inset" in data ? data.inset : 12;
1216
+ const pulseInset = "pulseInset" in data ? data.pulseInset : 24;
1217
+ const ringOpacity = "ringOpacity" in data ? data.ringOpacity : 0.3;
1218
+ const ringScale = "ringScale" in data ? data.ringScale : 1;
1219
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1220
+ /* @__PURE__ */ jsxRuntime.jsx(
1221
+ "div",
1222
+ {
1223
+ className: chunkF2N7P5XU_cjs.cn("absolute rounded-xl -z-10", blur),
1224
+ style: {
1225
+ inset: `-${inset}px`,
1226
+ background: `conic-gradient(
1227
+ from ${data.rotation}deg,
1228
+ hsl(${colors[0]} / ${data.colors[0]?.opacity || 0.5}),
1229
+ hsl(${colors[1] || colors[0]} / ${data.colors[1]?.opacity || 0.7}),
1230
+ hsl(${colors[2] || colors[0]} / ${data.colors[2]?.opacity || 0.5}),
1231
+ hsl(${colors[0]} / ${data.colors[1]?.opacity || 0.7}),
1232
+ hsl(${colors[0]} / ${data.colors[0]?.opacity || 0.5})
1233
+ )`,
1234
+ opacity: isPlaying ? 1 : 0,
1235
+ transition: "all 0.08s ease-out"
1236
+ }
1237
+ }
1238
+ ),
1239
+ /* @__PURE__ */ jsxRuntime.jsx(
1240
+ "div",
1241
+ {
1242
+ className: "absolute -inset-1 rounded-lg bg-background -z-10",
1243
+ style: { opacity: isPlaying ? 1 : 0, transition: "opacity 0.1s" }
1244
+ }
1245
+ ),
1246
+ /* @__PURE__ */ jsxRuntime.jsx(
1247
+ "div",
1248
+ {
1249
+ className: chunkF2N7P5XU_cjs.cn("absolute rounded-2xl -z-10", blur),
1250
+ style: {
1251
+ inset: `-${pulseInset}px`,
1252
+ background: `radial-gradient(circle, hsl(${colors[0]} / 0.7) 0%, hsl(${colors[0]} / 0.3) 50%, transparent 70%)`,
1253
+ opacity: isPlaying ? data.pulseOpacity : 0,
1254
+ transform: `scale(${data.pulseScale})`,
1255
+ transition: "all 0.08s ease-out"
1256
+ }
1257
+ }
1258
+ ),
1259
+ /* @__PURE__ */ jsxRuntime.jsx(
1260
+ "div",
1261
+ {
1262
+ className: "absolute rounded-3xl -z-10 blur-2xl",
1263
+ style: {
1264
+ inset: `-${pulseInset + 30}px`,
1265
+ background: `radial-gradient(circle, hsl(${colors[1] || colors[0]} / 0.4) 0%, transparent 60%)`,
1266
+ opacity: isPlaying ? ringOpacity : 0,
1267
+ transform: `scale(${ringScale})`,
1268
+ transition: "all 0.08s ease-out"
1269
+ }
1270
+ }
1271
+ )
1272
+ ] });
1273
+ }
1274
+ chunkWGEGR3DF_cjs.__name(SpotlightEffect, "SpotlightEffect");
1275
+ function MeshEffect({ gradients, isPlaying }) {
1276
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: gradients.map((g, i) => {
1277
+ const isCenter = "isCenter" in g && g.isCenter;
1278
+ const scale = "scale" in g ? g.scale : 1;
1279
+ const rotation = "rotation" in g ? g.rotation : 0;
1280
+ const itemBlur = "blur" in g ? g.blur : "blur-2xl";
1281
+ return /* @__PURE__ */ jsxRuntime.jsx(
1282
+ "div",
1283
+ {
1284
+ className: chunkF2N7P5XU_cjs.cn("absolute rounded-full -z-10", itemBlur),
1285
+ style: {
1286
+ width: g.width,
1287
+ height: g.height,
1288
+ top: "top" in g ? g.top : void 0,
1289
+ bottom: "bottom" in g ? g.bottom : void 0,
1290
+ left: "left" in g ? g.left : void 0,
1291
+ right: "right" in g ? g.right : void 0,
1292
+ background: isCenter ? `radial-gradient(circle, hsl(${g.color} / 0.6) 0%, hsl(${g.color} / 0.3) 30%, transparent 60%)` : `radial-gradient(circle, hsl(${g.color}) 0%, hsl(${g.color} / 0.5) 30%, transparent 65%)`,
1293
+ opacity: isPlaying ? g.opacity : 0,
1294
+ transform: isCenter ? `translate(-50%, -50%) scale(${scale})` : `scale(${scale}) rotate(${rotation}deg)`,
1295
+ transition: "all 0.08s ease-out"
1296
+ }
1297
+ },
1298
+ i
1299
+ );
1300
+ }) });
1301
+ }
1302
+ chunkWGEGR3DF_cjs.__name(MeshEffect, "MeshEffect");
1303
+ var SIZES = {
1304
+ sm: { container: "w-32 h-32", orbBase: 40 },
1305
+ md: { container: "w-40 h-40", orbBase: 50 },
1306
+ lg: { container: "w-48 h-48", orbBase: 60 }
1307
+ };
1308
+ function AudioReactiveCover({
1309
+ children,
1310
+ size = "lg",
1311
+ variant = "spotlight",
1312
+ intensity = "medium",
1313
+ colorScheme = "primary",
1314
+ onClick,
1315
+ className
1316
+ }) {
1317
+ const { isPlaying } = useHybridAudioState();
1318
+ const levels = useHybridAudioLevels();
1319
+ const sizeConfig = SIZES[size];
1320
+ const effectConfig = getEffectConfig(intensity);
1321
+ const { colors, hueShift } = prepareEffectColors(colorScheme, levels);
1322
+ const containerScale = 1 + levels.overall * effectConfig.scale;
1323
+ const glowData = variant === "glow" ? {
1324
+ layers: calculateGlowLayers(levels, effectConfig, colors),
1325
+ hueShift,
1326
+ showPulseRings: levels.bass > 0.5,
1327
+ showSparkle: levels.high > 0.4
1328
+ } : null;
1329
+ const orbsData = variant === "orbs" ? calculateOrbs(levels, effectConfig, colors, sizeConfig.orbBase) : null;
1330
+ const meshData = variant === "mesh" ? calculateMeshGradients(levels, effectConfig, colors) : null;
1331
+ const spotlightData = variant === "spotlight" ? calculateSpotlight(levels, effectConfig, colors, levels.mid * 360) : null;
1332
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1333
+ "div",
1334
+ {
1335
+ className: chunkF2N7P5XU_cjs.cn("relative", sizeConfig.container, className),
1336
+ style: {
1337
+ transform: `scale(${containerScale})`,
1338
+ transition: "transform 0.1s ease-out"
1339
+ },
1340
+ children: [
1341
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "absolute inset-0 z-0 pointer-events-none overflow-visible", children: [
1342
+ glowData && /* @__PURE__ */ jsxRuntime.jsx(GlowEffect, { data: glowData, colors, isPlaying }),
1343
+ orbsData && /* @__PURE__ */ jsxRuntime.jsx(OrbsEffect, { orbs: orbsData, blur: effectConfig.blur, isPlaying }),
1344
+ spotlightData && /* @__PURE__ */ jsxRuntime.jsx(SpotlightEffect, { data: spotlightData, colors, blur: effectConfig.blur, isPlaying }),
1345
+ meshData && /* @__PURE__ */ jsxRuntime.jsx(MeshEffect, { gradients: meshData, blur: effectConfig.blur, isPlaying })
1346
+ ] }),
1347
+ /* @__PURE__ */ jsxRuntime.jsx(
1348
+ "div",
1349
+ {
1350
+ className: "relative w-full h-full rounded-lg overflow-hidden shadow-2xl z-10 bg-background cursor-pointer",
1351
+ onClick,
1352
+ role: onClick ? "button" : void 0,
1353
+ tabIndex: onClick ? 0 : void 0,
1354
+ onKeyDown: onClick ? (e) => e.key === "Enter" && onClick() : void 0,
1355
+ children
1356
+ }
1357
+ ),
1358
+ /* @__PURE__ */ jsxRuntime.jsx("style", { dangerouslySetInnerHTML: { __html: EFFECT_ANIMATIONS } })
1359
+ ]
1360
+ }
1361
+ );
1362
+ }
1363
+ chunkWGEGR3DF_cjs.__name(AudioReactiveCover, "AudioReactiveCover");
1364
+ var COVER_SIZES = {
1365
+ sm: "w-24 h-24",
1366
+ md: "w-32 h-32",
1367
+ lg: "w-48 h-48"
1368
+ };
1369
+ function HybridSimplePlayer(props) {
1370
+ return /* @__PURE__ */ jsxRuntime.jsx(VisualizationProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(HybridSimplePlayerContent, { ...props }) });
1371
+ }
1372
+ chunkWGEGR3DF_cjs.__name(HybridSimplePlayer, "HybridSimplePlayer");
1373
+ function HybridSimplePlayerContent({
1374
+ src,
1375
+ title,
1376
+ artist,
1377
+ coverArt,
1378
+ coverSize = "md",
1379
+ showWaveform = true,
1380
+ waveformMode = "frequency",
1381
+ waveformHeight = 64,
1382
+ showTimer = true,
1383
+ showVolume = true,
1384
+ showLoop = true,
1385
+ reactiveCover = true,
1386
+ variant,
1387
+ intensity,
1388
+ colorScheme,
1389
+ autoPlay = false,
1390
+ loop = false,
1391
+ initialVolume = 1,
1392
+ layout = "vertical",
1393
+ className,
1394
+ onPlay,
1395
+ onPause,
1396
+ onEnded,
1397
+ onError
1398
+ }) {
1399
+ const { settings: vizSettings, nextVariant } = useVisualization();
1400
+ const effectiveVariant = variant ?? (vizSettings.variant !== "none" ? vizSettings.variant : "spotlight");
1401
+ const effectiveIntensity = intensity ?? vizSettings.intensity;
1402
+ const effectiveColorScheme = colorScheme ?? vizSettings.colorScheme;
1403
+ const showReactiveCover = reactiveCover && effectiveVariant !== "none";
1404
+ const renderCoverContent = /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(() => {
1405
+ if (typeof coverArt === "string") {
1406
+ return /* @__PURE__ */ jsxRuntime.jsx("img", { src: coverArt, alt: title || "Album cover", className: "w-full h-full object-cover" });
1407
+ }
1408
+ if (coverArt) {
1409
+ return coverArt;
1410
+ }
1411
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full h-full bg-muted/30 flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Music, { className: "w-1/3 h-1/3 text-muted-foreground/50" }) });
1412
+ }, "renderCoverContent");
1413
+ const isHorizontal = layout === "horizontal";
1414
+ return /* @__PURE__ */ jsxRuntime.jsx(
1415
+ HybridAudioProvider,
1416
+ {
1417
+ src,
1418
+ autoPlay,
1419
+ loop,
1420
+ initialVolume,
1421
+ onPlay,
1422
+ onPause,
1423
+ onEnded,
1424
+ onError,
1425
+ children: /* @__PURE__ */ jsxRuntime.jsxs(
1426
+ "div",
1427
+ {
1428
+ className: uiCore.cn(
1429
+ "flex gap-4",
1430
+ isHorizontal ? "flex-row items-center" : "flex-col items-center",
1431
+ className
1432
+ ),
1433
+ children: [
1434
+ (coverArt || reactiveCover) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center gap-2 shrink-0", children: [
1435
+ showReactiveCover ? /* @__PURE__ */ jsxRuntime.jsx(
1436
+ AudioReactiveCover,
1437
+ {
1438
+ size: coverSize,
1439
+ variant: effectiveVariant,
1440
+ intensity: effectiveIntensity,
1441
+ colorScheme: effectiveColorScheme,
1442
+ onClick: nextVariant,
1443
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: uiCore.cn("rounded-lg overflow-hidden", COVER_SIZES[coverSize]), children: renderCoverContent() })
1444
+ }
1445
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
1446
+ "div",
1447
+ {
1448
+ className: uiCore.cn(
1449
+ "rounded-lg overflow-hidden shadow-lg cursor-pointer",
1450
+ COVER_SIZES[coverSize]
1451
+ ),
1452
+ onClick: nextVariant,
1453
+ role: "button",
1454
+ tabIndex: 0,
1455
+ onKeyDown: (e) => e.key === "Enter" && nextVariant(),
1456
+ children: renderCoverContent()
1457
+ }
1458
+ ),
1459
+ reactiveCover && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] uppercase tracking-wider text-muted-foreground/50 select-none", children: vizSettings.variant === "none" ? "off" : vizSettings.variant })
1460
+ ] }),
1461
+ /* @__PURE__ */ jsxRuntime.jsxs(
1462
+ "div",
1463
+ {
1464
+ className: uiCore.cn("flex flex-col gap-3", isHorizontal ? "flex-1 min-w-0" : "w-full max-w-md"),
1465
+ children: [
1466
+ (title || artist) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: uiCore.cn("text-center", isHorizontal && "text-left"), children: [
1467
+ title && /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-base font-medium text-foreground truncate", children: title }),
1468
+ artist && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground truncate", children: artist })
1469
+ ] }),
1470
+ /* @__PURE__ */ jsxRuntime.jsx(
1471
+ HybridAudioPlayer,
1472
+ {
1473
+ showControls: true,
1474
+ showWaveform,
1475
+ waveformMode,
1476
+ waveformHeight,
1477
+ showTimer,
1478
+ showVolume,
1479
+ showLoop,
1480
+ className: "border-0 bg-transparent"
1481
+ }
1482
+ )
1483
+ ]
1484
+ }
1485
+ )
1486
+ ]
1487
+ }
1488
+ )
1489
+ }
1490
+ );
1491
+ }
1492
+ chunkWGEGR3DF_cjs.__name(HybridSimplePlayerContent, "HybridSimplePlayerContent");
1493
+
1494
+ exports.AudioReactiveCover = AudioReactiveCover;
1495
+ exports.COLOR_SCHEMES = COLOR_SCHEMES2;
1496
+ exports.COLOR_SCHEME_INFO = COLOR_SCHEME_INFO;
1497
+ exports.EFFECT_ANIMATIONS = EFFECT_ANIMATIONS;
1498
+ exports.GlowEffect = GlowEffect;
1499
+ exports.HybridAudioPlayer = HybridAudioPlayer;
1500
+ exports.HybridAudioProvider = HybridAudioProvider;
1501
+ exports.HybridSimplePlayer = HybridSimplePlayer;
1502
+ exports.HybridWaveform = HybridWaveform;
1503
+ exports.INTENSITY_CONFIG = INTENSITY_CONFIG;
1504
+ exports.INTENSITY_INFO = INTENSITY_INFO;
1505
+ exports.MeshEffect = MeshEffect;
1506
+ exports.OrbsEffect = OrbsEffect;
1507
+ exports.SpotlightEffect = SpotlightEffect;
1508
+ exports.VARIANT_INFO = VARIANT_INFO;
1509
+ exports.VisualizationProvider = VisualizationProvider;
1510
+ exports.calculateGlowLayers = calculateGlowLayers;
1511
+ exports.calculateMeshGradients = calculateMeshGradients;
1512
+ exports.calculateOrbs = calculateOrbs;
1513
+ exports.calculateSpotlight = calculateSpotlight;
1514
+ exports.formatTime = formatTime;
1515
+ exports.getColors = getColors;
1516
+ exports.getEffectConfig = getEffectConfig;
1517
+ exports.prepareEffectColors = prepareEffectColors;
1518
+ exports.useAudioVisualization = useAudioVisualization;
1519
+ exports.useHybridAudio = useHybridAudio;
1520
+ exports.useHybridAudioAnalysis = useHybridAudioAnalysis;
1521
+ exports.useHybridAudioContext = useHybridAudioContext;
1522
+ exports.useHybridAudioControls = useHybridAudioControls;
1523
+ exports.useHybridAudioLevels = useHybridAudioLevels;
1524
+ exports.useHybridAudioState = useHybridAudioState;
1525
+ exports.useHybridWebAudio = useHybridWebAudio;
1526
+ exports.useVisualization = useVisualization;
1527
+ //# sourceMappingURL=chunk-EVGWYASL.cjs.map
1528
+ //# sourceMappingURL=chunk-EVGWYASL.cjs.map