@neuctra/ui 0.2.8 → 0.2.10

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 (81) hide show
  1. package/dist/index.cjs.js +107 -138
  2. package/dist/index.cjs.js.map +1 -1
  3. package/dist/index.es.js +1555 -2367
  4. package/dist/index.es.js.map +1 -1
  5. package/dist/{components → types/components}/basic/Alert.d.ts +3 -2
  6. package/dist/{components → types/components}/basic/Avatar.d.ts +1 -0
  7. package/dist/{components → types/components}/basic/Badge.d.ts +1 -2
  8. package/dist/{components → types/components}/basic/Button.d.ts +2 -2
  9. package/dist/{components → types/components}/basic/Input.d.ts +1 -1
  10. package/dist/types/components/basic/Tabs.d.ts +76 -0
  11. package/dist/{components → types/components}/basic/Text.d.ts +25 -20
  12. package/dist/{index.d.ts → types/index.d.ts} +3 -7
  13. package/dist/ui.css +1 -1
  14. package/package.json +9 -2
  15. package/dist/components/basic/Tabs.d.ts +0 -47
  16. package/dist/src/components/basic/Accordation.js +0 -73
  17. package/dist/src/components/basic/Alert.js +0 -36
  18. package/dist/src/components/basic/AudioGallery.js +0 -425
  19. package/dist/src/components/basic/AudioPlayer.js +0 -130
  20. package/dist/src/components/basic/Avatar.js +0 -68
  21. package/dist/src/components/basic/Badge.js +0 -27
  22. package/dist/src/components/basic/Button.js +0 -25
  23. package/dist/src/components/basic/CheckboxGroup.js +0 -63
  24. package/dist/src/components/basic/Container.js +0 -26
  25. package/dist/src/components/basic/Drawer.js +0 -43
  26. package/dist/src/components/basic/DropDown.js +0 -98
  27. package/dist/src/components/basic/FlexView.js +0 -19
  28. package/dist/src/components/basic/GridView.js +0 -18
  29. package/dist/src/components/basic/Image.js +0 -55
  30. package/dist/src/components/basic/Input.js +0 -82
  31. package/dist/src/components/basic/List.js +0 -29
  32. package/dist/src/components/basic/Modal.js +0 -34
  33. package/dist/src/components/basic/RadioGroup.js +0 -54
  34. package/dist/src/components/basic/Stack.js +0 -22
  35. package/dist/src/components/basic/SwitchGroup.js +0 -76
  36. package/dist/src/components/basic/Table.js +0 -30
  37. package/dist/src/components/basic/Tabs.js +0 -140
  38. package/dist/src/components/basic/Text.js +0 -25
  39. package/dist/src/index.js +0 -44
  40. package/dist/types/src/components/basic/Accordation.d.ts +0 -40
  41. package/dist/types/src/components/basic/Alert.d.ts +0 -17
  42. package/dist/types/src/components/basic/AudioGallery.d.ts +0 -23
  43. package/dist/types/src/components/basic/AudioPlayer.d.ts +0 -16
  44. package/dist/types/src/components/basic/Avatar.d.ts +0 -23
  45. package/dist/types/src/components/basic/Badge.d.ts +0 -21
  46. package/dist/types/src/components/basic/Button.d.ts +0 -15
  47. package/dist/types/src/components/basic/CheckboxGroup.d.ts +0 -27
  48. package/dist/types/src/components/basic/Container.d.ts +0 -15
  49. package/dist/types/src/components/basic/Drawer.d.ts +0 -22
  50. package/dist/types/src/components/basic/DropDown.d.ts +0 -33
  51. package/dist/types/src/components/basic/FlexView.d.ts +0 -16
  52. package/dist/types/src/components/basic/GridView.d.ts +0 -14
  53. package/dist/types/src/components/basic/Image.d.ts +0 -37
  54. package/dist/types/src/components/basic/Input.d.ts +0 -33
  55. package/dist/types/src/components/basic/List.d.ts +0 -20
  56. package/dist/types/src/components/basic/Modal.d.ts +0 -17
  57. package/dist/types/src/components/basic/RadioGroup.d.ts +0 -26
  58. package/dist/types/src/components/basic/Stack.d.ts +0 -17
  59. package/dist/types/src/components/basic/SwitchGroup.d.ts +0 -26
  60. package/dist/types/src/components/basic/Table.d.ts +0 -28
  61. package/dist/types/src/components/basic/Tabs.d.ts +0 -47
  62. package/dist/types/src/components/basic/Text.d.ts +0 -1121
  63. package/dist/types/src/index.d.ts +0 -24
  64. package/dist/types/vite.config.d.ts +0 -2
  65. package/dist/vite.config.js +0 -34
  66. /package/dist/{components/basic/Accordation.d.ts → types/components/basic/Accordion.d.ts} +0 -0
  67. /package/dist/{components → types/components}/basic/AudioGallery.d.ts +0 -0
  68. /package/dist/{components → types/components}/basic/AudioPlayer.d.ts +0 -0
  69. /package/dist/{components → types/components}/basic/CheckboxGroup.d.ts +0 -0
  70. /package/dist/{components → types/components}/basic/Container.d.ts +0 -0
  71. /package/dist/{components → types/components}/basic/Drawer.d.ts +0 -0
  72. /package/dist/{components → types/components}/basic/DropDown.d.ts +0 -0
  73. /package/dist/{components → types/components}/basic/FlexView.d.ts +0 -0
  74. /package/dist/{components → types/components}/basic/GridView.d.ts +0 -0
  75. /package/dist/{components → types/components}/basic/Image.d.ts +0 -0
  76. /package/dist/{components → types/components}/basic/List.d.ts +0 -0
  77. /package/dist/{components → types/components}/basic/Modal.d.ts +0 -0
  78. /package/dist/{components → types/components}/basic/RadioGroup.d.ts +0 -0
  79. /package/dist/{components → types/components}/basic/Stack.d.ts +0 -0
  80. /package/dist/{components → types/components}/basic/SwitchGroup.d.ts +0 -0
  81. /package/dist/{components → types/components}/basic/Table.d.ts +0 -0
