@sparkletree/core 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.
- package/LICENSE +21 -0
- package/README.md +105 -0
- package/dist/analytics.d.ts +75 -0
- package/dist/analytics.d.ts.map +1 -0
- package/dist/analytics.js +170 -0
- package/dist/analytics.js.map +1 -0
- package/dist/audio.d.ts +85 -0
- package/dist/audio.d.ts.map +1 -0
- package/dist/audio.js +465 -0
- package/dist/audio.js.map +1 -0
- package/dist/client.d.ts +79 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +251 -0
- package/dist/client.js.map +1 -0
- package/dist/context.d.ts +104 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +277 -0
- package/dist/context.js.map +1 -0
- package/dist/fragments.d.ts +108 -0
- package/dist/fragments.d.ts.map +1 -0
- package/dist/fragments.js +223 -0
- package/dist/fragments.js.map +1 -0
- package/dist/index.d.ts +31 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +30 -0
- package/dist/index.js.map +1 -0
- package/dist/protocol.d.ts +70 -0
- package/dist/protocol.d.ts.map +1 -0
- package/dist/protocol.js +97 -0
- package/dist/protocol.js.map +1 -0
- package/dist/publishableKey.d.ts +38 -0
- package/dist/publishableKey.d.ts.map +1 -0
- package/dist/publishableKey.js +69 -0
- package/dist/publishableKey.js.map +1 -0
- package/dist/safeUrl.d.ts +56 -0
- package/dist/safeUrl.d.ts.map +1 -0
- package/dist/safeUrl.js +117 -0
- package/dist/safeUrl.js.map +1 -0
- package/dist/sse.d.ts +51 -0
- package/dist/sse.d.ts.map +1 -0
- package/dist/sse.js +137 -0
- package/dist/sse.js.map +1 -0
- package/dist/state.d.ts +321 -0
- package/dist/state.d.ts.map +1 -0
- package/dist/state.js +594 -0
- package/dist/state.js.map +1 -0
- package/dist/text.d.ts +10 -0
- package/dist/text.d.ts.map +1 -0
- package/dist/text.js +29 -0
- package/dist/text.js.map +1 -0
- package/dist/theme.d.ts +52 -0
- package/dist/theme.d.ts.map +1 -0
- package/dist/theme.js +88 -0
- package/dist/theme.js.map +1 -0
- package/dist/trust.d.ts +52 -0
- package/dist/trust.d.ts.map +1 -0
- package/dist/trust.js +95 -0
- package/dist/trust.js.map +1 -0
- package/dist/variant.d.ts +117 -0
- package/dist/variant.d.ts.map +1 -0
- package/dist/variant.js +167 -0
- package/dist/variant.js.map +1 -0
- package/dist/wire.d.ts +564 -0
- package/dist/wire.d.ts.map +1 -0
- package/dist/wire.js +133 -0
- package/dist/wire.js.map +1 -0
- package/package.json +55 -0
package/dist/audio.js
ADDED
|
@@ -0,0 +1,465 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Audio engine — W3, plan v1.1 decision (b): audio is CORE-ONLY.
|
|
3
|
+
*
|
|
4
|
+
* `window.__squidAudio` was an inline IIFE in the shell template. Moving it
|
|
5
|
+
* here makes it versioned and patchable: a provider changes their embed API
|
|
6
|
+
* and one package bump reaches every consumer, instead of every customer
|
|
7
|
+
* needing to re-copy a component.
|
|
8
|
+
*
|
|
9
|
+
* The accepted trade-off is that consumers cannot customise playback
|
|
10
|
+
* behaviour without forking. The mitigation is the shape of this module: what
|
|
11
|
+
* moves into core is the ENGINE — adapters, gesture wiring, the listen clock,
|
|
12
|
+
* media session — and NOT the chrome. `getState()` and `on()` expose
|
|
13
|
+
* everything a copied component needs to render its own player UI against an
|
|
14
|
+
* engine it does not own. Moving the shell's markup in here as well would have
|
|
15
|
+
* been "just moving the file", and would have made every consumer's player
|
|
16
|
+
* look like signage.
|
|
17
|
+
*
|
|
18
|
+
* Two invariants worth stating because both are load-bearing:
|
|
19
|
+
*
|
|
20
|
+
* - AUTOPLAY IS NEVER USED. Tap to play, always. Autoplaying audio in
|
|
21
|
+
* someone else's page is the single fastest way for a customer to remove
|
|
22
|
+
* the SDK.
|
|
23
|
+
* - ONE PLAYER AT A TIME. Mounting a second destroys the first, so a page
|
|
24
|
+
* that cycles variants cannot end up with two tracks over each other.
|
|
25
|
+
*/
|
|
26
|
+
// --- listen clock -------------------------------------------------------------
|
|
27
|
+
/**
|
|
28
|
+
* Accumulates audible time.
|
|
29
|
+
*
|
|
30
|
+
* Capped at ten times the track duration (six hours when the duration is
|
|
31
|
+
* unknown). A tab left open for a week on a looping track would otherwise
|
|
32
|
+
* report a listen time that is technically true and analytically useless —
|
|
33
|
+
* and, since listen time feeds CVG, one such session can dominate a campaign's
|
|
34
|
+
* engagement numbers on its own.
|
|
35
|
+
*/
|
|
36
|
+
function createListenClock(getDurationMs) {
|
|
37
|
+
let accumulatedMs = 0;
|
|
38
|
+
let startedAt = null;
|
|
39
|
+
const capMs = () => {
|
|
40
|
+
const total = getDurationMs() || 0;
|
|
41
|
+
return total > 0 ? total * 10 : 21_600_000;
|
|
42
|
+
};
|
|
43
|
+
const fold = () => {
|
|
44
|
+
if (startedAt === null)
|
|
45
|
+
return;
|
|
46
|
+
const now = Date.now();
|
|
47
|
+
accumulatedMs = Math.min(accumulatedMs + (now - startedAt), capMs());
|
|
48
|
+
startedAt = now;
|
|
49
|
+
};
|
|
50
|
+
return {
|
|
51
|
+
start: () => {
|
|
52
|
+
if (startedAt === null)
|
|
53
|
+
startedAt = Date.now();
|
|
54
|
+
},
|
|
55
|
+
stop: () => {
|
|
56
|
+
fold();
|
|
57
|
+
startedAt = null;
|
|
58
|
+
},
|
|
59
|
+
valueMs: () => {
|
|
60
|
+
fold();
|
|
61
|
+
return accumulatedMs;
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
function createEmitter() {
|
|
66
|
+
const listeners = new Map();
|
|
67
|
+
return {
|
|
68
|
+
on(event, listener) {
|
|
69
|
+
const set = listeners.get(event) ?? new Set();
|
|
70
|
+
set.add(listener);
|
|
71
|
+
listeners.set(event, set);
|
|
72
|
+
return () => set.delete(listener);
|
|
73
|
+
},
|
|
74
|
+
emit(event, state) {
|
|
75
|
+
for (const listener of listeners.get(event) ?? []) {
|
|
76
|
+
try {
|
|
77
|
+
listener(state);
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
// A consumer's listener throwing must not stop playback or the
|
|
81
|
+
// other listeners.
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
clear() {
|
|
86
|
+
listeners.clear();
|
|
87
|
+
},
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
// --- media session ------------------------------------------------------------
|
|
91
|
+
/**
|
|
92
|
+
* Publish lock-screen metadata and point the OS transport controls at the
|
|
93
|
+
* handle (not the raw element), so custom chrome stays in sync with the
|
|
94
|
+
* Dynamic Island.
|
|
95
|
+
*
|
|
96
|
+
* Best-effort throughout: every touch is wrapped, because an OS metadata
|
|
97
|
+
* failure must never break playback. The Spotify adapter deliberately never
|
|
98
|
+
* calls this — its iframe owns its own media session, and two sessions fight.
|
|
99
|
+
*/
|
|
100
|
+
function armMediaSession(block, handle) {
|
|
101
|
+
try {
|
|
102
|
+
const nav = typeof navigator !== "undefined" ? navigator : undefined;
|
|
103
|
+
const session = nav?.mediaSession;
|
|
104
|
+
if (!session || typeof MediaMetadata === "undefined")
|
|
105
|
+
return;
|
|
106
|
+
const init = { title: block.title || "" };
|
|
107
|
+
// Suno ingestion often leaves artist empty — omit rather than pass "",
|
|
108
|
+
// which renders as a blank line on the lock screen.
|
|
109
|
+
if (block.artist)
|
|
110
|
+
init.artist = block.artist;
|
|
111
|
+
if (block.artwork?.url) {
|
|
112
|
+
init.artwork = [{ src: block.artwork.url, sizes: "512x512" }];
|
|
113
|
+
}
|
|
114
|
+
session.metadata = new MediaMetadata(init);
|
|
115
|
+
session.setActionHandler("play", () => handle.play());
|
|
116
|
+
session.setActionHandler("pause", () => handle.pause());
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
// No media session, or a browser that rejects one of the handlers.
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
function setPlaybackState(state) {
|
|
123
|
+
try {
|
|
124
|
+
const nav = typeof navigator !== "undefined" ? navigator : undefined;
|
|
125
|
+
if (nav?.mediaSession)
|
|
126
|
+
nav.mediaSession.playbackState = state;
|
|
127
|
+
}
|
|
128
|
+
catch {
|
|
129
|
+
// Best-effort.
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
// --- suno adapter -------------------------------------------------------------
|
|
133
|
+
const PROGRESS_INTERVAL_MS = 500;
|
|
134
|
+
function mountSuno(block, host) {
|
|
135
|
+
if (!block.audioUrl)
|
|
136
|
+
return null;
|
|
137
|
+
const emitter = createEmitter();
|
|
138
|
+
const audio = document.createElement("audio");
|
|
139
|
+
audio.preload = "metadata";
|
|
140
|
+
audio.loop = Boolean(block.loop);
|
|
141
|
+
audio.src = block.audioUrl;
|
|
142
|
+
// Hidden: the engine owns playback, the consumer owns the chrome.
|
|
143
|
+
audio.style.display = "none";
|
|
144
|
+
host.appendChild(audio);
|
|
145
|
+
let destroyed = false;
|
|
146
|
+
let lastProgressAt = 0;
|
|
147
|
+
const durationMs = () => audio.duration && Number.isFinite(audio.duration)
|
|
148
|
+
? audio.duration * 1000
|
|
149
|
+
: block.durationMs || 0;
|
|
150
|
+
const positionMs = () => (audio.currentTime || 0) * 1000;
|
|
151
|
+
const clock = createListenClock(durationMs);
|
|
152
|
+
const getState = () => {
|
|
153
|
+
const duration = durationMs();
|
|
154
|
+
const position = positionMs();
|
|
155
|
+
return {
|
|
156
|
+
provider: "suno",
|
|
157
|
+
playing: !audio.paused && !audio.ended,
|
|
158
|
+
positionMs: position,
|
|
159
|
+
durationMs: duration,
|
|
160
|
+
percent: duration > 0 ? Math.max(0, Math.min(1, position / duration)) : 0,
|
|
161
|
+
listenedMs: clock.valueMs(),
|
|
162
|
+
ended: audio.ended,
|
|
163
|
+
errored: false,
|
|
164
|
+
};
|
|
165
|
+
};
|
|
166
|
+
const handle = {
|
|
167
|
+
provider: "suno",
|
|
168
|
+
caps: { customChrome: true, anonymousPlayback: true },
|
|
169
|
+
getState,
|
|
170
|
+
play() {
|
|
171
|
+
try {
|
|
172
|
+
// play() rejects when the browser blocks it; that is a normal outcome
|
|
173
|
+
// of a gesture policy, not an error worth surfacing.
|
|
174
|
+
void audio.play()?.catch(() => { });
|
|
175
|
+
}
|
|
176
|
+
catch {
|
|
177
|
+
/* element torn down */
|
|
178
|
+
}
|
|
179
|
+
},
|
|
180
|
+
pause() {
|
|
181
|
+
try {
|
|
182
|
+
audio.pause();
|
|
183
|
+
}
|
|
184
|
+
catch {
|
|
185
|
+
/* element torn down */
|
|
186
|
+
}
|
|
187
|
+
},
|
|
188
|
+
toggle() {
|
|
189
|
+
if (getState().playing)
|
|
190
|
+
handle.pause();
|
|
191
|
+
else
|
|
192
|
+
handle.play();
|
|
193
|
+
},
|
|
194
|
+
seek(target) {
|
|
195
|
+
try {
|
|
196
|
+
audio.currentTime = Math.max(0, target) / 1000;
|
|
197
|
+
}
|
|
198
|
+
catch {
|
|
199
|
+
/* not seekable yet */
|
|
200
|
+
}
|
|
201
|
+
},
|
|
202
|
+
on: emitter.on,
|
|
203
|
+
destroy() {
|
|
204
|
+
if (destroyed)
|
|
205
|
+
return;
|
|
206
|
+
destroyed = true;
|
|
207
|
+
clock.stop();
|
|
208
|
+
try {
|
|
209
|
+
audio.pause();
|
|
210
|
+
audio.removeAttribute("src");
|
|
211
|
+
audio.load();
|
|
212
|
+
audio.remove();
|
|
213
|
+
}
|
|
214
|
+
catch {
|
|
215
|
+
/* already gone */
|
|
216
|
+
}
|
|
217
|
+
setPlaybackState("none");
|
|
218
|
+
emitter.clear();
|
|
219
|
+
},
|
|
220
|
+
};
|
|
221
|
+
audio.addEventListener("playing", () => {
|
|
222
|
+
clock.start();
|
|
223
|
+
armMediaSession(block, handle);
|
|
224
|
+
setPlaybackState("playing");
|
|
225
|
+
emitter.emit("play", getState());
|
|
226
|
+
});
|
|
227
|
+
audio.addEventListener("pause", () => {
|
|
228
|
+
clock.stop();
|
|
229
|
+
setPlaybackState("paused");
|
|
230
|
+
emitter.emit("pause", getState());
|
|
231
|
+
});
|
|
232
|
+
audio.addEventListener("timeupdate", () => {
|
|
233
|
+
const now = Date.now();
|
|
234
|
+
if (now - lastProgressAt < PROGRESS_INTERVAL_MS)
|
|
235
|
+
return;
|
|
236
|
+
lastProgressAt = now;
|
|
237
|
+
emitter.emit("progress", getState());
|
|
238
|
+
});
|
|
239
|
+
audio.addEventListener("ended", () => {
|
|
240
|
+
clock.stop();
|
|
241
|
+
setPlaybackState("paused");
|
|
242
|
+
emitter.emit("complete", getState());
|
|
243
|
+
});
|
|
244
|
+
audio.addEventListener("error", () => {
|
|
245
|
+
clock.stop();
|
|
246
|
+
emitter.emit("error", { ...getState(), errored: true });
|
|
247
|
+
});
|
|
248
|
+
audio.addEventListener("loadedmetadata", () => emitter.emit("ready", getState()));
|
|
249
|
+
return handle;
|
|
250
|
+
}
|
|
251
|
+
const SPOTIFY_API_SRC = "https://open.spotify.com/embed/iframe-api/v1";
|
|
252
|
+
let spotifyApiPromise = null;
|
|
253
|
+
/** Lazy-load the Spotify iFrame API, once per page. */
|
|
254
|
+
function loadSpotifyIframeApi() {
|
|
255
|
+
if (spotifyApiPromise)
|
|
256
|
+
return spotifyApiPromise;
|
|
257
|
+
spotifyApiPromise = new Promise((resolve, reject) => {
|
|
258
|
+
const global = window;
|
|
259
|
+
// Chain rather than clobber: this global is THE handoff point for the
|
|
260
|
+
// iFrame API, so any other Spotify embed on the customer's page registers
|
|
261
|
+
// the same callback — overwriting it would silently kill their player.
|
|
262
|
+
const previous = global.onSpotifyIframeApiReady;
|
|
263
|
+
global.onSpotifyIframeApiReady = (api) => {
|
|
264
|
+
try {
|
|
265
|
+
previous?.(api);
|
|
266
|
+
}
|
|
267
|
+
catch {
|
|
268
|
+
// The other embed's handler throwing must not cost us the API.
|
|
269
|
+
}
|
|
270
|
+
resolve(api);
|
|
271
|
+
};
|
|
272
|
+
const script = document.createElement("script");
|
|
273
|
+
script.src = SPOTIFY_API_SRC;
|
|
274
|
+
script.async = true;
|
|
275
|
+
script.onerror = () => {
|
|
276
|
+
// Reset so a later mount can retry — a blocked third-party script is
|
|
277
|
+
// often a transient network or extension condition, and caching the
|
|
278
|
+
// failure forever would mean audio never recovers in that tab.
|
|
279
|
+
spotifyApiPromise = null;
|
|
280
|
+
reject(new Error("SparkleTree: Spotify iFrame API failed to load"));
|
|
281
|
+
};
|
|
282
|
+
document.head.appendChild(script);
|
|
283
|
+
});
|
|
284
|
+
return spotifyApiPromise;
|
|
285
|
+
}
|
|
286
|
+
function mountSpotify(block, host) {
|
|
287
|
+
if (!block.trackRef)
|
|
288
|
+
return null;
|
|
289
|
+
const emitter = createEmitter();
|
|
290
|
+
let controller = null;
|
|
291
|
+
let destroyed = false;
|
|
292
|
+
let pendingPlay = false;
|
|
293
|
+
let paused = true;
|
|
294
|
+
let position = 0;
|
|
295
|
+
let duration = block.durationMs || 0;
|
|
296
|
+
let ended = false;
|
|
297
|
+
let lastProgressAt = 0;
|
|
298
|
+
const clock = createListenClock(() => duration);
|
|
299
|
+
const getState = () => ({
|
|
300
|
+
provider: "spotify",
|
|
301
|
+
playing: !paused,
|
|
302
|
+
positionMs: position,
|
|
303
|
+
durationMs: duration,
|
|
304
|
+
percent: duration > 0 ? Math.max(0, Math.min(1, position / duration)) : 0,
|
|
305
|
+
listenedMs: clock.valueMs(),
|
|
306
|
+
ended,
|
|
307
|
+
errored: false,
|
|
308
|
+
});
|
|
309
|
+
const handle = {
|
|
310
|
+
provider: "spotify",
|
|
311
|
+
// The Spotify embed must remain visible and unmodified, so a consumer
|
|
312
|
+
// cannot legitimately render its own transport over it.
|
|
313
|
+
caps: { customChrome: false, anonymousPlayback: false },
|
|
314
|
+
getState,
|
|
315
|
+
play() {
|
|
316
|
+
if (!controller) {
|
|
317
|
+
// Arm rather than drop: a tap before the iframe is ready is the
|
|
318
|
+
// common case on a cold load, and losing it reads as a dead button.
|
|
319
|
+
pendingPlay = true;
|
|
320
|
+
return;
|
|
321
|
+
}
|
|
322
|
+
try {
|
|
323
|
+
controller.play();
|
|
324
|
+
}
|
|
325
|
+
catch {
|
|
326
|
+
/* controller torn down */
|
|
327
|
+
}
|
|
328
|
+
},
|
|
329
|
+
pause() {
|
|
330
|
+
try {
|
|
331
|
+
controller?.pause();
|
|
332
|
+
}
|
|
333
|
+
catch {
|
|
334
|
+
/* controller torn down */
|
|
335
|
+
}
|
|
336
|
+
},
|
|
337
|
+
toggle() {
|
|
338
|
+
if (!paused)
|
|
339
|
+
handle.pause();
|
|
340
|
+
else
|
|
341
|
+
handle.play();
|
|
342
|
+
},
|
|
343
|
+
seek(target) {
|
|
344
|
+
try {
|
|
345
|
+
controller?.seek(Math.max(0, target) / 1000);
|
|
346
|
+
}
|
|
347
|
+
catch {
|
|
348
|
+
/* not seekable */
|
|
349
|
+
}
|
|
350
|
+
},
|
|
351
|
+
on: emitter.on,
|
|
352
|
+
destroy() {
|
|
353
|
+
if (destroyed)
|
|
354
|
+
return;
|
|
355
|
+
destroyed = true;
|
|
356
|
+
clock.stop();
|
|
357
|
+
try {
|
|
358
|
+
controller?.destroy();
|
|
359
|
+
}
|
|
360
|
+
catch {
|
|
361
|
+
/* already gone */
|
|
362
|
+
}
|
|
363
|
+
controller = null;
|
|
364
|
+
emitter.clear();
|
|
365
|
+
},
|
|
366
|
+
};
|
|
367
|
+
void loadSpotifyIframeApi()
|
|
368
|
+
.then((api) => {
|
|
369
|
+
if (destroyed)
|
|
370
|
+
return;
|
|
371
|
+
api.createController(host, { uri: block.trackRef, width: "100%", height: 80 }, (ctrl) => {
|
|
372
|
+
if (destroyed) {
|
|
373
|
+
try {
|
|
374
|
+
ctrl.destroy();
|
|
375
|
+
}
|
|
376
|
+
catch {
|
|
377
|
+
/* already gone */
|
|
378
|
+
}
|
|
379
|
+
return;
|
|
380
|
+
}
|
|
381
|
+
controller = ctrl;
|
|
382
|
+
ctrl.addListener("ready", () => {
|
|
383
|
+
emitter.emit("ready", getState());
|
|
384
|
+
if (pendingPlay && !destroyed) {
|
|
385
|
+
pendingPlay = false;
|
|
386
|
+
try {
|
|
387
|
+
ctrl.play();
|
|
388
|
+
}
|
|
389
|
+
catch {
|
|
390
|
+
/* controller torn down */
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
});
|
|
394
|
+
// Spotify has no play/pause/ended events — everything is derived from
|
|
395
|
+
// playback_update transitions.
|
|
396
|
+
ctrl.addListener("playback_update", (event) => {
|
|
397
|
+
const data = event?.data ?? {};
|
|
398
|
+
if (typeof data.position === "number")
|
|
399
|
+
position = data.position;
|
|
400
|
+
if (typeof data.duration === "number" && data.duration > 0)
|
|
401
|
+
duration = data.duration;
|
|
402
|
+
const nowPaused = Boolean(data.isPaused);
|
|
403
|
+
if (!nowPaused && paused) {
|
|
404
|
+
paused = false;
|
|
405
|
+
ended = false;
|
|
406
|
+
clock.start();
|
|
407
|
+
emitter.emit("play", getState());
|
|
408
|
+
}
|
|
409
|
+
else if (nowPaused && !paused) {
|
|
410
|
+
paused = true;
|
|
411
|
+
clock.stop();
|
|
412
|
+
// Within half a second of the end counts as completion: the
|
|
413
|
+
// provider stops reporting before position reaches duration
|
|
414
|
+
// exactly, so an equality test would never fire.
|
|
415
|
+
if (duration > 0 && position >= duration - 500) {
|
|
416
|
+
ended = true;
|
|
417
|
+
emitter.emit("complete", getState());
|
|
418
|
+
}
|
|
419
|
+
else {
|
|
420
|
+
emitter.emit("pause", getState());
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
const now = Date.now();
|
|
424
|
+
if (now - lastProgressAt >= PROGRESS_INTERVAL_MS) {
|
|
425
|
+
lastProgressAt = now;
|
|
426
|
+
emitter.emit("progress", getState());
|
|
427
|
+
}
|
|
428
|
+
});
|
|
429
|
+
});
|
|
430
|
+
})
|
|
431
|
+
.catch(() => {
|
|
432
|
+
emitter.emit("error", { ...getState(), errored: true });
|
|
433
|
+
});
|
|
434
|
+
return handle;
|
|
435
|
+
}
|
|
436
|
+
// --- single-player registry ---------------------------------------------------
|
|
437
|
+
let activeHandle = null;
|
|
438
|
+
/** The currently mounted player, if any. */
|
|
439
|
+
export function activePlayer() {
|
|
440
|
+
return activeHandle;
|
|
441
|
+
}
|
|
442
|
+
/**
|
|
443
|
+
* Mount a player for `block` inside `host`.
|
|
444
|
+
*
|
|
445
|
+
* Destroys any existing player first — the single-player invariant. A page
|
|
446
|
+
* cycling variants would otherwise stack tracks on top of each other, and the
|
|
447
|
+
* viewer has no way to stop one they can no longer see.
|
|
448
|
+
*/
|
|
449
|
+
export function mountAudio(block, host) {
|
|
450
|
+
destroyActiveAudio();
|
|
451
|
+
const handle = block.provider === "suno"
|
|
452
|
+
? mountSuno(block, host)
|
|
453
|
+
: block.provider === "spotify"
|
|
454
|
+
? mountSpotify(block, host)
|
|
455
|
+
: null;
|
|
456
|
+
activeHandle = handle;
|
|
457
|
+
return handle;
|
|
458
|
+
}
|
|
459
|
+
export function destroyActiveAudio() {
|
|
460
|
+
if (!activeHandle)
|
|
461
|
+
return;
|
|
462
|
+
activeHandle.destroy();
|
|
463
|
+
activeHandle = null;
|
|
464
|
+
}
|
|
465
|
+
//# sourceMappingURL=audio.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audio.js","sourceRoot":"","sources":["../src/audio.ts"],"names":[],"mappings":"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"}
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The client: fetch `/content` for first paint, then open the stream and feed
|
|
3
|
+
* every event into the choreographer.
|
|
4
|
+
*
|
|
5
|
+
* The event dispatch below is the ONLY place in the SDK that knows event
|
|
6
|
+
* names, and every name it knows comes from the generated contract. A server
|
|
7
|
+
* that starts emitting something newer than this build is not an error — it is
|
|
8
|
+
* an older client, which the protocol explicitly supports — so unknown events
|
|
9
|
+
* are ignored rather than warned about.
|
|
10
|
+
*/
|
|
11
|
+
import { type StreamTarget } from "./protocol.js";
|
|
12
|
+
import { CopyChoreographer, type ChoreographerOptions, type CreativeState } from "./state.js";
|
|
13
|
+
export interface ContentSnapshot {
|
|
14
|
+
campaignId: string;
|
|
15
|
+
variantId: string;
|
|
16
|
+
content: {
|
|
17
|
+
headline?: string;
|
|
18
|
+
body?: string;
|
|
19
|
+
cta?: string | {
|
|
20
|
+
text?: string;
|
|
21
|
+
};
|
|
22
|
+
image?: string;
|
|
23
|
+
experienceManifest?: unknown;
|
|
24
|
+
};
|
|
25
|
+
theme?: {
|
|
26
|
+
colors: Record<string, string>;
|
|
27
|
+
sources: Record<string, string>;
|
|
28
|
+
};
|
|
29
|
+
products?: unknown[];
|
|
30
|
+
meta?: Record<string, unknown>;
|
|
31
|
+
}
|
|
32
|
+
export interface StreamOptions extends ChoreographerOptions {
|
|
33
|
+
target: StreamTarget;
|
|
34
|
+
signal?: AbortSignal;
|
|
35
|
+
/** Swap the transport (SSR, tests, a customer's instrumented fetch). */
|
|
36
|
+
fetchImpl?: typeof fetch;
|
|
37
|
+
/** Called on every state change. */
|
|
38
|
+
onState?: (state: CreativeState) => void;
|
|
39
|
+
/**
|
|
40
|
+
* Called when the server cannot speak the version this build requested. The
|
|
41
|
+
* SDK has already kept its own first paint by the time this fires; the hook
|
|
42
|
+
* exists so a consumer can log it once, not so it can retry.
|
|
43
|
+
*/
|
|
44
|
+
onProtocolUnsupported?: (info: {
|
|
45
|
+
requested: number;
|
|
46
|
+
supported: number[];
|
|
47
|
+
}) => void;
|
|
48
|
+
}
|
|
49
|
+
export interface StreamHandle {
|
|
50
|
+
/** The live choreographer. Subscribe for updates. */
|
|
51
|
+
choreographer: CopyChoreographer;
|
|
52
|
+
/** Resolves when the stream ends, however it ends. Never rejects. */
|
|
53
|
+
finished: Promise<CreativeState>;
|
|
54
|
+
/** Stop early. Idempotent. */
|
|
55
|
+
close: () => void;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Fetch the first-paint content.
|
|
59
|
+
*
|
|
60
|
+
* Content-first, rewrite-once: this is what the SDK paints BEFORE any stream
|
|
61
|
+
* exists, so there is never a skeleton on screen. If it fails, the consumer's
|
|
62
|
+
* `fallback` prop is what stands in — which is why that prop is required
|
|
63
|
+
* rather than optional.
|
|
64
|
+
*/
|
|
65
|
+
export declare function fetchContent(target: StreamTarget, options?: {
|
|
66
|
+
signal?: AbortSignal;
|
|
67
|
+
fetchImpl?: typeof fetch;
|
|
68
|
+
}): Promise<ContentSnapshot | null>;
|
|
69
|
+
/**
|
|
70
|
+
* Open an island stream and choreograph it.
|
|
71
|
+
*
|
|
72
|
+
* Returns immediately with a handle; `finished` resolves with the terminal
|
|
73
|
+
* state. It never rejects — a broken stream leaves whatever was painted on
|
|
74
|
+
* screen and reports `phase: "failed"`, because throwing from inside a
|
|
75
|
+
* customer's render tree is a worse outcome than a creative that stopped
|
|
76
|
+
* adapting.
|
|
77
|
+
*/
|
|
78
|
+
export declare function openStream(options: StreamOptions): StreamHandle;
|
|
79
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAcH,OAAO,EAIL,KAAK,YAAY,EAClB,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,iBAAiB,EACjB,KAAK,oBAAoB,EAEzB,KAAK,aAAa,EACnB,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE;QACP,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,GAAG,CAAC,EAAE,MAAM,GAAG;YAAE,IAAI,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;QACjC,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,kBAAkB,CAAC,EAAE,OAAO,CAAC;KAC9B,CAAC;IACF,KAAK,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KAAE,CAAC;IAC5E,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChC;AAED,MAAM,WAAW,aAAc,SAAQ,oBAAoB;IACzD,MAAM,EAAE,YAAY,CAAC;IACrB,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,wEAAwE;IACxE,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IACzB,oCAAoC;IACpC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;IACzC;;;;OAIG;IACH,qBAAqB,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,EAAE,CAAA;KAAE,KAAK,IAAI,CAAC;CACpF;AAED,MAAM,WAAW,YAAY;IAC3B,qDAAqD;IACrD,aAAa,EAAE,iBAAiB,CAAC;IACjC,qEAAqE;IACrE,QAAQ,EAAE,OAAO,CAAC,aAAa,CAAC,CAAC;IACjC,8BAA8B;IAC9B,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB;AAwBD;;;;;;;GAOG;AACH,wBAAsB,YAAY,CAChC,MAAM,EAAE,YAAY,EACpB,OAAO,GAAE;IAAE,MAAM,CAAC,EAAE,WAAW,CAAC;IAAC,SAAS,CAAC,EAAE,OAAO,KAAK,CAAA;CAAO,GAC/D,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAwBjC;AAED;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,aAAa,GAAG,YAAY,CAwG/D"}
|