@stargate91/pill-player 0.1.0

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.
@@ -0,0 +1,249 @@
1
+ import * as react from 'react';
2
+ import { ReactNode, SVGProps } from 'react';
3
+
4
+ interface AudioTrack {
5
+ id: string;
6
+ title: string;
7
+ code?: string;
8
+ artist?: string;
9
+ genre?: string;
10
+ bpm?: number | string;
11
+ duration?: string;
12
+ src?: string;
13
+ soundcloud?: string;
14
+ youtube?: string;
15
+ feed?: string;
16
+ externalUrl?: string;
17
+ }
18
+ type PillTheme = "orbital" | "stargate" | "cyberpunk" | "matrix" | "synthwave" | "amber" | "nordic" | "minimal";
19
+ type PillPosition = "bottom-right" | "bottom-left" | "top-right" | "top-left" | "inline";
20
+ interface PillColors {
21
+ accent?: string;
22
+ secondary?: string;
23
+ bg?: string;
24
+ surface?: string;
25
+ border?: string;
26
+ text?: string;
27
+ textDim?: string;
28
+ glow?: string;
29
+ }
30
+ type EmbedMode = "seamless" | "themed" | "widget";
31
+ type MixcloudEmbedMode = EmbedMode;
32
+ interface PillIcons {
33
+ play?: ReactNode;
34
+ pause?: ReactNode;
35
+ prev?: ReactNode;
36
+ next?: ReactNode;
37
+ mute?: ReactNode;
38
+ unmute?: ReactNode;
39
+ close?: ReactNode;
40
+ external?: ReactNode;
41
+ }
42
+ interface PillLabels {
43
+ badge: string;
44
+ openPlayer: string;
45
+ closePlayer: string;
46
+ play: string;
47
+ pause: string;
48
+ prevTrack: string;
49
+ nextTrack: string;
50
+ mute: string;
51
+ unmute: string;
52
+ directPlayHint: string;
53
+ listenExternal: string;
54
+ selectTrack: string;
55
+ frequenciesActive: string;
56
+ frequenciesStandby: string;
57
+ spectrumHeader: string;
58
+ spectrumDsp: string;
59
+ subtitle: string;
60
+ }
61
+ interface PillFeatures {
62
+ showSpectrum?: boolean;
63
+ showSeekbar?: boolean;
64
+ showPlaylist?: boolean;
65
+ persistState?: boolean;
66
+ enableKeyboardShortcuts?: boolean;
67
+ embedMode?: EmbedMode;
68
+ mixcloudEmbedMode?: MixcloudEmbedMode;
69
+ beaconGlow?: boolean;
70
+ }
71
+ interface PillPlayerProps {
72
+ tracks: AudioTrack[] | string;
73
+ theme?: PillTheme;
74
+ colors?: PillColors;
75
+ position?: PillPosition;
76
+ icons?: PillIcons;
77
+ labels?: Partial<PillLabels>;
78
+ features?: PillFeatures;
79
+ initialOpen?: boolean;
80
+ className?: string;
81
+ style?: React.CSSProperties;
82
+ onTrackChange?: (track: AudioTrack, index: number) => void;
83
+ onPlayStateChange?: (isPlaying: boolean) => void;
84
+ }
85
+ declare const DEFAULT_PILL_LABELS: PillLabels;
86
+
87
+ declare function PillPlayer({ tracks, theme, colors, position, icons, labels: customLabels, features, initialOpen, className, style, onTrackChange, onPlayStateChange, }: PillPlayerProps): react.JSX.Element;
88
+
89
+ interface AudioTriggerPillProps {
90
+ isOpen: boolean;
91
+ isPlaying: boolean;
92
+ currentTrack?: AudioTrack;
93
+ labels: PillLabels;
94
+ icons?: PillIcons;
95
+ onToggleOpen: () => void;
96
+ }
97
+ declare function AudioTriggerPill({ isOpen, isPlaying, currentTrack, labels, icons, onToggleOpen, }: AudioTriggerPillProps): react.JSX.Element;
98
+
99
+ interface SpectrumVisualizerProps {
100
+ isPlaying: boolean;
101
+ labels: PillLabels;
102
+ frequencyData?: number[];
103
+ hasLiveFrequency?: boolean;
104
+ }
105
+ declare function SpectrumVisualizer({ isPlaying, labels, frequencyData, hasLiveFrequency, }: SpectrumVisualizerProps): react.JSX.Element;
106
+
107
+ interface AudioPlaylistProps {
108
+ tracks: AudioTrack[];
109
+ currentTrackIndex: number;
110
+ labels: PillLabels;
111
+ onSelectTrack: (index: number) => void;
112
+ }
113
+ declare function AudioPlaylist({ tracks, currentTrackIndex, labels, onSelectTrack, }: AudioPlaylistProps): react.JSX.Element;
114
+
115
+ interface AudioSeekbarProps {
116
+ currentTime: number;
117
+ duration: number;
118
+ onSeek: (timeInSeconds: number) => void;
119
+ }
120
+ declare function AudioSeekbar({ currentTime, duration, onSeek, }: AudioSeekbarProps): react.JSX.Element;
121
+
122
+ interface PlayerHeaderProps {
123
+ labels: PillLabels;
124
+ icons?: PillIcons;
125
+ onClose: () => void;
126
+ }
127
+ declare function PlayerHeader({ labels, icons, onClose }: PlayerHeaderProps): react.JSX.Element;
128
+
129
+ interface TrackInfoProps {
130
+ currentTrack?: AudioTrack;
131
+ labels: PillLabels;
132
+ }
133
+ declare function TrackInfo({ currentTrack, labels }: TrackInfoProps): react.JSX.Element;
134
+
135
+ interface PlayerControlsProps {
136
+ isPlaying: boolean;
137
+ isMuted: boolean;
138
+ externalLinkUrl?: string;
139
+ labels: PillLabels;
140
+ icons?: PillIcons;
141
+ onPrev: () => void;
142
+ onTogglePlay: () => void;
143
+ onNext: () => void;
144
+ onToggleMute: () => void;
145
+ }
146
+ declare function PlayerControls({ isPlaying, isMuted, externalLinkUrl, labels, icons, onPrev, onTogglePlay, onNext, onToggleMute, }: PlayerControlsProps): react.JSX.Element;
147
+
148
+ interface ProviderEmbedsProps {
149
+ isLoaded: boolean;
150
+ embedMode: EmbedMode;
151
+ currentTrack?: AudioTrack;
152
+ labels: PillLabels;
153
+ isSoundCloud: boolean;
154
+ soundCloudIframeSrc: string;
155
+ scIframeRef: any;
156
+ onSoundCloudLoad: () => void;
157
+ isYouTube: boolean;
158
+ youTubeIframeSrc: string;
159
+ ytIframeRef: any;
160
+ onYouTubeLoad: () => void;
161
+ iframeSrc: string;
162
+ iframeRef: any;
163
+ onMixcloudLoad: () => void;
164
+ }
165
+ declare function ProviderEmbeds({ isLoaded, embedMode, currentTrack, labels, isSoundCloud, soundCloudIframeSrc, scIframeRef, onSoundCloudLoad, isYouTube, youTubeIframeSrc, ytIframeRef, onYouTubeLoad, iframeSrc, iframeRef, onMixcloudLoad, }: ProviderEmbedsProps): react.JSX.Element | null;
166
+
167
+ interface IconProps extends SVGProps<SVGSVGElement> {
168
+ size?: number | string;
169
+ }
170
+ declare function PlayIcon({ size, ...props }: IconProps): react.JSX.Element;
171
+ declare function PauseIcon({ size, ...props }: IconProps): react.JSX.Element;
172
+ declare function SkipBackIcon({ size, ...props }: IconProps): react.JSX.Element;
173
+ declare function SkipForwardIcon({ size, ...props }: IconProps): react.JSX.Element;
174
+ declare function VolumeMuteIcon({ size, ...props }: IconProps): react.JSX.Element;
175
+ declare function VolumeUpIcon({ size, ...props }: IconProps): react.JSX.Element;
176
+ declare function CloseIcon({ size, ...props }: IconProps): react.JSX.Element;
177
+ declare function ExternalLinkIcon({ size, ...props }: IconProps): react.JSX.Element;
178
+
179
+ /**
180
+ * Extracts 11-character YouTube video ID from various URL formats or returns the ID if already clean.
181
+ */
182
+ declare function extractYouTubeId(urlOrId?: string): string | null;
183
+
184
+ interface UseAudioPlayerOptions {
185
+ tracks: AudioTrack[];
186
+ persistState?: boolean;
187
+ onTrackChange?: (track: AudioTrack, index: number) => void;
188
+ onPlayStateChange?: (isPlaying: boolean) => void;
189
+ }
190
+ declare function useAudioPlayer({ tracks, persistState, onTrackChange, onPlayStateChange, }: UseAudioPlayerOptions): {
191
+ tracks: AudioTrack[];
192
+ currentTrack: AudioTrack;
193
+ currentTrackIndex: number;
194
+ isPlaying: boolean;
195
+ isMuted: boolean;
196
+ isLoaded: boolean;
197
+ currentTime: number;
198
+ duration: number;
199
+ handleSeek: (seconds: number) => void;
200
+ iframeRef: react.MutableRefObject<HTMLIFrameElement | null>;
201
+ scIframeRef: react.MutableRefObject<HTMLIFrameElement | null>;
202
+ soundCloudIframeSrc: string;
203
+ isSoundCloud: boolean;
204
+ isYouTube: boolean;
205
+ ytIframeRef: react.MutableRefObject<HTMLIFrameElement | null>;
206
+ youTubeIframeSrc: string;
207
+ setupYouTubePlayer: () => void;
208
+ isHtmlAudio: boolean;
209
+ isMixcloud: boolean;
210
+ setupSoundCloudWidget: () => void;
211
+ iframeSrc: string;
212
+ frequencyData: number[];
213
+ hasLiveFrequency: boolean;
214
+ timing: {
215
+ numericBpm: number;
216
+ beatMs: number;
217
+ halfBeatMs: number;
218
+ twoBeatsMs: number;
219
+ barMs: number;
220
+ };
221
+ setIsLoaded: react.Dispatch<react.SetStateAction<boolean>>;
222
+ handleTogglePlay: () => void;
223
+ handleToggleMute: () => void;
224
+ handleNextTrack: () => void;
225
+ handlePrevTrack: () => void;
226
+ handleSelectTrack: (index: number) => void;
227
+ setupMixcloudWidget: () => void;
228
+ };
229
+
230
+ /**
231
+ * Formats seconds into mm:ss or hh:mm:ss string.
232
+ */
233
+ declare function formatTime(totalSeconds: number): string;
234
+ /**
235
+ * Parses duration strings like "3:45", "30 min", or number of seconds.
236
+ */
237
+ declare function parseDurationToSeconds(duration?: string): number;
238
+ /**
239
+ * Calculates beat, half-beat, two-beats, and bar timings in milliseconds from BPM.
240
+ */
241
+ declare function calculateBpmTiming(bpm?: number | string): {
242
+ numericBpm: number;
243
+ beatMs: number;
244
+ halfBeatMs: number;
245
+ twoBeatsMs: number;
246
+ barMs: number;
247
+ };
248
+
249
+ export { AudioPlaylist, AudioSeekbar, type AudioTrack, AudioTriggerPill, CloseIcon, DEFAULT_PILL_LABELS, type EmbedMode, ExternalLinkIcon, type IconProps, type MixcloudEmbedMode, PauseIcon, type PillColors, type PillFeatures, type PillIcons, type PillLabels, PillPlayer, type PillPlayerProps, type PillPosition, type PillTheme, PlayIcon, PlayerControls, PlayerHeader, ProviderEmbeds, SkipBackIcon, SkipForwardIcon, SpectrumVisualizer, TrackInfo, VolumeMuteIcon, VolumeUpIcon, calculateBpmTiming, extractYouTubeId, formatTime, parseDurationToSeconds, useAudioPlayer };
@@ -0,0 +1,249 @@
1
+ import * as react from 'react';
2
+ import { ReactNode, SVGProps } from 'react';
3
+
4
+ interface AudioTrack {
5
+ id: string;
6
+ title: string;
7
+ code?: string;
8
+ artist?: string;
9
+ genre?: string;
10
+ bpm?: number | string;
11
+ duration?: string;
12
+ src?: string;
13
+ soundcloud?: string;
14
+ youtube?: string;
15
+ feed?: string;
16
+ externalUrl?: string;
17
+ }
18
+ type PillTheme = "orbital" | "stargate" | "cyberpunk" | "matrix" | "synthwave" | "amber" | "nordic" | "minimal";
19
+ type PillPosition = "bottom-right" | "bottom-left" | "top-right" | "top-left" | "inline";
20
+ interface PillColors {
21
+ accent?: string;
22
+ secondary?: string;
23
+ bg?: string;
24
+ surface?: string;
25
+ border?: string;
26
+ text?: string;
27
+ textDim?: string;
28
+ glow?: string;
29
+ }
30
+ type EmbedMode = "seamless" | "themed" | "widget";
31
+ type MixcloudEmbedMode = EmbedMode;
32
+ interface PillIcons {
33
+ play?: ReactNode;
34
+ pause?: ReactNode;
35
+ prev?: ReactNode;
36
+ next?: ReactNode;
37
+ mute?: ReactNode;
38
+ unmute?: ReactNode;
39
+ close?: ReactNode;
40
+ external?: ReactNode;
41
+ }
42
+ interface PillLabels {
43
+ badge: string;
44
+ openPlayer: string;
45
+ closePlayer: string;
46
+ play: string;
47
+ pause: string;
48
+ prevTrack: string;
49
+ nextTrack: string;
50
+ mute: string;
51
+ unmute: string;
52
+ directPlayHint: string;
53
+ listenExternal: string;
54
+ selectTrack: string;
55
+ frequenciesActive: string;
56
+ frequenciesStandby: string;
57
+ spectrumHeader: string;
58
+ spectrumDsp: string;
59
+ subtitle: string;
60
+ }
61
+ interface PillFeatures {
62
+ showSpectrum?: boolean;
63
+ showSeekbar?: boolean;
64
+ showPlaylist?: boolean;
65
+ persistState?: boolean;
66
+ enableKeyboardShortcuts?: boolean;
67
+ embedMode?: EmbedMode;
68
+ mixcloudEmbedMode?: MixcloudEmbedMode;
69
+ beaconGlow?: boolean;
70
+ }
71
+ interface PillPlayerProps {
72
+ tracks: AudioTrack[] | string;
73
+ theme?: PillTheme;
74
+ colors?: PillColors;
75
+ position?: PillPosition;
76
+ icons?: PillIcons;
77
+ labels?: Partial<PillLabels>;
78
+ features?: PillFeatures;
79
+ initialOpen?: boolean;
80
+ className?: string;
81
+ style?: React.CSSProperties;
82
+ onTrackChange?: (track: AudioTrack, index: number) => void;
83
+ onPlayStateChange?: (isPlaying: boolean) => void;
84
+ }
85
+ declare const DEFAULT_PILL_LABELS: PillLabels;
86
+
87
+ declare function PillPlayer({ tracks, theme, colors, position, icons, labels: customLabels, features, initialOpen, className, style, onTrackChange, onPlayStateChange, }: PillPlayerProps): react.JSX.Element;
88
+
89
+ interface AudioTriggerPillProps {
90
+ isOpen: boolean;
91
+ isPlaying: boolean;
92
+ currentTrack?: AudioTrack;
93
+ labels: PillLabels;
94
+ icons?: PillIcons;
95
+ onToggleOpen: () => void;
96
+ }
97
+ declare function AudioTriggerPill({ isOpen, isPlaying, currentTrack, labels, icons, onToggleOpen, }: AudioTriggerPillProps): react.JSX.Element;
98
+
99
+ interface SpectrumVisualizerProps {
100
+ isPlaying: boolean;
101
+ labels: PillLabels;
102
+ frequencyData?: number[];
103
+ hasLiveFrequency?: boolean;
104
+ }
105
+ declare function SpectrumVisualizer({ isPlaying, labels, frequencyData, hasLiveFrequency, }: SpectrumVisualizerProps): react.JSX.Element;
106
+
107
+ interface AudioPlaylistProps {
108
+ tracks: AudioTrack[];
109
+ currentTrackIndex: number;
110
+ labels: PillLabels;
111
+ onSelectTrack: (index: number) => void;
112
+ }
113
+ declare function AudioPlaylist({ tracks, currentTrackIndex, labels, onSelectTrack, }: AudioPlaylistProps): react.JSX.Element;
114
+
115
+ interface AudioSeekbarProps {
116
+ currentTime: number;
117
+ duration: number;
118
+ onSeek: (timeInSeconds: number) => void;
119
+ }
120
+ declare function AudioSeekbar({ currentTime, duration, onSeek, }: AudioSeekbarProps): react.JSX.Element;
121
+
122
+ interface PlayerHeaderProps {
123
+ labels: PillLabels;
124
+ icons?: PillIcons;
125
+ onClose: () => void;
126
+ }
127
+ declare function PlayerHeader({ labels, icons, onClose }: PlayerHeaderProps): react.JSX.Element;
128
+
129
+ interface TrackInfoProps {
130
+ currentTrack?: AudioTrack;
131
+ labels: PillLabels;
132
+ }
133
+ declare function TrackInfo({ currentTrack, labels }: TrackInfoProps): react.JSX.Element;
134
+
135
+ interface PlayerControlsProps {
136
+ isPlaying: boolean;
137
+ isMuted: boolean;
138
+ externalLinkUrl?: string;
139
+ labels: PillLabels;
140
+ icons?: PillIcons;
141
+ onPrev: () => void;
142
+ onTogglePlay: () => void;
143
+ onNext: () => void;
144
+ onToggleMute: () => void;
145
+ }
146
+ declare function PlayerControls({ isPlaying, isMuted, externalLinkUrl, labels, icons, onPrev, onTogglePlay, onNext, onToggleMute, }: PlayerControlsProps): react.JSX.Element;
147
+
148
+ interface ProviderEmbedsProps {
149
+ isLoaded: boolean;
150
+ embedMode: EmbedMode;
151
+ currentTrack?: AudioTrack;
152
+ labels: PillLabels;
153
+ isSoundCloud: boolean;
154
+ soundCloudIframeSrc: string;
155
+ scIframeRef: any;
156
+ onSoundCloudLoad: () => void;
157
+ isYouTube: boolean;
158
+ youTubeIframeSrc: string;
159
+ ytIframeRef: any;
160
+ onYouTubeLoad: () => void;
161
+ iframeSrc: string;
162
+ iframeRef: any;
163
+ onMixcloudLoad: () => void;
164
+ }
165
+ declare function ProviderEmbeds({ isLoaded, embedMode, currentTrack, labels, isSoundCloud, soundCloudIframeSrc, scIframeRef, onSoundCloudLoad, isYouTube, youTubeIframeSrc, ytIframeRef, onYouTubeLoad, iframeSrc, iframeRef, onMixcloudLoad, }: ProviderEmbedsProps): react.JSX.Element | null;
166
+
167
+ interface IconProps extends SVGProps<SVGSVGElement> {
168
+ size?: number | string;
169
+ }
170
+ declare function PlayIcon({ size, ...props }: IconProps): react.JSX.Element;
171
+ declare function PauseIcon({ size, ...props }: IconProps): react.JSX.Element;
172
+ declare function SkipBackIcon({ size, ...props }: IconProps): react.JSX.Element;
173
+ declare function SkipForwardIcon({ size, ...props }: IconProps): react.JSX.Element;
174
+ declare function VolumeMuteIcon({ size, ...props }: IconProps): react.JSX.Element;
175
+ declare function VolumeUpIcon({ size, ...props }: IconProps): react.JSX.Element;
176
+ declare function CloseIcon({ size, ...props }: IconProps): react.JSX.Element;
177
+ declare function ExternalLinkIcon({ size, ...props }: IconProps): react.JSX.Element;
178
+
179
+ /**
180
+ * Extracts 11-character YouTube video ID from various URL formats or returns the ID if already clean.
181
+ */
182
+ declare function extractYouTubeId(urlOrId?: string): string | null;
183
+
184
+ interface UseAudioPlayerOptions {
185
+ tracks: AudioTrack[];
186
+ persistState?: boolean;
187
+ onTrackChange?: (track: AudioTrack, index: number) => void;
188
+ onPlayStateChange?: (isPlaying: boolean) => void;
189
+ }
190
+ declare function useAudioPlayer({ tracks, persistState, onTrackChange, onPlayStateChange, }: UseAudioPlayerOptions): {
191
+ tracks: AudioTrack[];
192
+ currentTrack: AudioTrack;
193
+ currentTrackIndex: number;
194
+ isPlaying: boolean;
195
+ isMuted: boolean;
196
+ isLoaded: boolean;
197
+ currentTime: number;
198
+ duration: number;
199
+ handleSeek: (seconds: number) => void;
200
+ iframeRef: react.MutableRefObject<HTMLIFrameElement | null>;
201
+ scIframeRef: react.MutableRefObject<HTMLIFrameElement | null>;
202
+ soundCloudIframeSrc: string;
203
+ isSoundCloud: boolean;
204
+ isYouTube: boolean;
205
+ ytIframeRef: react.MutableRefObject<HTMLIFrameElement | null>;
206
+ youTubeIframeSrc: string;
207
+ setupYouTubePlayer: () => void;
208
+ isHtmlAudio: boolean;
209
+ isMixcloud: boolean;
210
+ setupSoundCloudWidget: () => void;
211
+ iframeSrc: string;
212
+ frequencyData: number[];
213
+ hasLiveFrequency: boolean;
214
+ timing: {
215
+ numericBpm: number;
216
+ beatMs: number;
217
+ halfBeatMs: number;
218
+ twoBeatsMs: number;
219
+ barMs: number;
220
+ };
221
+ setIsLoaded: react.Dispatch<react.SetStateAction<boolean>>;
222
+ handleTogglePlay: () => void;
223
+ handleToggleMute: () => void;
224
+ handleNextTrack: () => void;
225
+ handlePrevTrack: () => void;
226
+ handleSelectTrack: (index: number) => void;
227
+ setupMixcloudWidget: () => void;
228
+ };
229
+
230
+ /**
231
+ * Formats seconds into mm:ss or hh:mm:ss string.
232
+ */
233
+ declare function formatTime(totalSeconds: number): string;
234
+ /**
235
+ * Parses duration strings like "3:45", "30 min", or number of seconds.
236
+ */
237
+ declare function parseDurationToSeconds(duration?: string): number;
238
+ /**
239
+ * Calculates beat, half-beat, two-beats, and bar timings in milliseconds from BPM.
240
+ */
241
+ declare function calculateBpmTiming(bpm?: number | string): {
242
+ numericBpm: number;
243
+ beatMs: number;
244
+ halfBeatMs: number;
245
+ twoBeatsMs: number;
246
+ barMs: number;
247
+ };
248
+
249
+ export { AudioPlaylist, AudioSeekbar, type AudioTrack, AudioTriggerPill, CloseIcon, DEFAULT_PILL_LABELS, type EmbedMode, ExternalLinkIcon, type IconProps, type MixcloudEmbedMode, PauseIcon, type PillColors, type PillFeatures, type PillIcons, type PillLabels, PillPlayer, type PillPlayerProps, type PillPosition, type PillTheme, PlayIcon, PlayerControls, PlayerHeader, ProviderEmbeds, SkipBackIcon, SkipForwardIcon, SpectrumVisualizer, TrackInfo, VolumeMuteIcon, VolumeUpIcon, calculateBpmTiming, extractYouTubeId, formatTime, parseDurationToSeconds, useAudioPlayer };