@@ -1,425 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useRef, useState, useEffect } from "react";
3
- import { Play, Pause, Volume2, VolumeX, RotateCcw, SkipBack, SkipForward, Heart, Music, Shuffle, } from "lucide-react";
4
- const defaultTracks = [
5
- {
6
- src: "https://www.soundjay.com/misc/sounds/bell-ringing-05.wav",
7
- title: "Morning Bell",
8
- artist: "Nature Sounds",
9
- duration: "0:15",
10
- thumbnail: "https://images.unsplash.com/photo-1493225457124-a3eb161ffa5f?w=300&h=300&fit=crop",
11
- },
12
- {
13
- src: "https://www.soundjay.com/buttons/sounds/button-4.wav",
14
- title: "Digital Click",
15
- artist: "Tech Audio",
16
- duration: "0:05",
17
- thumbnail: "https://images.unsplash.com/photo-1514525253161-7a46d19cd819?w=300&h=300&fit=crop",
18
- },
19
- {
20
- src: "https://www.soundjay.com/buttons/sounds/button-10.wav",
21
- title: "Soft Chime",
22
- artist: "Ambient Studio",
23
- duration: "0:08",
24
- thumbnail: "https://images.unsplash.com/photo-1493225457124-a3eb161ffa5f?w=300&h=300&fit=crop",
25
- },
26
- ];
27
- export function AudioGallery({ tracks = defaultTracks, className = "", galleryTitle = "Audio Gallery", primaryColor = "#8b5cf6", backgroundColor = "#0f0f23", textColor = "#e4e4e7", secondaryColor = "#1a1a2e", border = 0, borderColor, maxWidth = 420, autoplay = false, loop = false, }) {
28
- const [currentTrackIndex, setCurrentTrackIndex] = useState(null);
29
- const [isPlaying, setIsPlaying] = useState(false);
30
- const [currentTime, setCurrentTime] = useState(0);
31
- const [duration, setDuration] = useState(0);
32
- const [volume, setVolume] = useState(0.7);
33
- const [isFullscreen, setIsFullscreen] = useState(false);
34
- const [isLooping, setIsLooping] = useState(loop);
35
- const [isShuffle, setIsShuffle] = useState(false);
36
- const [isLiked, setIsLiked] = useState(false);
37
- const [showVolumeSlider, setShowVolumeSlider] = useState(false);
38
- const audioRef = useRef(null);
39
- const playerRef = useRef(null);
40
- const volumeTimeoutRef = useRef(null);
41
- useEffect(() => {
42
- if (audioRef.current) {
43
- audioRef.current.volume = volume;
44
- }
45
- }, [volume]);
46
- useEffect(() => {
47
- if (audioRef.current) {
48
- audioRef.current.loop = isLooping;
49
- }
50
- }, [isLooping]);
51
- useEffect(() => {
52
- if (currentTrackIndex === null && audioRef.current) {
53
- audioRef.current.pause();
54
- setIsPlaying(false);
55
- setCurrentTime(0);
56
- setDuration(0);
57
- }
58
- }, [currentTrackIndex]);
59
- const playPauseTrack = (index) => {
60
- if (currentTrackIndex === index) {
61
- if (!audioRef.current)
62
- return;
63
- if (audioRef.current.paused) {
64
- audioRef.current.play().catch(() => { });
65
- setIsPlaying(true);
66
- }
67
- else {
68
- audioRef.current.pause();
69
- setIsPlaying(false);
70
- }
71
- }
72
- else {
73
- setCurrentTrackIndex(index);
74
- setTimeout(() => {
75
- if (audioRef.current) {
76
- audioRef.current.play().catch(() => { });
77
- setIsPlaying(true);
78
- }
79
- }, 100);
80
- }
81
- };
82
- const handleTimeUpdate = () => {
83
- if (!audioRef.current)
84
- return;
85
- setCurrentTime(audioRef.current.currentTime);
86
- if (audioRef.current.duration) {
87
- setDuration(audioRef.current.duration);
88
- }
89
- };
90
- const handleSeek = (e) => {
91
- if (!audioRef.current || !duration)
92
- return;
93
- const rect = e.currentTarget.getBoundingClientRect();
94
- const clickPos = e.clientX - rect.left;
95
- const percent = clickPos / rect.width;
96
- const seekTime = percent * duration;
97
- audioRef.current.currentTime = seekTime;
98
- setCurrentTime(seekTime);
99
- };
100
- const handleVolumeChange = (e) => {
101
- const rect = e.currentTarget.getBoundingClientRect();
102
- const clickPos = e.clientX - rect.left;
103
- const percent = clickPos / rect.width;
104
- const newVolume = Math.max(0, Math.min(1, percent));
105
- setVolume(newVolume);
106
- };
107
- const skip = (seconds) => {
108
- if (audioRef.current && duration) {
109
- let newTime = audioRef.current.currentTime + seconds;
110
- newTime = Math.min(Math.max(newTime, 0), duration);
111
- audioRef.current.currentTime = newTime;
112
- setCurrentTime(newTime);
113
- }
114
- };
115
- const nextTrack = () => {
116
- if (currentTrackIndex === null)
117
- return;
118
- let nextIndex;
119
- if (isShuffle) {
120
- nextIndex = Math.floor(Math.random() * tracks.length);
121
- }
122
- else {
123
- nextIndex = (currentTrackIndex + 1) % tracks.length;
124
- }
125
- playPauseTrack(nextIndex);
126
- };
127
- const prevTrack = () => {
128
- if (currentTrackIndex === null)
129
- return;
130
- let prevIndex;
131
- if (isShuffle) {
132
- prevIndex = Math.floor(Math.random() * tracks.length);
133
- }
134
- else {
135
- prevIndex = (currentTrackIndex - 1 + tracks.length) % tracks.length;
136
- }
137
- playPauseTrack(prevIndex);
138
- };
139
- const toggleMute = () => {
140
- setVolume((prev) => (prev > 0 ? 0 : 0.7));
141
- };
142
- const showVolume = () => {
143
- setShowVolumeSlider(true);
144
- if (volumeTimeoutRef.current) {
145
- clearTimeout(volumeTimeoutRef.current);
146
- }
147
- volumeTimeoutRef.current = setTimeout(() => {
148
- setShowVolumeSlider(false);
149
- }, 3000);
150
- };
151
- const formatTime = (time) => {
152
- if (isNaN(time))
153
- return "0:00";
154
- const minutes = Math.floor(time / 60);
155
- const seconds = Math.floor(time % 60);
156
- return `${minutes}:${seconds < 10 ? "0" : ""}${seconds}`;
157
- };
158
- const currentTrack = currentTrackIndex !== null ? tracks[currentTrackIndex] : null;
159
- return (_jsxs("div", { className: className, style: {
160
- maxWidth: `${maxWidth}px`,
161
- margin: "20px auto",
162
- background: `linear-gradient(145deg, ${backgroundColor}, ${secondaryColor})`,
163
- color: textColor,
164
- borderRadius: "24px",
165
- padding: "24px 16px",
166
- fontFamily: "'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif",
167
- userSelect: "none",
168
- backdropFilter: "blur(20px)",
169
- border: `${border}px solid ${borderColor}40`,
170
- }, children: [_jsxs("div", { style: {
171
- display: "flex",
172
- alignItems: "center",
173
- justifyContent: "space-between",
174
- marginBottom: "24px",
175
- }, children: [_jsxs("div", { style: { display: "flex", alignItems: "center", gap: "12px" }, children: [_jsx("div", { style: {
176
- width: "40px",
177
- height: "40px",
178
- borderRadius: "12px",
179
- background: `linear-gradient(135deg, ${primaryColor}, ${secondaryColor})`,
180
- display: "flex",
181
- alignItems: "center",
182
- justifyContent: "center",
183
- }, children: _jsx(Music, { size: 20, color: "white" }) }), _jsxs("div", { children: [_jsx("h2", { style: {
184
- margin: 0,
185
- fontSize: "1.25rem",
186
- fontWeight: "700",
187
- color: primaryColor, // fallback for browsers without WebkitTextFillColor
188
- }, children: galleryTitle }), _jsxs("p", { style: { margin: 0, fontSize: "0.875rem", opacity: 0.7 }, children: [tracks.length, " tracks"] })] })] }), _jsx("button", { onClick: () => setIsShuffle(!isShuffle), style: {
189
- background: isShuffle ? primaryColor : "transparent",
190
- border: "none",
191
- borderRadius: "12px",
192
- padding: "8px",
193
- cursor: "pointer",
194
- transition: "all 0.3s ease",
195
- opacity: isShuffle ? 1 : 0.6,
196
- }, "aria-label": "Toggle Shuffle", children: _jsx(Shuffle, { size: 18, color: isShuffle ? "white" : textColor }) })] }), _jsx("div", { style: {
197
- display: "flex",
198
- flexDirection: "column",
199
- gap: "8px",
200
- marginBottom: "20px",
201
- maxHeight: "240px",
202
- overflowY: "auto",
203
- paddingRight: "4px",
204
- }, children: tracks.map((track, index) => {
205
- const isActive = currentTrackIndex === index;
206
- const isCurrentlyPlaying = isActive && isPlaying;
207
- return (_jsxs("div", { onClick: () => playPauseTrack(index), style: {
208
- display: "flex",
209
- alignItems: "center",
210
- padding: "12px 16px",
211
- borderRadius: "16px",
212
- background: isActive
213
- ? `linear-gradient(135deg, ${primaryColor}20, ${primaryColor}10)`
214
- : "rgba(255,255,255,0.05)",
215
- border: isActive
216
- ? `1px solid ${primaryColor}40`
217
- : "1px solid transparent",
218
- cursor: "pointer",
219
- transition: "all 0.3s ease",
220
- backdropFilter: isActive ? `blur(20px)` : "none",
221
- }, children: [_jsxs("div", { style: {
222
- width: "48px",
223
- height: "48px",
224
- borderRadius: "12px",
225
- background: track.thumbnail
226
- ? `url(${track.thumbnail}) center/cover`
227
- : primaryColor,
228
- display: "flex",
229
- alignItems: "center",
230
- justifyContent: "center",
231
- marginRight: "12px",
232
- position: "relative",
233
- overflow: "hidden",
234
- }, children: [!track.thumbnail && _jsx(Music, { size: 20, color: "white" }), isCurrentlyPlaying && (_jsx("div", { style: {
235
- position: "absolute",
236
- top: 0,
237
- left: 0,
238
- right: 0,
239
- bottom: 0,
240
- background: "rgba(0,0,0,0.6)",
241
- display: "flex",
242
- alignItems: "center",
243
- justifyContent: "center",
244
- }, children: _jsx("div", { style: {
245
- width: "16px",
246
- height: "16px",
247
- display: "flex",
248
- gap: "2px",
249
- alignItems: "end",
250
- justifyContent: "center",
251
- }, children: [0, 1, 2].map((i) => (_jsx("div", { style: {
252
- width: "3px",
253
- background: "white",
254
- borderRadius: "2px",
255
- animation: `equalizer 1s ease-in-out infinite ${i * 0.2}s`,
256
- height: "12px",
257
- } }, i))) }) }))] }), _jsxs("div", { style: { flex: 1, minWidth: 0 }, children: [_jsx("div", { style: {
258
- fontWeight: "600",
259
- fontSize: "0.95rem",
260
- color: isActive ? primaryColor : textColor,
261
- whiteSpace: "nowrap",
262
- overflow: "hidden",
263
- textOverflow: "ellipsis",
264
- }, children: track.title }), track.artist && (_jsx("div", { style: {
265
- fontSize: "0.8rem",
266
- opacity: 0.7,
267
- whiteSpace: "nowrap",
268
- overflow: "hidden",
269
- textOverflow: "ellipsis",
270
- }, children: track.artist }))] }), _jsxs("div", { style: { display: "flex", alignItems: "center", gap: "12px" }, children: [track.duration && (_jsx("span", { style: { fontSize: "0.8rem", opacity: 0.6 }, children: track.duration })), _jsx("div", { style: {
271
- width: "32px",
272
- height: "32px",
273
- borderRadius: "8px",
274
- background: isActive
275
- ? primaryColor
276
- : "rgba(255,255,255,0.1)",
277
- display: "flex",
278
- alignItems: "center",
279
- justifyContent: "center",
280
- transition: "all 0.3s ease",
281
- }, children: isCurrentlyPlaying ? (_jsx(Pause, { size: 16, color: "white" })) : (_jsx(Play, { size: 16, color: "white" })) })] })] }, index));
282
- }) }), currentTrack && (_jsxs("div", { ref: playerRef, style: {
283
- background: `linear-gradient(135deg, ${secondaryColor}, ${backgroundColor})`,
284
- borderRadius: "20px",
285
- padding: "20px",
286
- border: `1px solid ${primaryColor}40`,
287
- backdropFilter: "blur(20px)",
288
- position: "relative",
289
- overflow: "hidden",
290
- }, children: [currentTrack.thumbnail && (_jsx("div", { style: {
291
- position: "absolute",
292
- top: 0,
293
- left: 0,
294
- right: 0,
295
- bottom: 0,
296
- backgroundImage: `url(${currentTrack.thumbnail})`,
297
- backgroundSize: "cover",
298
- backgroundPosition: "center",
299
- filter: "blur(60px) opacity(0.1)",
300
- transform: "scale(1.1)",
301
- } })), _jsxs("div", { style: { position: "relative", zIndex: 1 }, children: [_jsxs("div", { style: { textAlign: "center", marginBottom: "20px" }, children: [_jsx("h3", { style: {
302
- margin: "0 0 4px 0",
303
- fontSize: "1.1rem",
304
- fontWeight: "700",
305
- color: primaryColor,
306
- }, children: currentTrack.title }), currentTrack.artist && (_jsx("p", { style: { margin: 0, opacity: 0.7, fontSize: "0.9rem" }, children: currentTrack.artist }))] }), _jsxs("div", { style: {
307
- display: "flex",
308
- alignItems: "center",
309
- justifyContent: "center",
310
- gap: "20px",
311
- marginBottom: "20px",
312
- }, children: [_jsx("button", { onClick: prevTrack, style: controlButtonStyle(textColor, "rgba(255,255,255,0.1)"), "aria-label": "Previous Track", children: _jsx(SkipBack, { size: 20 }) }), _jsxs("button", { onClick: () => skip(-10), style: controlButtonStyle(textColor, "rgba(255,255,255,0.1)"), "aria-label": "Skip back 10 seconds", children: [_jsx(SkipBack, { size: 16 }), _jsx("span", { style: { fontSize: "0.7rem", marginLeft: "2px" }, children: "10" })] }), _jsx("button", { onClick: () => {
313
- if (!audioRef.current)
314
- return;
315
- if (isPlaying) {
316
- audioRef.current.pause();
317
- setIsPlaying(false);
318
- }
319
- else {
320
- audioRef.current.play().catch(() => { });
321
- setIsPlaying(true);
322
- }
323
- }, style: {
324
- ...controlButtonStyle("#fff", primaryColor),
325
- width: "60px",
326
- height: "60px",
327
- borderRadius: "50%",
328
- boxShadow: `0 8px 25px ${primaryColor}40`,
329
- }, "aria-label": isPlaying ? "Pause" : "Play", children: isPlaying ? _jsx(Pause, { size: 24 }) : _jsx(Play, { size: 24 }) }), _jsxs("button", { onClick: () => skip(10), style: controlButtonStyle(textColor, "rgba(255,255,255,0.1)"), "aria-label": "Skip forward 10 seconds", children: [_jsx("span", { style: { fontSize: "0.7rem", marginRight: "2px" }, children: "10" }), _jsx(SkipForward, { size: 16 })] }), _jsx("button", { onClick: nextTrack, style: controlButtonStyle(textColor, "rgba(255,255,255,0.1)"), "aria-label": "Next Track", children: _jsx(SkipForward, { size: 20 }) })] }), _jsxs("div", { style: { marginBottom: "16px" }, children: [_jsxs("div", { style: {
330
- display: "flex",
331
- alignItems: "center",
332
- justifyContent: "space-between",
333
- marginBottom: "8px",
334
- fontSize: "0.8rem",
335
- opacity: 0.7,
336
- }, children: [_jsx("span", { children: formatTime(currentTime) }), _jsx("span", { children: formatTime(duration) })] }), _jsx("div", { onClick: handleSeek, style: {
337
- height: "6px",
338
- background: "rgba(255,255,255,0.2)",
339
- borderRadius: "3px",
340
- cursor: "pointer",
341
- position: "relative",
342
- overflow: "hidden",
343
- }, children: _jsx("div", { style: {
344
- width: `${(currentTime / duration) * 100 || 0}%`,
345
- height: "100%",
346
- background: `linear-gradient(90deg, ${primaryColor}, #ec4899)`,
347
- borderRadius: "3px",
348
- position: "relative",
349
- }, children: _jsx("div", { style: {
350
- position: "absolute",
351
- right: "-6px",
352
- top: "50%",
353
- transform: "translateY(-50%)",
354
- width: "12px",
355
- height: "12px",
356
- background: primaryColor,
357
- borderRadius: "50%",
358
- boxShadow: `0 2px 8px ${primaryColor}60`,
359
- } }) }) })] }), _jsxs("div", { style: {
360
- display: "flex",
361
- alignItems: "center",
362
- justifyContent: "space-between",
363
- }, children: [_jsxs("div", { style: { display: "flex", gap: "8px" }, children: [_jsx("button", { onClick: () => setIsLiked(!isLiked), style: controlButtonStyle(isLiked ? "#ec4899" : textColor, "rgba(255,255,255,0.1)"), "aria-label": "Like", children: _jsx(Heart, { size: 16, fill: isLiked ? "#ec4899" : "none" }) }), _jsx("button", { onClick: () => setIsLooping(!isLooping), style: controlButtonStyle(isLooping ? primaryColor : textColor, "rgba(255,255,255,0.1)"), "aria-label": "Toggle Loop", children: _jsx(RotateCcw, { size: 16 }) })] }), _jsxs("div", { style: {
364
- display: "flex",
365
- alignItems: "center",
366
- gap: "8px",
367
- position: "relative",
368
- }, children: [showVolumeSlider && (_jsx("div", { onClick: handleVolumeChange, style: {
369
- width: "80px",
370
- height: "4px",
371
- background: "rgba(255,255,255,0.2)",
372
- borderRadius: "2px",
373
- cursor: "pointer",
374
- position: "relative",
375
- }, children: _jsx("div", { style: {
376
- width: `${volume * 100}%`,
377
- height: "100%",
378
- background: primaryColor,
379
- borderRadius: "2px",
380
- } }) })), _jsx("button", { onClick: toggleMute, onMouseEnter: showVolume, style: controlButtonStyle(textColor, "rgba(255,255,255,0.1)"), "aria-label": volume > 0 ? "Mute" : "Unmute", children: volume > 0 ? _jsx(Volume2, { size: 16 }) : _jsx(VolumeX, { size: 16 }) })] })] })] }), _jsx("audio", { ref: audioRef, src: currentTrack.src, autoPlay: autoplay, loop: isLooping, onTimeUpdate: handleTimeUpdate, onEnded: () => {
381
- setIsPlaying(false);
382
- if (!isLooping) {
383
- nextTrack();
384
- }
385
- }, onLoadedMetadata: handleTimeUpdate, preload: "metadata", style: { display: "none" } })] })), _jsx("style", { children: `
386
- @keyframes equalizer {
387
- 0%, 100% { height: 4px; }
388
- 50% { height: 12px; }
389
- }
390
-
391
- /* Custom Scrollbar */
392
- div::-webkit-scrollbar {
393
- width: 4px;
394
- }
395
-
396
- div::-webkit-scrollbar-track {
397
- background: rgba(255,255,255,0.1);
398
- border-radius: 2px;
399
- }
400
-
401
- div::-webkit-scrollbar-thumb {
402
- background: ${primaryColor};
403
- border-radius: 2px;
404
- }
405
-
406
- div::-webkit-scrollbar-thumb:hover {
407
- background: ${primaryColor}dd;
408
- }
409
- ` })] }));
410
- }
411
- function controlButtonStyle(color, backgroundColor) {
412
- return {
413
- border: "none",
414
- backgroundColor,
415
- color,
416
- cursor: "pointer",
417
- padding: "10px",
418
- borderRadius: "12px",
419
- display: "flex",
420
- alignItems: "center",
421
- justifyContent: "center",
422
- transition: "all 0.3s ease",
423
- backdropFilter: "blur(10px)",
424
- };
425
- }
@@ -1,130 +0,0 @@
1
- "use client";
2
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { useRef, useState, useEffect } from "react";
4
- import { Play, Pause, Volume2, VolumeX, Maximize, Minimize, RotateCcw, SkipBack, SkipForward, } from "lucide-react";
5
- export const AudioPlayer = ({ src, thumbnail, autoPlay = false, loop = false, backgroundColor = "#0a0a0a", primaryColor = "#10b981", secondaryColor = "#ffffff", borderRadius = "12px", padding = "12px", width = "100%", className, }) => {
6
- const audioRef = useRef(null);
7
- const playerRef = useRef(null);
8
- const [isPlaying, setIsPlaying] = useState(autoPlay);
9
- const [currentTime, setCurrentTime] = useState(0);
10
- const [duration, setDuration] = useState(0);
11
- const [volume, setVolume] = useState(0.7);
12
- const [isFullscreen, setIsFullscreen] = useState(false);
13
- const [isLooping, setIsLooping] = useState(loop);
14
- useEffect(() => {
15
- if (audioRef.current)
16
- audioRef.current.volume = volume;
17
- }, [volume]);
18
- useEffect(() => {
19
- if (audioRef.current)
20
- audioRef.current.loop = isLooping;
21
- }, [isLooping]);
22
- const togglePlayPause = () => {
23
- if (!audioRef.current)
24
- return;
25
- isPlaying ? audioRef.current.pause() : audioRef.current.play();
26
- setIsPlaying(!isPlaying);
27
- };
28
- const handleTimeUpdate = () => {
29
- if (!audioRef.current)
30
- return;
31
- setCurrentTime(audioRef.current.currentTime);
32
- setDuration(audioRef.current.duration);
33
- };
34
- const handleSeek = (e) => {
35
- if (!audioRef.current)
36
- return;
37
- const rect = e.currentTarget.getBoundingClientRect();
38
- const percent = (e.clientX - rect.left) / rect.width;
39
- audioRef.current.currentTime = percent * duration;
40
- setCurrentTime(percent * duration);
41
- };
42
- const skip = (seconds) => {
43
- if (audioRef.current)
44
- audioRef.current.currentTime += seconds;
45
- };
46
- const toggleFullscreen = () => {
47
- if (!playerRef.current)
48
- return;
49
- isFullscreen
50
- ? document.exitFullscreen?.()
51
- : playerRef.current.requestFullscreen?.();
52
- setIsFullscreen(!isFullscreen);
53
- };
54
- const formatTime = (time) => {
55
- const minutes = Math.floor(time / 60);
56
- const seconds = Math.floor(time % 60);
57
- return `${minutes}:${seconds < 10 ? "0" : ""}${seconds}`;
58
- };
59
- return (_jsxs("div", { ref: playerRef, className: className, style: {
60
- display: "flex",
61
- alignItems: "center",
62
- gap: "12px",
63
- width,
64
- backgroundColor,
65
- borderRadius,
66
- padding,
67
- boxSizing: "border-box",
68
- color: secondaryColor,
69
- boxShadow: "0 6px 16px rgba(0,0,0,0.2)",
70
- flexWrap: "wrap",
71
- }, children: [_jsx("audio", { ref: audioRef, src: src, autoPlay: autoPlay, loop: loop, onTimeUpdate: handleTimeUpdate, onLoadedMetadata: handleTimeUpdate }), thumbnail && (_jsx("img", { src: thumbnail, alt: "Audio Thumbnail", style: {
72
- width: "60px",
73
- height: "60px",
74
- borderRadius: "50%",
75
- objectFit: "cover",
76
- flexShrink: 0,
77
- } })), _jsxs("div", { style: {
78
- display: "flex",
79
- alignItems: "center",
80
- gap: "12px",
81
- flex: 1,
82
- minWidth: "0",
83
- }, children: [_jsx("button", { onClick: () => skip(-10), style: {
84
- background: "transparent",
85
- border: "none",
86
- color: secondaryColor,
87
- cursor: "pointer",
88
- }, "aria-label": "Skip Back 10s", children: _jsx(SkipBack, { size: 20 }) }), _jsx("button", { onClick: togglePlayPause, style: {
89
- background: primaryColor,
90
- borderRadius: "50%",
91
- padding: "10px",
92
- border: "none",
93
- cursor: "pointer",
94
- display: "flex",
95
- alignItems: "center",
96
- justifyContent: "center",
97
- }, "aria-label": isPlaying ? "Pause" : "Play", children: isPlaying ? _jsx(Pause, { size: 20 }) : _jsx(Play, { size: 20 }) }), _jsx("button", { onClick: () => skip(10), style: {
98
- background: "transparent",
99
- border: "none",
100
- color: secondaryColor,
101
- cursor: "pointer",
102
- }, "aria-label": "Skip Forward 10s", children: _jsx(SkipForward, { size: 20 }) }), _jsx("div", { onClick: handleSeek, style: {
103
- flex: 1,
104
- height: "6px",
105
- background: "#444",
106
- borderRadius: "3px",
107
- cursor: "pointer",
108
- position: "relative",
109
- }, children: _jsx("div", { style: {
110
- width: `${(currentTime / duration) * 100 || 0}%`,
111
- height: "100%",
112
- background: primaryColor,
113
- borderRadius: "3px",
114
- } }) }), _jsxs("div", { style: { minWidth: "70px", textAlign: "right", fontSize: "0.8rem" }, children: [formatTime(currentTime), " / ", formatTime(duration)] }), _jsxs("div", { style: { display: "flex", alignItems: "center", gap: "8px" }, children: [_jsx("button", { onClick: () => setIsLooping(!isLooping), style: {
115
- background: "transparent",
116
- border: "none",
117
- cursor: "pointer",
118
- color: isLooping ? primaryColor : secondaryColor,
119
- }, "aria-label": "Toggle Loop", children: _jsx(RotateCcw, { size: 18 }) }), _jsx("button", { onClick: () => setVolume(volume > 0 ? 0 : 0.7), style: {
120
- background: "transparent",
121
- border: "none",
122
- cursor: "pointer",
123
- color: secondaryColor,
124
- }, "aria-label": "Toggle Mute", children: volume > 0 ? _jsx(Volume2, { size: 18 }) : _jsx(VolumeX, { size: 18 }) }), _jsx("button", { onClick: toggleFullscreen, style: {
125
- background: "transparent",
126
- border: "none",
127
- cursor: "pointer",
128
- color: secondaryColor,
129
- }, "aria-label": "Toggle Fullscreen", children: isFullscreen ? _jsx(Minimize, { size: 18 }) : _jsx(Maximize, { size: 18 }) })] })] })] }));
130
- };
@@ -1,68 +0,0 @@
1
- "use client";
2
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { useState } from "react";
4
- import { User } from "lucide-react";
5
- // --- Base maps ---
6
- const sizeMap = {
7
- xs: 24,
8
- sm: 32,
9
- md: 40,
10
- lg: 48,
11
- xl: 56,
12
- "2xl": 64,
13
- };
14
- const fontSizeMap = {
15
- xs: "text-[10px]",
16
- sm: "text-[12px]",
17
- md: "text-[14px]",
18
- lg: "text-[16px]",
19
- xl: "text-[18px]",
20
- "2xl": "text-[20px]",
21
- };
22
- const dimensionMap = {
23
- xs: "w-6 h-6",
24
- sm: "w-8 h-8",
25
- md: "w-10 h-10",
26
- lg: "w-12 h-12",
27
- xl: "w-14 h-14",
28
- "2xl": "w-16 h-16",
29
- };
30
- const variantMap = {
31
- circular: "rounded-full",
32
- rounded: "rounded-lg",
33
- square: "rounded-none",
34
- };
35
- const statusPositionMap = {
36
- "top-left": "top-0 left-0",
37
- "top-right": "top-0 right-0",
38
- "bottom-left": "bottom-0 left-0",
39
- "bottom-right": "bottom-0 right-0",
40
- };
41
- // --- Avatar Component ---
42
- export const Avatar = ({ src, alt = "User avatar", size = "md", variant = "circular", isOnline = false, isOffline = false, fallback, ring = false, ringColor = "#3b82f6", onClick, statusPosition = "bottom-right", className = "", statusClassName = "", style, statusStyle, }) => {
43
- const [imageError, setImageError] = useState(false);
44
- const clickable = !!onClick;
45
- const initials = fallback ||
46
- alt
47
- .split(" ")
48
- .map((n) => n[0])
49
- .join("")
50
- .toUpperCase()
51
- .slice(0, 2);
52
- const statusColor = isOnline ? "bg-green-500" : isOffline ? "bg-gray-400" : "";
53
- // Width/height for inline styles
54
- const dimensionPx = sizeMap[size];
55
- return (_jsxs("div", { role: clickable ? "button" : "img", tabIndex: clickable ? 0 : -1, "aria-label": alt, onClick: onClick, className: `relative inline-flex items-center justify-center overflow-hidden ${dimensionMap[size]} ${variantMap[variant]} transition-all duration-200 ${clickable ? "cursor-pointer hover:scale-105" : ""} ${ring ? "ring-2" : ""} ${className}`, style: {
56
- ...style,
57
- ...(ring ? { boxShadow: `0 0 0 2px ${ringColor}` } : {}),
58
- }, onKeyDown: (e) => {
59
- if (clickable && (e.key === "Enter" || e.key === " ")) {
60
- e.preventDefault();
61
- onClick?.();
62
- }
63
- }, children: [src && !imageError ? (_jsx("img", { src: src, alt: alt, onError: () => setImageError(true), className: `w-full h-full object-cover ${variantMap[variant]} transition-opacity duration-300` })) : (_jsx("div", { className: `w-full h-full flex items-center justify-center bg-gradient-to-tr from-purple-500 to-blue-500 text-white font-semibold ${fontSizeMap[size]} ${variantMap[variant]}`, children: initials || _jsx(User, { className: "text-white" }) })), (isOnline || isOffline) && (_jsx("span", { "aria-label": isOnline ? "Online" : "Offline", title: isOnline ? "Online" : "Offline", className: `absolute ${statusPositionMap[statusPosition]} ${statusColor} border-2 border-white rounded-full shadow-sm ${statusClassName}`, style: {
64
- width: dimensionPx / 3,
65
- height: dimensionPx / 3,
66
- ...statusStyle,
67
- } }))] }));
68
- };
@@ -1,27 +0,0 @@
1
- "use client";
2
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { memo } from "react";
4
- import clsx from "clsx";
5
- /* -------------------------------------------------------------------------- */
6
- /* 🏷 Badge */
7
- /* -------------------------------------------------------------------------- */
8
- export const Badge = memo(({ text, icon, iconPosition = "left", primaryTheme = true, primaryColor = "#3b82f6", size = "md", rounded = true, notificationDot = false, dotColor = "#ef4444", count, pulse = false, className, onClick, }) => {
9
- /** 📏 Sizes */
10
- const sizes = {
11
- sm: "px-2 py-0.5 text-xs",
12
- md: "px-3 py-1 text-xs",
13
- lg: "px-4 py-1.5 text-sm",
14
- };
15
- /** 🎨 Theme */
16
- const themeClasses = primaryTheme
17
- ? "bg-[var(--primary)] text-white"
18
- : "";
19
- const dynamicStyle = !primaryTheme
20
- ? {
21
- backgroundColor: primaryColor,
22
- color: "#fff",
23
- }
24
- : {};
25
- return (_jsxs("span", { onClick: onClick, style: !primaryTheme ? dynamicStyle : undefined, className: clsx("relative inline-flex items-center justify-center gap-1 font-medium", "transition-all duration-200 select-none", rounded ? "rounded-full" : "rounded-md", sizes[size], themeClasses, onClick && "cursor-pointer hover:opacity-90", className), children: [notificationDot && (_jsx("span", { style: !primaryTheme ? { backgroundColor: dotColor } : undefined, className: clsx("absolute -top-1 -right-1 w-2 h-2 rounded-full", pulse && "animate-ping", primaryTheme ? "bg-red-500" : "") })), count !== undefined && (_jsx("span", { style: !primaryTheme ? { backgroundColor: dotColor } : undefined, className: clsx("absolute -top-2 -right-2 min-w-[18px] h-[18px] px-1 text-[10px]", "flex items-center justify-center rounded-full text-white", primaryTheme ? "bg-red-500" : ""), children: count })), icon && iconPosition === "left" && (_jsx("span", { className: "flex items-center", children: icon })), text && _jsx("span", { children: text }), icon && iconPosition === "right" && (_jsx("span", { className: "flex items-center", children: icon }))] }));
26
- });
27
- Badge.displayName = "Badge";