soundcloud-widget-react 1.0.1

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.
package/README.md ADDED
@@ -0,0 +1,153 @@
1
+ # soundcloud-widget-react
2
+
3
+ React component library that wraps the [SoundCloud HTML5 Widget API](https://developers.soundcloud.com/docs/api/html5-widget) with full TypeScript support.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install soundcloud-widget-react
9
+ # or
10
+ pnpm add soundcloud-widget-react
11
+ # or
12
+ yarn add soundcloud-widget-react
13
+ ```
14
+
15
+ Peer dependencies: `react` and `react-dom` >= 17.
16
+
17
+ ## Basic Usage
18
+
19
+ ```tsx
20
+ import { SCWidget } from "soundcloud-widget-react";
21
+
22
+ export default function App() {
23
+ return (
24
+ <SCWidget
25
+ url="https://soundcloud.com/artist/track"
26
+ autoPlay={false}
27
+ showArtwork={true}
28
+ onReady={() => console.log("Widget ready")}
29
+ onPlay={(e) => console.log("Playing at", e.currentPosition)}
30
+ onFinish={() => console.log("Track finished")}
31
+ />
32
+ );
33
+ }
34
+ ```
35
+
36
+ ## Ref Usage
37
+
38
+ Access the player programmatically via a ref:
39
+
40
+ ```tsx
41
+ import { useRef } from "react";
42
+ import { SCWidget, SCWidgetRef } from "soundcloud-widget-react";
43
+
44
+ export default function Player() {
45
+ const playerRef = useRef<SCWidgetRef>(null);
46
+
47
+ const handlePlay = () => playerRef.current?.play();
48
+ const handleSeek = () => playerRef.current?.seekTo(30000); // 30 seconds
49
+
50
+ const handleGetDuration = () => {
51
+ playerRef.current?.getDuration((duration) => {
52
+ console.log("Duration (ms):", duration);
53
+ });
54
+ };
55
+
56
+ return (
57
+ <>
58
+ <SCWidget
59
+ ref={playerRef}
60
+ url="https://soundcloud.com/artist/track"
61
+ height={166}
62
+ />
63
+ <button onClick={handlePlay}>Play</button>
64
+ <button onClick={handleSeek}>Seek to 0:30</button>
65
+ <button onClick={handleGetDuration}>Log Duration</button>
66
+ </>
67
+ );
68
+ }
69
+ ```
70
+
71
+ ## Props
72
+
73
+ | Prop | Type | Default | Description |
74
+ |------|------|---------|-------------|
75
+ | `url` | `string` | **required** | SoundCloud track, playlist, or user URL |
76
+ | `width` | `string \| number` | `"100%"` | iframe width |
77
+ | `height` | `string \| number` | `166` | iframe height |
78
+ | `style` | `CSSProperties` | — | Inline styles for the iframe |
79
+ | `className` | `string` | — | CSS class for the iframe |
80
+ | `iframeId` | `string` | auto-generated | `id` attribute for the iframe |
81
+ | `autoPlay` | `boolean` | — | Start playing automatically |
82
+ | `color` | `string` | — | Player color (hex, e.g. `"ff5500"`) |
83
+ | `buying` | `boolean` | — | Show buy button |
84
+ | `sharing` | `boolean` | — | Show share button |
85
+ | `download` | `boolean` | — | Show download button |
86
+ | `showArtwork` | `boolean` | — | Show artwork |
87
+ | `showPlaycount` | `boolean` | — | Show play count |
88
+ | `showUser` | `boolean` | — | Show user info |
89
+ | `startTrack` | `number` | — | Index of track to start on (for playlists) |
90
+ | `singleActive` | `boolean` | — | Pause other widgets when this one plays |
91
+ | `showTeaser` | `boolean` | — | Show teaser |
92
+ | `onReady` | `() => void` | — | Fired when widget is ready |
93
+ | `onPlay` | `(e: SCAudioEventPayload) => void` | — | Fired on play |
94
+ | `onPause` | `(e: SCAudioEventPayload) => void` | — | Fired on pause |
95
+ | `onFinish` | `(e: SCAudioEventPayload) => void` | — | Fired when track finishes |
96
+ | `onSeek` | `(e: SCAudioEventPayload) => void` | — | Fired on seek |
97
+ | `onPlayProgress` | `(e: SCAudioEventPayload) => void` | — | Fired during playback progress |
98
+ | `onLoadProgress` | `(e: SCAudioEventPayload) => void` | — | Fired during load progress |
99
+ | `onError` | `() => void` | — | Fired on error |
100
+ | `onClickDownload` | `() => void` | — | Fired when download button clicked |
101
+ | `onClickBuy` | `() => void` | — | Fired when buy button clicked |
102
+ | `onOpenSharePanel` | `() => void` | — | Fired when share panel opens |
103
+
104
+ ### SCAudioEventPayload
105
+
106
+ ```ts
107
+ interface SCAudioEventPayload {
108
+ relativePosition: number; // 0–1
109
+ loadProgress: number; // 0–1
110
+ currentPosition: number; // milliseconds
111
+ }
112
+ ```
113
+
114
+ ## Ref Methods
115
+
116
+ Attach a `ref` to `<SCWidget>` and call these methods imperatively:
117
+
118
+ | Method | Description |
119
+ |--------|-------------|
120
+ | `play()` | Start playback |
121
+ | `pause()` | Pause playback |
122
+ | `toggle()` | Toggle play/pause |
123
+ | `seekTo(ms: number)` | Seek to position in milliseconds |
124
+ | `setVolume(volume: number)` | Set volume (0–1) |
125
+ | `next()` | Skip to next track (playlist) |
126
+ | `prev()` | Go to previous track (playlist) |
127
+ | `skip(index: number)` | Jump to track at index (playlist) |
128
+ | `load(url, options?)` | Load a new URL; options may include any `SCWidgetParams` plus `callback` |
129
+ | `getVolume(cb)` | Async get current volume |
130
+ | `getDuration(cb)` | Async get track duration in ms |
131
+ | `getPosition(cb)` | Async get current position in ms |
132
+ | `getSounds(cb)` | Async get all sounds in playlist |
133
+ | `getCurrentSound(cb)` | Async get currently playing sound |
134
+ | `getCurrentSoundIndex(cb)` | Async get index of current sound |
135
+ | `isPaused(cb)` | Async check if paused |
136
+
137
+ ## SSR Note
138
+
139
+ This component is **client-only**. It uses an `<iframe>` and communicates via `postMessage`, neither of which are available in server-side rendering environments. When using Next.js or similar frameworks, import it with dynamic loading and `ssr: false`:
140
+
141
+ ```tsx
142
+ // Next.js example
143
+ import dynamic from "next/dynamic";
144
+
145
+ const SCWidget = dynamic(
146
+ () => import("soundcloud-widget-react").then((m) => m.SCWidget),
147
+ { ssr: false }
148
+ );
149
+ ```
150
+
151
+ ## License
152
+
153
+ MIT
@@ -0,0 +1,103 @@
1
+ import React, { CSSProperties } from 'react';
2
+
3
+ interface SCWidgetParams {
4
+ autoPlay?: boolean;
5
+ color?: string;
6
+ buying?: boolean;
7
+ sharing?: boolean;
8
+ download?: boolean;
9
+ showArtwork?: boolean;
10
+ showPlaycount?: boolean;
11
+ showUser?: boolean;
12
+ startTrack?: number;
13
+ singleActive?: boolean;
14
+ showTeaser?: boolean;
15
+ }
16
+ interface SCAudioEventPayload {
17
+ relativePosition: number;
18
+ loadProgress: number;
19
+ currentPosition: number;
20
+ }
21
+ interface SCSound {
22
+ id: number;
23
+ title: string;
24
+ permalink_url: string;
25
+ artwork_url: string | null;
26
+ user: {
27
+ username: string;
28
+ permalink_url: string;
29
+ };
30
+ duration: number;
31
+ }
32
+ interface SCWidgetInstance {
33
+ bind(eventName: string, listener: (e?: SCAudioEventPayload) => void): void;
34
+ unbind(eventName: string): void;
35
+ load(url: string, options?: Partial<SCWidgetParams> & {
36
+ callback?: () => void;
37
+ }): void;
38
+ play(): void;
39
+ pause(): void;
40
+ toggle(): void;
41
+ seekTo(milliseconds: number): void;
42
+ setVolume(volume: number): void;
43
+ next(): void;
44
+ prev(): void;
45
+ skip(soundIndex: number): void;
46
+ getVolume(callback: (volume: number) => void): void;
47
+ getDuration(callback: (duration: number) => void): void;
48
+ getPosition(callback: (position: number) => void): void;
49
+ getSounds(callback: (sounds: SCSound[]) => void): void;
50
+ getCurrentSound(callback: (sound: SCSound) => void): void;
51
+ getCurrentSoundIndex(callback: (index: number) => void): void;
52
+ isPaused(callback: (paused: boolean) => void): void;
53
+ }
54
+ interface SCWidgetRef {
55
+ play(): void;
56
+ pause(): void;
57
+ toggle(): void;
58
+ seekTo(milliseconds: number): void;
59
+ setVolume(volume: number): void;
60
+ next(): void;
61
+ prev(): void;
62
+ skip(soundIndex: number): void;
63
+ load(url: string, options?: Partial<SCWidgetParams> & {
64
+ callback?: () => void;
65
+ }): void;
66
+ getVolume(callback: (volume: number) => void): void;
67
+ getDuration(callback: (duration: number) => void): void;
68
+ getPosition(callback: (position: number) => void): void;
69
+ getSounds(callback: (sounds: SCSound[]) => void): void;
70
+ getCurrentSound(callback: (sound: SCSound) => void): void;
71
+ getCurrentSoundIndex(callback: (index: number) => void): void;
72
+ isPaused(callback: (paused: boolean) => void): void;
73
+ }
74
+ interface SCWidgetProps extends SCWidgetParams {
75
+ url: string;
76
+ width?: string | number;
77
+ height?: string | number;
78
+ style?: CSSProperties;
79
+ className?: string;
80
+ iframeId?: string;
81
+ onReady?: () => void;
82
+ onPlay?: (e: SCAudioEventPayload) => void;
83
+ onPause?: (e: SCAudioEventPayload) => void;
84
+ onFinish?: (e: SCAudioEventPayload) => void;
85
+ onSeek?: (e: SCAudioEventPayload) => void;
86
+ onPlayProgress?: (e: SCAudioEventPayload) => void;
87
+ onLoadProgress?: (e: SCAudioEventPayload) => void;
88
+ onError?: () => void;
89
+ onClickDownload?: () => void;
90
+ onClickBuy?: () => void;
91
+ onOpenSharePanel?: () => void;
92
+ }
93
+
94
+ declare global {
95
+ interface Window {
96
+ SC: {
97
+ Widget: (iframe: HTMLIFrameElement) => SCWidgetInstance;
98
+ };
99
+ }
100
+ }
101
+ declare const SCWidget: React.ForwardRefExoticComponent<SCWidgetProps & React.RefAttributes<SCWidgetRef>>;
102
+
103
+ export { type SCAudioEventPayload, type SCSound, SCWidget, type SCWidgetInstance, type SCWidgetParams, type SCWidgetProps, type SCWidgetRef, SCWidget as default };
@@ -0,0 +1,103 @@
1
+ import React, { CSSProperties } from 'react';
2
+
3
+ interface SCWidgetParams {
4
+ autoPlay?: boolean;
5
+ color?: string;
6
+ buying?: boolean;
7
+ sharing?: boolean;
8
+ download?: boolean;
9
+ showArtwork?: boolean;
10
+ showPlaycount?: boolean;
11
+ showUser?: boolean;
12
+ startTrack?: number;
13
+ singleActive?: boolean;
14
+ showTeaser?: boolean;
15
+ }
16
+ interface SCAudioEventPayload {
17
+ relativePosition: number;
18
+ loadProgress: number;
19
+ currentPosition: number;
20
+ }
21
+ interface SCSound {
22
+ id: number;
23
+ title: string;
24
+ permalink_url: string;
25
+ artwork_url: string | null;
26
+ user: {
27
+ username: string;
28
+ permalink_url: string;
29
+ };
30
+ duration: number;
31
+ }
32
+ interface SCWidgetInstance {
33
+ bind(eventName: string, listener: (e?: SCAudioEventPayload) => void): void;
34
+ unbind(eventName: string): void;
35
+ load(url: string, options?: Partial<SCWidgetParams> & {
36
+ callback?: () => void;
37
+ }): void;
38
+ play(): void;
39
+ pause(): void;
40
+ toggle(): void;
41
+ seekTo(milliseconds: number): void;
42
+ setVolume(volume: number): void;
43
+ next(): void;
44
+ prev(): void;
45
+ skip(soundIndex: number): void;
46
+ getVolume(callback: (volume: number) => void): void;
47
+ getDuration(callback: (duration: number) => void): void;
48
+ getPosition(callback: (position: number) => void): void;
49
+ getSounds(callback: (sounds: SCSound[]) => void): void;
50
+ getCurrentSound(callback: (sound: SCSound) => void): void;
51
+ getCurrentSoundIndex(callback: (index: number) => void): void;
52
+ isPaused(callback: (paused: boolean) => void): void;
53
+ }
54
+ interface SCWidgetRef {
55
+ play(): void;
56
+ pause(): void;
57
+ toggle(): void;
58
+ seekTo(milliseconds: number): void;
59
+ setVolume(volume: number): void;
60
+ next(): void;
61
+ prev(): void;
62
+ skip(soundIndex: number): void;
63
+ load(url: string, options?: Partial<SCWidgetParams> & {
64
+ callback?: () => void;
65
+ }): void;
66
+ getVolume(callback: (volume: number) => void): void;
67
+ getDuration(callback: (duration: number) => void): void;
68
+ getPosition(callback: (position: number) => void): void;
69
+ getSounds(callback: (sounds: SCSound[]) => void): void;
70
+ getCurrentSound(callback: (sound: SCSound) => void): void;
71
+ getCurrentSoundIndex(callback: (index: number) => void): void;
72
+ isPaused(callback: (paused: boolean) => void): void;
73
+ }
74
+ interface SCWidgetProps extends SCWidgetParams {
75
+ url: string;
76
+ width?: string | number;
77
+ height?: string | number;
78
+ style?: CSSProperties;
79
+ className?: string;
80
+ iframeId?: string;
81
+ onReady?: () => void;
82
+ onPlay?: (e: SCAudioEventPayload) => void;
83
+ onPause?: (e: SCAudioEventPayload) => void;
84
+ onFinish?: (e: SCAudioEventPayload) => void;
85
+ onSeek?: (e: SCAudioEventPayload) => void;
86
+ onPlayProgress?: (e: SCAudioEventPayload) => void;
87
+ onLoadProgress?: (e: SCAudioEventPayload) => void;
88
+ onError?: () => void;
89
+ onClickDownload?: () => void;
90
+ onClickBuy?: () => void;
91
+ onOpenSharePanel?: () => void;
92
+ }
93
+
94
+ declare global {
95
+ interface Window {
96
+ SC: {
97
+ Widget: (iframe: HTMLIFrameElement) => SCWidgetInstance;
98
+ };
99
+ }
100
+ }
101
+ declare const SCWidget: React.ForwardRefExoticComponent<SCWidgetProps & React.RefAttributes<SCWidgetRef>>;
102
+
103
+ export { type SCAudioEventPayload, type SCSound, SCWidget, type SCWidgetInstance, type SCWidgetParams, type SCWidgetProps, type SCWidgetRef, SCWidget as default };
package/dist/index.js ADDED
@@ -0,0 +1,357 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var react = require('react');
6
+ var jsxRuntime = require('react/jsx-runtime');
7
+
8
+ var __defProp = Object.defineProperty;
9
+ var __defProps = Object.defineProperties;
10
+ var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
11
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
12
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
13
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
14
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
15
+ var __spreadValues = (a, b) => {
16
+ for (var prop in b || (b = {}))
17
+ if (__hasOwnProp.call(b, prop))
18
+ __defNormalProp(a, prop, b[prop]);
19
+ if (__getOwnPropSymbols)
20
+ for (var prop of __getOwnPropSymbols(b)) {
21
+ if (__propIsEnum.call(b, prop))
22
+ __defNormalProp(a, prop, b[prop]);
23
+ }
24
+ return a;
25
+ };
26
+ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
27
+ var __objRest = (source, exclude) => {
28
+ var target = {};
29
+ for (var prop in source)
30
+ if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
31
+ target[prop] = source[prop];
32
+ if (source != null && __getOwnPropSymbols)
33
+ for (var prop of __getOwnPropSymbols(source)) {
34
+ if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
35
+ target[prop] = source[prop];
36
+ }
37
+ return target;
38
+ };
39
+ var SC_API_URL = "https://w.soundcloud.com/player/api.js";
40
+ var scriptPromise = null;
41
+ function loadScript() {
42
+ if (scriptPromise) return scriptPromise;
43
+ scriptPromise = new Promise((resolve, reject) => {
44
+ const script = document.createElement("script");
45
+ script.src = SC_API_URL;
46
+ script.async = true;
47
+ script.onload = () => resolve();
48
+ script.onerror = () => {
49
+ scriptPromise = null;
50
+ reject(new Error("Failed to load SoundCloud Widget API"));
51
+ };
52
+ document.head.appendChild(script);
53
+ });
54
+ return scriptPromise;
55
+ }
56
+ function useScript() {
57
+ const [loaded, setLoaded] = react.useState(false);
58
+ react.useEffect(() => {
59
+ if (typeof window === "undefined") return;
60
+ loadScript().then(() => setLoaded(true)).catch((err) => console.error(err));
61
+ }, []);
62
+ return { loaded };
63
+ }
64
+ var PARAM_MAP = [
65
+ ["autoPlay", "auto_play"],
66
+ ["color", "color"],
67
+ ["buying", "buying"],
68
+ ["sharing", "sharing"],
69
+ ["download", "download"],
70
+ ["showArtwork", "show_artwork"],
71
+ ["showPlaycount", "show_playcount"],
72
+ ["showUser", "show_user"],
73
+ ["startTrack", "start_track"],
74
+ ["singleActive", "single_active"],
75
+ ["showTeaser", "show_teaser"]
76
+ ];
77
+ function buildIframeSrc(url, params) {
78
+ const search = new URLSearchParams();
79
+ search.set("url", encodeURIComponent(url));
80
+ for (const [prop, urlKey] of PARAM_MAP) {
81
+ const value = params[prop];
82
+ if (value !== void 0) {
83
+ search.set(urlKey, String(value));
84
+ }
85
+ }
86
+ return `https://w.soundcloud.com/player/?${search.toString()}`;
87
+ }
88
+ function extractParams(props) {
89
+ return {
90
+ autoPlay: props.autoPlay,
91
+ color: props.color,
92
+ buying: props.buying,
93
+ sharing: props.sharing,
94
+ download: props.download,
95
+ showArtwork: props.showArtwork,
96
+ showPlaycount: props.showPlaycount,
97
+ showUser: props.showUser,
98
+ startTrack: props.startTrack,
99
+ singleActive: props.singleActive,
100
+ showTeaser: props.showTeaser
101
+ };
102
+ }
103
+ var SCWidget = react.forwardRef(
104
+ function SCWidget2(props, ref) {
105
+ const _a = props, {
106
+ url,
107
+ width = "100%",
108
+ height = 166,
109
+ style,
110
+ className,
111
+ iframeId,
112
+ onReady,
113
+ onPlay,
114
+ onPause,
115
+ onFinish,
116
+ onSeek,
117
+ onPlayProgress,
118
+ onLoadProgress,
119
+ onError,
120
+ onClickDownload,
121
+ onClickBuy,
122
+ onOpenSharePanel
123
+ } = _a, params = __objRest(_a, [
124
+ "url",
125
+ "width",
126
+ "height",
127
+ "style",
128
+ "className",
129
+ "iframeId",
130
+ "onReady",
131
+ "onPlay",
132
+ "onPause",
133
+ "onFinish",
134
+ "onSeek",
135
+ "onPlayProgress",
136
+ "onLoadProgress",
137
+ "onError",
138
+ "onClickDownload",
139
+ "onClickBuy",
140
+ "onOpenSharePanel"
141
+ ]);
142
+ const { loaded } = useScript();
143
+ const iframeRef = react.useRef(null);
144
+ const widgetRef = react.useRef(null);
145
+ const initializedRef = react.useRef(false);
146
+ const generatedId = react.useId();
147
+ const frameId = iframeId != null ? iframeId : `sc-widget-${generatedId}`;
148
+ const callbacksRef = react.useRef({
149
+ onReady,
150
+ onPlay,
151
+ onPause,
152
+ onFinish,
153
+ onSeek,
154
+ onPlayProgress,
155
+ onLoadProgress,
156
+ onError,
157
+ onClickDownload,
158
+ onClickBuy,
159
+ onOpenSharePanel
160
+ });
161
+ react.useEffect(() => {
162
+ callbacksRef.current = {
163
+ onReady,
164
+ onPlay,
165
+ onPause,
166
+ onFinish,
167
+ onSeek,
168
+ onPlayProgress,
169
+ onLoadProgress,
170
+ onError,
171
+ onClickDownload,
172
+ onClickBuy,
173
+ onOpenSharePanel
174
+ };
175
+ });
176
+ react.useEffect(() => {
177
+ if (!loaded || !iframeRef.current || initializedRef.current) return;
178
+ const widget = window.SC.Widget(iframeRef.current);
179
+ widgetRef.current = widget;
180
+ initializedRef.current = true;
181
+ const handlers = [
182
+ ["ready", () => {
183
+ var _a2, _b;
184
+ return (_b = (_a2 = callbacksRef.current).onReady) == null ? void 0 : _b.call(_a2);
185
+ }],
186
+ ["play", (e) => {
187
+ var _a2, _b;
188
+ return (_b = (_a2 = callbacksRef.current).onPlay) == null ? void 0 : _b.call(_a2, e);
189
+ }],
190
+ ["pause", (e) => {
191
+ var _a2, _b;
192
+ return (_b = (_a2 = callbacksRef.current).onPause) == null ? void 0 : _b.call(_a2, e);
193
+ }],
194
+ ["finish", (e) => {
195
+ var _a2, _b;
196
+ return (_b = (_a2 = callbacksRef.current).onFinish) == null ? void 0 : _b.call(_a2, e);
197
+ }],
198
+ ["seek", (e) => {
199
+ var _a2, _b;
200
+ return (_b = (_a2 = callbacksRef.current).onSeek) == null ? void 0 : _b.call(_a2, e);
201
+ }],
202
+ ["play_progress", (e) => {
203
+ var _a2, _b;
204
+ return (_b = (_a2 = callbacksRef.current).onPlayProgress) == null ? void 0 : _b.call(_a2, e);
205
+ }],
206
+ ["load_progress", (e) => {
207
+ var _a2, _b;
208
+ return (_b = (_a2 = callbacksRef.current).onLoadProgress) == null ? void 0 : _b.call(_a2, e);
209
+ }],
210
+ ["error", () => {
211
+ var _a2, _b;
212
+ return (_b = (_a2 = callbacksRef.current).onError) == null ? void 0 : _b.call(_a2);
213
+ }],
214
+ ["click_download", () => {
215
+ var _a2, _b;
216
+ return (_b = (_a2 = callbacksRef.current).onClickDownload) == null ? void 0 : _b.call(_a2);
217
+ }],
218
+ ["click_buy", () => {
219
+ var _a2, _b;
220
+ return (_b = (_a2 = callbacksRef.current).onClickBuy) == null ? void 0 : _b.call(_a2);
221
+ }],
222
+ ["open_share_panel", () => {
223
+ var _a2, _b;
224
+ return (_b = (_a2 = callbacksRef.current).onOpenSharePanel) == null ? void 0 : _b.call(_a2);
225
+ }]
226
+ ];
227
+ for (const [event, handler] of handlers) {
228
+ widget.bind(event, handler);
229
+ }
230
+ return () => {
231
+ for (const [event] of handlers) {
232
+ widget.unbind(event);
233
+ }
234
+ widgetRef.current = null;
235
+ initializedRef.current = false;
236
+ };
237
+ }, [loaded]);
238
+ const isFirstRender = react.useRef(true);
239
+ const prevUrl = react.useRef(url);
240
+ const prevParams = react.useRef(params);
241
+ react.useEffect(() => {
242
+ if (isFirstRender.current) {
243
+ isFirstRender.current = false;
244
+ prevUrl.current = url;
245
+ prevParams.current = params;
246
+ return;
247
+ }
248
+ if (!widgetRef.current) return;
249
+ prevUrl.current = url;
250
+ prevParams.current = params;
251
+ widgetRef.current.load(url, __spreadProps(__spreadValues({}, params), {
252
+ callback: callbacksRef.current.onReady
253
+ }));
254
+ }, [
255
+ url,
256
+ params.autoPlay,
257
+ params.color,
258
+ params.buying,
259
+ params.sharing,
260
+ params.download,
261
+ params.showArtwork,
262
+ params.showPlaycount,
263
+ params.showUser,
264
+ params.startTrack,
265
+ params.singleActive,
266
+ params.showTeaser
267
+ ]);
268
+ react.useImperativeHandle(ref, () => ({
269
+ play: () => {
270
+ var _a2;
271
+ return (_a2 = widgetRef.current) == null ? void 0 : _a2.play();
272
+ },
273
+ pause: () => {
274
+ var _a2;
275
+ return (_a2 = widgetRef.current) == null ? void 0 : _a2.pause();
276
+ },
277
+ toggle: () => {
278
+ var _a2;
279
+ return (_a2 = widgetRef.current) == null ? void 0 : _a2.toggle();
280
+ },
281
+ seekTo: (ms) => {
282
+ var _a2;
283
+ return (_a2 = widgetRef.current) == null ? void 0 : _a2.seekTo(ms);
284
+ },
285
+ setVolume: (vol) => {
286
+ var _a2;
287
+ return (_a2 = widgetRef.current) == null ? void 0 : _a2.setVolume(vol);
288
+ },
289
+ next: () => {
290
+ var _a2;
291
+ return (_a2 = widgetRef.current) == null ? void 0 : _a2.next();
292
+ },
293
+ prev: () => {
294
+ var _a2;
295
+ return (_a2 = widgetRef.current) == null ? void 0 : _a2.prev();
296
+ },
297
+ skip: (idx) => {
298
+ var _a2;
299
+ return (_a2 = widgetRef.current) == null ? void 0 : _a2.skip(idx);
300
+ },
301
+ load: (u, opts) => {
302
+ var _a2;
303
+ return (_a2 = widgetRef.current) == null ? void 0 : _a2.load(u, opts);
304
+ },
305
+ getVolume: (cb) => {
306
+ var _a2, _b;
307
+ return (_b = (_a2 = widgetRef.current) == null ? void 0 : _a2.getVolume(cb)) != null ? _b : cb(0);
308
+ },
309
+ getDuration: (cb) => {
310
+ var _a2, _b;
311
+ return (_b = (_a2 = widgetRef.current) == null ? void 0 : _a2.getDuration(cb)) != null ? _b : cb(0);
312
+ },
313
+ getPosition: (cb) => {
314
+ var _a2, _b;
315
+ return (_b = (_a2 = widgetRef.current) == null ? void 0 : _a2.getPosition(cb)) != null ? _b : cb(0);
316
+ },
317
+ getSounds: (cb) => {
318
+ var _a2, _b;
319
+ return (_b = (_a2 = widgetRef.current) == null ? void 0 : _a2.getSounds(cb)) != null ? _b : cb([]);
320
+ },
321
+ getCurrentSound: (cb) => {
322
+ var _a2;
323
+ return (_a2 = widgetRef.current) == null ? void 0 : _a2.getCurrentSound(cb);
324
+ },
325
+ getCurrentSoundIndex: (cb) => {
326
+ var _a2, _b;
327
+ return (_b = (_a2 = widgetRef.current) == null ? void 0 : _a2.getCurrentSoundIndex(cb)) != null ? _b : cb(0);
328
+ },
329
+ isPaused: (cb) => {
330
+ var _a2, _b;
331
+ return (_b = (_a2 = widgetRef.current) == null ? void 0 : _a2.isPaused(cb)) != null ? _b : cb(true);
332
+ }
333
+ }));
334
+ const src = buildIframeSrc(url, extractParams(props));
335
+ return /* @__PURE__ */ jsxRuntime.jsx(
336
+ "iframe",
337
+ {
338
+ ref: iframeRef,
339
+ id: frameId,
340
+ src,
341
+ width,
342
+ height,
343
+ style,
344
+ className,
345
+ scrolling: "no",
346
+ frameBorder: "no",
347
+ allow: "autoplay"
348
+ }
349
+ );
350
+ }
351
+ );
352
+ SCWidget.displayName = "SCWidget";
353
+
354
+ exports.SCWidget = SCWidget;
355
+ exports.default = SCWidget;
356
+ //# sourceMappingURL=index.js.map
357
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/useScript.ts","../src/SCWidget.tsx"],"names":["useState","useEffect","forwardRef","SCWidget","useRef","useId","_a","useImperativeHandle","jsx"],"mappings":"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","file":"index.js","sourcesContent":["import { useState, useEffect } from \"react\";\n\nconst SC_API_URL = \"https://w.soundcloud.com/player/api.js\";\n\nlet scriptPromise: Promise<void> | null = null;\n\nfunction loadScript(): Promise<void> {\n if (scriptPromise) return scriptPromise;\n\n scriptPromise = new Promise<void>((resolve, reject) => {\n const script = document.createElement(\"script\");\n script.src = SC_API_URL;\n script.async = true;\n script.onload = () => resolve();\n script.onerror = () => {\n scriptPromise = null;\n reject(new Error(\"Failed to load SoundCloud Widget API\"));\n };\n document.head.appendChild(script);\n });\n\n return scriptPromise;\n}\n\nexport function useScript(): { loaded: boolean } {\n const [loaded, setLoaded] = useState(false);\n\n useEffect(() => {\n if (typeof window === \"undefined\") return;\n\n loadScript()\n .then(() => setLoaded(true))\n .catch((err) => console.error(err));\n }, []);\n\n return { loaded };\n}\n","import React, {\n forwardRef,\n useEffect,\n useId,\n useImperativeHandle,\n useRef,\n} from \"react\";\nimport { useScript } from \"./useScript\";\nimport type {\n SCAudioEventPayload,\n SCWidgetInstance,\n SCWidgetParams,\n SCWidgetProps,\n SCWidgetRef,\n} from \"./types\";\n\ndeclare global {\n interface Window {\n SC: {\n Widget: (iframe: HTMLIFrameElement) => SCWidgetInstance;\n };\n }\n}\n\nconst PARAM_MAP: Array<[keyof SCWidgetParams, string]> = [\n [\"autoPlay\", \"auto_play\"],\n [\"color\", \"color\"],\n [\"buying\", \"buying\"],\n [\"sharing\", \"sharing\"],\n [\"download\", \"download\"],\n [\"showArtwork\", \"show_artwork\"],\n [\"showPlaycount\", \"show_playcount\"],\n [\"showUser\", \"show_user\"],\n [\"startTrack\", \"start_track\"],\n [\"singleActive\", \"single_active\"],\n [\"showTeaser\", \"show_teaser\"],\n];\n\nfunction buildIframeSrc(url: string, params: SCWidgetParams): string {\n const search = new URLSearchParams();\n search.set(\"url\", encodeURIComponent(url));\n\n for (const [prop, urlKey] of PARAM_MAP) {\n const value = params[prop];\n if (value !== undefined) {\n search.set(urlKey, String(value));\n }\n }\n\n return `https://w.soundcloud.com/player/?${search.toString()}`;\n}\n\nfunction extractParams(props: SCWidgetProps): SCWidgetParams {\n return {\n autoPlay: props.autoPlay,\n color: props.color,\n buying: props.buying,\n sharing: props.sharing,\n download: props.download,\n showArtwork: props.showArtwork,\n showPlaycount: props.showPlaycount,\n showUser: props.showUser,\n startTrack: props.startTrack,\n singleActive: props.singleActive,\n showTeaser: props.showTeaser,\n };\n}\n\nexport const SCWidget = forwardRef<SCWidgetRef, SCWidgetProps>(\n function SCWidget(props, ref) {\n const {\n url,\n width = \"100%\",\n height = 166,\n style,\n className,\n iframeId,\n onReady,\n onPlay,\n onPause,\n onFinish,\n onSeek,\n onPlayProgress,\n onLoadProgress,\n onError,\n onClickDownload,\n onClickBuy,\n onOpenSharePanel,\n ...params\n } = props;\n\n const { loaded } = useScript();\n const iframeRef = useRef<HTMLIFrameElement>(null);\n const widgetRef = useRef<SCWidgetInstance | null>(null);\n const initializedRef = useRef(false);\n const generatedId = useId();\n const frameId = iframeId ?? `sc-widget-${generatedId}`;\n\n // Stable refs for callbacks so effects don't re-run on each render\n const callbacksRef = useRef({\n onReady,\n onPlay,\n onPause,\n onFinish,\n onSeek,\n onPlayProgress,\n onLoadProgress,\n onError,\n onClickDownload,\n onClickBuy,\n onOpenSharePanel,\n });\n useEffect(() => {\n callbacksRef.current = {\n onReady,\n onPlay,\n onPause,\n onFinish,\n onSeek,\n onPlayProgress,\n onLoadProgress,\n onError,\n onClickDownload,\n onClickBuy,\n onOpenSharePanel,\n };\n });\n\n // Initialize widget once script is loaded and iframe is mounted\n useEffect(() => {\n if (!loaded || !iframeRef.current || initializedRef.current) return;\n\n const widget = window.SC.Widget(iframeRef.current);\n widgetRef.current = widget;\n initializedRef.current = true;\n\n const handlers: Array<[string, (e?: SCAudioEventPayload) => void]> = [\n [\"ready\", () => callbacksRef.current.onReady?.()],\n [\"play\", (e) => callbacksRef.current.onPlay?.(e as SCAudioEventPayload)],\n [\"pause\", (e) => callbacksRef.current.onPause?.(e as SCAudioEventPayload)],\n [\"finish\", (e) => callbacksRef.current.onFinish?.(e as SCAudioEventPayload)],\n [\"seek\", (e) => callbacksRef.current.onSeek?.(e as SCAudioEventPayload)],\n [\"play_progress\", (e) => callbacksRef.current.onPlayProgress?.(e as SCAudioEventPayload)],\n [\"load_progress\", (e) => callbacksRef.current.onLoadProgress?.(e as SCAudioEventPayload)],\n [\"error\", () => callbacksRef.current.onError?.()],\n [\"click_download\", () => callbacksRef.current.onClickDownload?.()],\n [\"click_buy\", () => callbacksRef.current.onClickBuy?.()],\n [\"open_share_panel\", () => callbacksRef.current.onOpenSharePanel?.()],\n ];\n\n for (const [event, handler] of handlers) {\n widget.bind(event, handler);\n }\n\n return () => {\n for (const [event] of handlers) {\n widget.unbind(event);\n }\n widgetRef.current = null;\n initializedRef.current = false;\n };\n }, [loaded]);\n\n // Reload when url or params change (after initial mount)\n const isFirstRender = useRef(true);\n const prevUrl = useRef(url);\n const prevParams = useRef(params);\n\n useEffect(() => {\n if (isFirstRender.current) {\n isFirstRender.current = false;\n prevUrl.current = url;\n prevParams.current = params;\n return;\n }\n\n if (!widgetRef.current) return;\n\n prevUrl.current = url;\n prevParams.current = params;\n\n widgetRef.current.load(url, {\n ...params,\n callback: callbacksRef.current.onReady,\n });\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [url, params.autoPlay, params.color, params.buying, params.sharing,\n params.download, params.showArtwork, params.showPlaycount, params.showUser,\n params.startTrack, params.singleActive, params.showTeaser]);\n\n useImperativeHandle(ref, () => ({\n play: () => widgetRef.current?.play(),\n pause: () => widgetRef.current?.pause(),\n toggle: () => widgetRef.current?.toggle(),\n seekTo: (ms) => widgetRef.current?.seekTo(ms),\n setVolume: (vol) => widgetRef.current?.setVolume(vol),\n next: () => widgetRef.current?.next(),\n prev: () => widgetRef.current?.prev(),\n skip: (idx) => widgetRef.current?.skip(idx),\n load: (u, opts) => widgetRef.current?.load(u, opts),\n getVolume: (cb) => widgetRef.current?.getVolume(cb) ?? cb(0),\n getDuration: (cb) => widgetRef.current?.getDuration(cb) ?? cb(0),\n getPosition: (cb) => widgetRef.current?.getPosition(cb) ?? cb(0),\n getSounds: (cb) => widgetRef.current?.getSounds(cb) ?? cb([]),\n getCurrentSound: (cb) => widgetRef.current?.getCurrentSound(cb),\n getCurrentSoundIndex: (cb) => widgetRef.current?.getCurrentSoundIndex(cb) ?? cb(0),\n isPaused: (cb) => widgetRef.current?.isPaused(cb) ?? cb(true),\n }));\n\n const src = buildIframeSrc(url, extractParams(props));\n\n return (\n <iframe\n ref={iframeRef}\n id={frameId}\n src={src}\n width={width}\n height={height}\n style={style}\n className={className}\n scrolling=\"no\"\n frameBorder=\"no\"\n allow=\"autoplay\"\n />\n );\n }\n);\n\nSCWidget.displayName = \"SCWidget\";\n\nexport default SCWidget;\n"]}
package/dist/index.mjs ADDED
@@ -0,0 +1,352 @@
1
+ import { forwardRef, useRef, useId, useEffect, useImperativeHandle, useState } from 'react';
2
+ import { jsx } from 'react/jsx-runtime';
3
+
4
+ var __defProp = Object.defineProperty;
5
+ var __defProps = Object.defineProperties;
6
+ var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
7
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
10
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
11
+ var __spreadValues = (a, b) => {
12
+ for (var prop in b || (b = {}))
13
+ if (__hasOwnProp.call(b, prop))
14
+ __defNormalProp(a, prop, b[prop]);
15
+ if (__getOwnPropSymbols)
16
+ for (var prop of __getOwnPropSymbols(b)) {
17
+ if (__propIsEnum.call(b, prop))
18
+ __defNormalProp(a, prop, b[prop]);
19
+ }
20
+ return a;
21
+ };
22
+ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
23
+ var __objRest = (source, exclude) => {
24
+ var target = {};
25
+ for (var prop in source)
26
+ if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
27
+ target[prop] = source[prop];
28
+ if (source != null && __getOwnPropSymbols)
29
+ for (var prop of __getOwnPropSymbols(source)) {
30
+ if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
31
+ target[prop] = source[prop];
32
+ }
33
+ return target;
34
+ };
35
+ var SC_API_URL = "https://w.soundcloud.com/player/api.js";
36
+ var scriptPromise = null;
37
+ function loadScript() {
38
+ if (scriptPromise) return scriptPromise;
39
+ scriptPromise = new Promise((resolve, reject) => {
40
+ const script = document.createElement("script");
41
+ script.src = SC_API_URL;
42
+ script.async = true;
43
+ script.onload = () => resolve();
44
+ script.onerror = () => {
45
+ scriptPromise = null;
46
+ reject(new Error("Failed to load SoundCloud Widget API"));
47
+ };
48
+ document.head.appendChild(script);
49
+ });
50
+ return scriptPromise;
51
+ }
52
+ function useScript() {
53
+ const [loaded, setLoaded] = useState(false);
54
+ useEffect(() => {
55
+ if (typeof window === "undefined") return;
56
+ loadScript().then(() => setLoaded(true)).catch((err) => console.error(err));
57
+ }, []);
58
+ return { loaded };
59
+ }
60
+ var PARAM_MAP = [
61
+ ["autoPlay", "auto_play"],
62
+ ["color", "color"],
63
+ ["buying", "buying"],
64
+ ["sharing", "sharing"],
65
+ ["download", "download"],
66
+ ["showArtwork", "show_artwork"],
67
+ ["showPlaycount", "show_playcount"],
68
+ ["showUser", "show_user"],
69
+ ["startTrack", "start_track"],
70
+ ["singleActive", "single_active"],
71
+ ["showTeaser", "show_teaser"]
72
+ ];
73
+ function buildIframeSrc(url, params) {
74
+ const search = new URLSearchParams();
75
+ search.set("url", encodeURIComponent(url));
76
+ for (const [prop, urlKey] of PARAM_MAP) {
77
+ const value = params[prop];
78
+ if (value !== void 0) {
79
+ search.set(urlKey, String(value));
80
+ }
81
+ }
82
+ return `https://w.soundcloud.com/player/?${search.toString()}`;
83
+ }
84
+ function extractParams(props) {
85
+ return {
86
+ autoPlay: props.autoPlay,
87
+ color: props.color,
88
+ buying: props.buying,
89
+ sharing: props.sharing,
90
+ download: props.download,
91
+ showArtwork: props.showArtwork,
92
+ showPlaycount: props.showPlaycount,
93
+ showUser: props.showUser,
94
+ startTrack: props.startTrack,
95
+ singleActive: props.singleActive,
96
+ showTeaser: props.showTeaser
97
+ };
98
+ }
99
+ var SCWidget = forwardRef(
100
+ function SCWidget2(props, ref) {
101
+ const _a = props, {
102
+ url,
103
+ width = "100%",
104
+ height = 166,
105
+ style,
106
+ className,
107
+ iframeId,
108
+ onReady,
109
+ onPlay,
110
+ onPause,
111
+ onFinish,
112
+ onSeek,
113
+ onPlayProgress,
114
+ onLoadProgress,
115
+ onError,
116
+ onClickDownload,
117
+ onClickBuy,
118
+ onOpenSharePanel
119
+ } = _a, params = __objRest(_a, [
120
+ "url",
121
+ "width",
122
+ "height",
123
+ "style",
124
+ "className",
125
+ "iframeId",
126
+ "onReady",
127
+ "onPlay",
128
+ "onPause",
129
+ "onFinish",
130
+ "onSeek",
131
+ "onPlayProgress",
132
+ "onLoadProgress",
133
+ "onError",
134
+ "onClickDownload",
135
+ "onClickBuy",
136
+ "onOpenSharePanel"
137
+ ]);
138
+ const { loaded } = useScript();
139
+ const iframeRef = useRef(null);
140
+ const widgetRef = useRef(null);
141
+ const initializedRef = useRef(false);
142
+ const generatedId = useId();
143
+ const frameId = iframeId != null ? iframeId : `sc-widget-${generatedId}`;
144
+ const callbacksRef = useRef({
145
+ onReady,
146
+ onPlay,
147
+ onPause,
148
+ onFinish,
149
+ onSeek,
150
+ onPlayProgress,
151
+ onLoadProgress,
152
+ onError,
153
+ onClickDownload,
154
+ onClickBuy,
155
+ onOpenSharePanel
156
+ });
157
+ useEffect(() => {
158
+ callbacksRef.current = {
159
+ onReady,
160
+ onPlay,
161
+ onPause,
162
+ onFinish,
163
+ onSeek,
164
+ onPlayProgress,
165
+ onLoadProgress,
166
+ onError,
167
+ onClickDownload,
168
+ onClickBuy,
169
+ onOpenSharePanel
170
+ };
171
+ });
172
+ useEffect(() => {
173
+ if (!loaded || !iframeRef.current || initializedRef.current) return;
174
+ const widget = window.SC.Widget(iframeRef.current);
175
+ widgetRef.current = widget;
176
+ initializedRef.current = true;
177
+ const handlers = [
178
+ ["ready", () => {
179
+ var _a2, _b;
180
+ return (_b = (_a2 = callbacksRef.current).onReady) == null ? void 0 : _b.call(_a2);
181
+ }],
182
+ ["play", (e) => {
183
+ var _a2, _b;
184
+ return (_b = (_a2 = callbacksRef.current).onPlay) == null ? void 0 : _b.call(_a2, e);
185
+ }],
186
+ ["pause", (e) => {
187
+ var _a2, _b;
188
+ return (_b = (_a2 = callbacksRef.current).onPause) == null ? void 0 : _b.call(_a2, e);
189
+ }],
190
+ ["finish", (e) => {
191
+ var _a2, _b;
192
+ return (_b = (_a2 = callbacksRef.current).onFinish) == null ? void 0 : _b.call(_a2, e);
193
+ }],
194
+ ["seek", (e) => {
195
+ var _a2, _b;
196
+ return (_b = (_a2 = callbacksRef.current).onSeek) == null ? void 0 : _b.call(_a2, e);
197
+ }],
198
+ ["play_progress", (e) => {
199
+ var _a2, _b;
200
+ return (_b = (_a2 = callbacksRef.current).onPlayProgress) == null ? void 0 : _b.call(_a2, e);
201
+ }],
202
+ ["load_progress", (e) => {
203
+ var _a2, _b;
204
+ return (_b = (_a2 = callbacksRef.current).onLoadProgress) == null ? void 0 : _b.call(_a2, e);
205
+ }],
206
+ ["error", () => {
207
+ var _a2, _b;
208
+ return (_b = (_a2 = callbacksRef.current).onError) == null ? void 0 : _b.call(_a2);
209
+ }],
210
+ ["click_download", () => {
211
+ var _a2, _b;
212
+ return (_b = (_a2 = callbacksRef.current).onClickDownload) == null ? void 0 : _b.call(_a2);
213
+ }],
214
+ ["click_buy", () => {
215
+ var _a2, _b;
216
+ return (_b = (_a2 = callbacksRef.current).onClickBuy) == null ? void 0 : _b.call(_a2);
217
+ }],
218
+ ["open_share_panel", () => {
219
+ var _a2, _b;
220
+ return (_b = (_a2 = callbacksRef.current).onOpenSharePanel) == null ? void 0 : _b.call(_a2);
221
+ }]
222
+ ];
223
+ for (const [event, handler] of handlers) {
224
+ widget.bind(event, handler);
225
+ }
226
+ return () => {
227
+ for (const [event] of handlers) {
228
+ widget.unbind(event);
229
+ }
230
+ widgetRef.current = null;
231
+ initializedRef.current = false;
232
+ };
233
+ }, [loaded]);
234
+ const isFirstRender = useRef(true);
235
+ const prevUrl = useRef(url);
236
+ const prevParams = useRef(params);
237
+ useEffect(() => {
238
+ if (isFirstRender.current) {
239
+ isFirstRender.current = false;
240
+ prevUrl.current = url;
241
+ prevParams.current = params;
242
+ return;
243
+ }
244
+ if (!widgetRef.current) return;
245
+ prevUrl.current = url;
246
+ prevParams.current = params;
247
+ widgetRef.current.load(url, __spreadProps(__spreadValues({}, params), {
248
+ callback: callbacksRef.current.onReady
249
+ }));
250
+ }, [
251
+ url,
252
+ params.autoPlay,
253
+ params.color,
254
+ params.buying,
255
+ params.sharing,
256
+ params.download,
257
+ params.showArtwork,
258
+ params.showPlaycount,
259
+ params.showUser,
260
+ params.startTrack,
261
+ params.singleActive,
262
+ params.showTeaser
263
+ ]);
264
+ useImperativeHandle(ref, () => ({
265
+ play: () => {
266
+ var _a2;
267
+ return (_a2 = widgetRef.current) == null ? void 0 : _a2.play();
268
+ },
269
+ pause: () => {
270
+ var _a2;
271
+ return (_a2 = widgetRef.current) == null ? void 0 : _a2.pause();
272
+ },
273
+ toggle: () => {
274
+ var _a2;
275
+ return (_a2 = widgetRef.current) == null ? void 0 : _a2.toggle();
276
+ },
277
+ seekTo: (ms) => {
278
+ var _a2;
279
+ return (_a2 = widgetRef.current) == null ? void 0 : _a2.seekTo(ms);
280
+ },
281
+ setVolume: (vol) => {
282
+ var _a2;
283
+ return (_a2 = widgetRef.current) == null ? void 0 : _a2.setVolume(vol);
284
+ },
285
+ next: () => {
286
+ var _a2;
287
+ return (_a2 = widgetRef.current) == null ? void 0 : _a2.next();
288
+ },
289
+ prev: () => {
290
+ var _a2;
291
+ return (_a2 = widgetRef.current) == null ? void 0 : _a2.prev();
292
+ },
293
+ skip: (idx) => {
294
+ var _a2;
295
+ return (_a2 = widgetRef.current) == null ? void 0 : _a2.skip(idx);
296
+ },
297
+ load: (u, opts) => {
298
+ var _a2;
299
+ return (_a2 = widgetRef.current) == null ? void 0 : _a2.load(u, opts);
300
+ },
301
+ getVolume: (cb) => {
302
+ var _a2, _b;
303
+ return (_b = (_a2 = widgetRef.current) == null ? void 0 : _a2.getVolume(cb)) != null ? _b : cb(0);
304
+ },
305
+ getDuration: (cb) => {
306
+ var _a2, _b;
307
+ return (_b = (_a2 = widgetRef.current) == null ? void 0 : _a2.getDuration(cb)) != null ? _b : cb(0);
308
+ },
309
+ getPosition: (cb) => {
310
+ var _a2, _b;
311
+ return (_b = (_a2 = widgetRef.current) == null ? void 0 : _a2.getPosition(cb)) != null ? _b : cb(0);
312
+ },
313
+ getSounds: (cb) => {
314
+ var _a2, _b;
315
+ return (_b = (_a2 = widgetRef.current) == null ? void 0 : _a2.getSounds(cb)) != null ? _b : cb([]);
316
+ },
317
+ getCurrentSound: (cb) => {
318
+ var _a2;
319
+ return (_a2 = widgetRef.current) == null ? void 0 : _a2.getCurrentSound(cb);
320
+ },
321
+ getCurrentSoundIndex: (cb) => {
322
+ var _a2, _b;
323
+ return (_b = (_a2 = widgetRef.current) == null ? void 0 : _a2.getCurrentSoundIndex(cb)) != null ? _b : cb(0);
324
+ },
325
+ isPaused: (cb) => {
326
+ var _a2, _b;
327
+ return (_b = (_a2 = widgetRef.current) == null ? void 0 : _a2.isPaused(cb)) != null ? _b : cb(true);
328
+ }
329
+ }));
330
+ const src = buildIframeSrc(url, extractParams(props));
331
+ return /* @__PURE__ */ jsx(
332
+ "iframe",
333
+ {
334
+ ref: iframeRef,
335
+ id: frameId,
336
+ src,
337
+ width,
338
+ height,
339
+ style,
340
+ className,
341
+ scrolling: "no",
342
+ frameBorder: "no",
343
+ allow: "autoplay"
344
+ }
345
+ );
346
+ }
347
+ );
348
+ SCWidget.displayName = "SCWidget";
349
+
350
+ export { SCWidget, SCWidget as default };
351
+ //# sourceMappingURL=index.mjs.map
352
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/useScript.ts","../src/SCWidget.tsx"],"names":["SCWidget","useEffect","_a"],"mappings":"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","file":"index.mjs","sourcesContent":["import { useState, useEffect } from \"react\";\n\nconst SC_API_URL = \"https://w.soundcloud.com/player/api.js\";\n\nlet scriptPromise: Promise<void> | null = null;\n\nfunction loadScript(): Promise<void> {\n if (scriptPromise) return scriptPromise;\n\n scriptPromise = new Promise<void>((resolve, reject) => {\n const script = document.createElement(\"script\");\n script.src = SC_API_URL;\n script.async = true;\n script.onload = () => resolve();\n script.onerror = () => {\n scriptPromise = null;\n reject(new Error(\"Failed to load SoundCloud Widget API\"));\n };\n document.head.appendChild(script);\n });\n\n return scriptPromise;\n}\n\nexport function useScript(): { loaded: boolean } {\n const [loaded, setLoaded] = useState(false);\n\n useEffect(() => {\n if (typeof window === \"undefined\") return;\n\n loadScript()\n .then(() => setLoaded(true))\n .catch((err) => console.error(err));\n }, []);\n\n return { loaded };\n}\n","import React, {\n forwardRef,\n useEffect,\n useId,\n useImperativeHandle,\n useRef,\n} from \"react\";\nimport { useScript } from \"./useScript\";\nimport type {\n SCAudioEventPayload,\n SCWidgetInstance,\n SCWidgetParams,\n SCWidgetProps,\n SCWidgetRef,\n} from \"./types\";\n\ndeclare global {\n interface Window {\n SC: {\n Widget: (iframe: HTMLIFrameElement) => SCWidgetInstance;\n };\n }\n}\n\nconst PARAM_MAP: Array<[keyof SCWidgetParams, string]> = [\n [\"autoPlay\", \"auto_play\"],\n [\"color\", \"color\"],\n [\"buying\", \"buying\"],\n [\"sharing\", \"sharing\"],\n [\"download\", \"download\"],\n [\"showArtwork\", \"show_artwork\"],\n [\"showPlaycount\", \"show_playcount\"],\n [\"showUser\", \"show_user\"],\n [\"startTrack\", \"start_track\"],\n [\"singleActive\", \"single_active\"],\n [\"showTeaser\", \"show_teaser\"],\n];\n\nfunction buildIframeSrc(url: string, params: SCWidgetParams): string {\n const search = new URLSearchParams();\n search.set(\"url\", encodeURIComponent(url));\n\n for (const [prop, urlKey] of PARAM_MAP) {\n const value = params[prop];\n if (value !== undefined) {\n search.set(urlKey, String(value));\n }\n }\n\n return `https://w.soundcloud.com/player/?${search.toString()}`;\n}\n\nfunction extractParams(props: SCWidgetProps): SCWidgetParams {\n return {\n autoPlay: props.autoPlay,\n color: props.color,\n buying: props.buying,\n sharing: props.sharing,\n download: props.download,\n showArtwork: props.showArtwork,\n showPlaycount: props.showPlaycount,\n showUser: props.showUser,\n startTrack: props.startTrack,\n singleActive: props.singleActive,\n showTeaser: props.showTeaser,\n };\n}\n\nexport const SCWidget = forwardRef<SCWidgetRef, SCWidgetProps>(\n function SCWidget(props, ref) {\n const {\n url,\n width = \"100%\",\n height = 166,\n style,\n className,\n iframeId,\n onReady,\n onPlay,\n onPause,\n onFinish,\n onSeek,\n onPlayProgress,\n onLoadProgress,\n onError,\n onClickDownload,\n onClickBuy,\n onOpenSharePanel,\n ...params\n } = props;\n\n const { loaded } = useScript();\n const iframeRef = useRef<HTMLIFrameElement>(null);\n const widgetRef = useRef<SCWidgetInstance | null>(null);\n const initializedRef = useRef(false);\n const generatedId = useId();\n const frameId = iframeId ?? `sc-widget-${generatedId}`;\n\n // Stable refs for callbacks so effects don't re-run on each render\n const callbacksRef = useRef({\n onReady,\n onPlay,\n onPause,\n onFinish,\n onSeek,\n onPlayProgress,\n onLoadProgress,\n onError,\n onClickDownload,\n onClickBuy,\n onOpenSharePanel,\n });\n useEffect(() => {\n callbacksRef.current = {\n onReady,\n onPlay,\n onPause,\n onFinish,\n onSeek,\n onPlayProgress,\n onLoadProgress,\n onError,\n onClickDownload,\n onClickBuy,\n onOpenSharePanel,\n };\n });\n\n // Initialize widget once script is loaded and iframe is mounted\n useEffect(() => {\n if (!loaded || !iframeRef.current || initializedRef.current) return;\n\n const widget = window.SC.Widget(iframeRef.current);\n widgetRef.current = widget;\n initializedRef.current = true;\n\n const handlers: Array<[string, (e?: SCAudioEventPayload) => void]> = [\n [\"ready\", () => callbacksRef.current.onReady?.()],\n [\"play\", (e) => callbacksRef.current.onPlay?.(e as SCAudioEventPayload)],\n [\"pause\", (e) => callbacksRef.current.onPause?.(e as SCAudioEventPayload)],\n [\"finish\", (e) => callbacksRef.current.onFinish?.(e as SCAudioEventPayload)],\n [\"seek\", (e) => callbacksRef.current.onSeek?.(e as SCAudioEventPayload)],\n [\"play_progress\", (e) => callbacksRef.current.onPlayProgress?.(e as SCAudioEventPayload)],\n [\"load_progress\", (e) => callbacksRef.current.onLoadProgress?.(e as SCAudioEventPayload)],\n [\"error\", () => callbacksRef.current.onError?.()],\n [\"click_download\", () => callbacksRef.current.onClickDownload?.()],\n [\"click_buy\", () => callbacksRef.current.onClickBuy?.()],\n [\"open_share_panel\", () => callbacksRef.current.onOpenSharePanel?.()],\n ];\n\n for (const [event, handler] of handlers) {\n widget.bind(event, handler);\n }\n\n return () => {\n for (const [event] of handlers) {\n widget.unbind(event);\n }\n widgetRef.current = null;\n initializedRef.current = false;\n };\n }, [loaded]);\n\n // Reload when url or params change (after initial mount)\n const isFirstRender = useRef(true);\n const prevUrl = useRef(url);\n const prevParams = useRef(params);\n\n useEffect(() => {\n if (isFirstRender.current) {\n isFirstRender.current = false;\n prevUrl.current = url;\n prevParams.current = params;\n return;\n }\n\n if (!widgetRef.current) return;\n\n prevUrl.current = url;\n prevParams.current = params;\n\n widgetRef.current.load(url, {\n ...params,\n callback: callbacksRef.current.onReady,\n });\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [url, params.autoPlay, params.color, params.buying, params.sharing,\n params.download, params.showArtwork, params.showPlaycount, params.showUser,\n params.startTrack, params.singleActive, params.showTeaser]);\n\n useImperativeHandle(ref, () => ({\n play: () => widgetRef.current?.play(),\n pause: () => widgetRef.current?.pause(),\n toggle: () => widgetRef.current?.toggle(),\n seekTo: (ms) => widgetRef.current?.seekTo(ms),\n setVolume: (vol) => widgetRef.current?.setVolume(vol),\n next: () => widgetRef.current?.next(),\n prev: () => widgetRef.current?.prev(),\n skip: (idx) => widgetRef.current?.skip(idx),\n load: (u, opts) => widgetRef.current?.load(u, opts),\n getVolume: (cb) => widgetRef.current?.getVolume(cb) ?? cb(0),\n getDuration: (cb) => widgetRef.current?.getDuration(cb) ?? cb(0),\n getPosition: (cb) => widgetRef.current?.getPosition(cb) ?? cb(0),\n getSounds: (cb) => widgetRef.current?.getSounds(cb) ?? cb([]),\n getCurrentSound: (cb) => widgetRef.current?.getCurrentSound(cb),\n getCurrentSoundIndex: (cb) => widgetRef.current?.getCurrentSoundIndex(cb) ?? cb(0),\n isPaused: (cb) => widgetRef.current?.isPaused(cb) ?? cb(true),\n }));\n\n const src = buildIframeSrc(url, extractParams(props));\n\n return (\n <iframe\n ref={iframeRef}\n id={frameId}\n src={src}\n width={width}\n height={height}\n style={style}\n className={className}\n scrolling=\"no\"\n frameBorder=\"no\"\n allow=\"autoplay\"\n />\n );\n }\n);\n\nSCWidget.displayName = \"SCWidget\";\n\nexport default SCWidget;\n"]}
package/package.json ADDED
@@ -0,0 +1,37 @@
1
+ {
2
+ "name": "soundcloud-widget-react",
3
+ "version": "1.0.1",
4
+ "description": "React component for the SoundCloud HTML5 Widget API with full TypeScript support",
5
+ "author": "twin-paws",
6
+ "license": "MIT",
7
+ "main": "dist/index.js",
8
+ "module": "dist/index.mjs",
9
+ "types": "dist/index.d.ts",
10
+ "exports": {
11
+ ".": {
12
+ "types": "./dist/index.d.ts",
13
+ "import": "./dist/index.mjs",
14
+ "require": "./dist/index.js"
15
+ }
16
+ },
17
+ "files": [
18
+ "dist"
19
+ ],
20
+ "scripts": {
21
+ "build": "tsup",
22
+ "dev": "tsup --watch",
23
+ "typecheck": "tsc --noEmit"
24
+ },
25
+ "peerDependencies": {
26
+ "react": ">=17",
27
+ "react-dom": ">=17"
28
+ },
29
+ "devDependencies": {
30
+ "@types/react": "^18.0.0",
31
+ "@types/react-dom": "^18.0.0",
32
+ "react": "^18.2.0",
33
+ "react-dom": "^18.2.0",
34
+ "tsup": "^8.0.0",
35
+ "typescript": "^5.0.0"
36
+ }
37
+ }