@scarlett-player/embed 0.5.1 → 0.5.2
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/dist/embed.audio.js +63 -23
- package/dist/embed.audio.js.map +1 -1
- package/dist/embed.audio.umd.cjs +1 -1
- package/dist/embed.audio.umd.cjs.map +1 -1
- package/dist/embed.js +118 -28
- package/dist/embed.js.map +1 -1
- package/dist/embed.umd.cjs +1 -1
- package/dist/embed.umd.cjs.map +1 -1
- package/dist/embed.video.js +73 -8
- package/dist/embed.video.js.map +1 -1
- package/dist/embed.video.umd.cjs +1 -1
- package/dist/embed.video.umd.cjs.map +1 -1
- package/package.json +8 -8
package/dist/embed.audio.js
CHANGED
|
@@ -1006,6 +1006,8 @@ function createStyles(prefix, theme) {
|
|
|
1006
1006
|
align-items: center;
|
|
1007
1007
|
justify-content: center;
|
|
1008
1008
|
transition: background 0.2s, transform 0.1s;
|
|
1009
|
+
min-width: 44px;
|
|
1010
|
+
min-height: 44px;
|
|
1009
1011
|
}
|
|
1010
1012
|
|
|
1011
1013
|
.${prefix}__btn:hover {
|
|
@@ -1155,6 +1157,8 @@ function createAudioUIPlugin(config) {
|
|
|
1155
1157
|
document.head.appendChild(styleElement);
|
|
1156
1158
|
container = document.createElement("div");
|
|
1157
1159
|
container.className = `${prefix} ${prefix}--${layout}`;
|
|
1160
|
+
container.setAttribute("role", "region");
|
|
1161
|
+
container.setAttribute("aria-label", "Audio player");
|
|
1158
1162
|
if (layout === "full") {
|
|
1159
1163
|
container.innerHTML = buildFullLayout();
|
|
1160
1164
|
} else if (layout === "compact") {
|
|
@@ -1189,24 +1193,24 @@ function createAudioUIPlugin(config) {
|
|
|
1189
1193
|
${mergedConfig.showArtist ? `<div class="${prefix}__artist">-</div>` : ""}
|
|
1190
1194
|
</div>
|
|
1191
1195
|
<div class="${prefix}__progress">
|
|
1192
|
-
${mergedConfig.showTime ? `<span class="${prefix}__time ${prefix}__time--current">0:00</span>` : ""}
|
|
1193
|
-
<div class="${prefix}__progress-bar">
|
|
1196
|
+
${mergedConfig.showTime ? `<span class="${prefix}__time ${prefix}__time--current" aria-label="Current time">0:00</span>` : ""}
|
|
1197
|
+
<div class="${prefix}__progress-bar" role="slider" aria-label="Seek" aria-valuemin="0" aria-valuemax="0" aria-valuenow="0" aria-valuetext="0:00" tabindex="0">
|
|
1194
1198
|
<div class="${prefix}__progress-fill" style="transform: scaleX(0)"></div>
|
|
1195
1199
|
</div>
|
|
1196
|
-
${mergedConfig.showTime ? `<span class="${prefix}__time ${prefix}__time--duration">0:00</span>` : ""}
|
|
1200
|
+
${mergedConfig.showTime ? `<span class="${prefix}__time ${prefix}__time--duration" aria-label="Duration">0:00</span>` : ""}
|
|
1197
1201
|
</div>
|
|
1198
|
-
<div class="${prefix}__controls">
|
|
1199
|
-
${mergedConfig.showShuffle ? `<button class="${prefix}__btn ${prefix}__btn--shuffle" title="Shuffle">${ICONS.shuffle}</button>` : ""}
|
|
1200
|
-
${mergedConfig.showNavigation ? `<button class="${prefix}__btn ${prefix}__btn--prev" title="Previous">${ICONS.previous}</button>` : ""}
|
|
1201
|
-
<button class="${prefix}__btn ${prefix}__btn--primary ${prefix}__btn--play" title="Play">${ICONS.play}</button>
|
|
1202
|
-
${mergedConfig.showNavigation ? `<button class="${prefix}__btn ${prefix}__btn--next" title="Next">${ICONS.next}</button>` : ""}
|
|
1203
|
-
${mergedConfig.showRepeat ? `<button class="${prefix}__btn ${prefix}__btn--repeat" title="Repeat">${ICONS.repeatOff}</button>` : ""}
|
|
1202
|
+
<div class="${prefix}__controls" role="group" aria-label="Playback controls">
|
|
1203
|
+
${mergedConfig.showShuffle ? `<button class="${prefix}__btn ${prefix}__btn--shuffle" title="Shuffle" aria-label="Shuffle" aria-pressed="false">${ICONS.shuffle}</button>` : ""}
|
|
1204
|
+
${mergedConfig.showNavigation ? `<button class="${prefix}__btn ${prefix}__btn--prev" title="Previous" aria-label="Previous track">${ICONS.previous}</button>` : ""}
|
|
1205
|
+
<button class="${prefix}__btn ${prefix}__btn--primary ${prefix}__btn--play" title="Play" aria-label="Play">${ICONS.play}</button>
|
|
1206
|
+
${mergedConfig.showNavigation ? `<button class="${prefix}__btn ${prefix}__btn--next" title="Next" aria-label="Next track">${ICONS.next}</button>` : ""}
|
|
1207
|
+
${mergedConfig.showRepeat ? `<button class="${prefix}__btn ${prefix}__btn--repeat" title="Repeat" aria-label="Repeat" aria-pressed="false">${ICONS.repeatOff}</button>` : ""}
|
|
1204
1208
|
</div>
|
|
1205
1209
|
${mergedConfig.showVolume ? `
|
|
1206
1210
|
<div class="${prefix}__secondary-controls">
|
|
1207
|
-
<div class="${prefix}__volume">
|
|
1208
|
-
<button class="${prefix}__btn ${prefix}__btn--volume" title="Volume">${ICONS.volumeHigh}</button>
|
|
1209
|
-
<div class="${prefix}__volume-slider">
|
|
1211
|
+
<div class="${prefix}__volume" role="group" aria-label="Volume controls">
|
|
1212
|
+
<button class="${prefix}__btn ${prefix}__btn--volume" title="Volume" aria-label="Mute">${ICONS.volumeHigh}</button>
|
|
1213
|
+
<div class="${prefix}__volume-slider" role="slider" aria-label="Volume" aria-valuemin="0" aria-valuemax="100" aria-valuenow="100" aria-valuetext="100%" tabindex="0">
|
|
1210
1214
|
<div class="${prefix}__volume-fill" style="width: 100%"></div>
|
|
1211
1215
|
</div>
|
|
1212
1216
|
</div>
|
|
@@ -1225,21 +1229,21 @@ function createAudioUIPlugin(config) {
|
|
|
1225
1229
|
${mergedConfig.showTitle ? `<div class="${prefix}__title">-</div>` : ""}
|
|
1226
1230
|
${mergedConfig.showArtist ? `<div class="${prefix}__artist">-</div>` : ""}
|
|
1227
1231
|
<div class="${prefix}__progress">
|
|
1228
|
-
<div class="${prefix}__progress-bar">
|
|
1232
|
+
<div class="${prefix}__progress-bar" role="slider" aria-label="Seek" aria-valuemin="0" aria-valuemax="0" aria-valuenow="0" aria-valuetext="0:00" tabindex="0">
|
|
1229
1233
|
<div class="${prefix}__progress-fill" style="transform: scaleX(0)"></div>
|
|
1230
1234
|
</div>
|
|
1231
1235
|
</div>
|
|
1232
1236
|
</div>
|
|
1233
|
-
<div class="${prefix}__controls">
|
|
1234
|
-
${mergedConfig.showNavigation ? `<button class="${prefix}__btn ${prefix}__btn--prev" title="Previous">${ICONS.previous}</button>` : ""}
|
|
1235
|
-
<button class="${prefix}__btn ${prefix}__btn--primary ${prefix}__btn--play" title="Play">${ICONS.play}</button>
|
|
1236
|
-
${mergedConfig.showNavigation ? `<button class="${prefix}__btn ${prefix}__btn--next" title="Next">${ICONS.next}</button>` : ""}
|
|
1237
|
+
<div class="${prefix}__controls" role="group" aria-label="Playback controls">
|
|
1238
|
+
${mergedConfig.showNavigation ? `<button class="${prefix}__btn ${prefix}__btn--prev" title="Previous" aria-label="Previous track">${ICONS.previous}</button>` : ""}
|
|
1239
|
+
<button class="${prefix}__btn ${prefix}__btn--primary ${prefix}__btn--play" title="Play" aria-label="Play">${ICONS.play}</button>
|
|
1240
|
+
${mergedConfig.showNavigation ? `<button class="${prefix}__btn ${prefix}__btn--next" title="Next" aria-label="Next track">${ICONS.next}</button>` : ""}
|
|
1237
1241
|
</div>
|
|
1238
1242
|
`;
|
|
1239
1243
|
};
|
|
1240
1244
|
const buildMiniLayout = () => {
|
|
1241
1245
|
return `
|
|
1242
|
-
<button class="${prefix}__btn ${prefix}__btn--primary ${prefix}__btn--play" title="Play">${ICONS.play}</button>
|
|
1246
|
+
<button class="${prefix}__btn ${prefix}__btn--primary ${prefix}__btn--play" title="Play" aria-label="Play">${ICONS.play}</button>
|
|
1243
1247
|
${mergedConfig.showArtwork ? `
|
|
1244
1248
|
<div class="${prefix}__artwork">
|
|
1245
1249
|
<img src="${mergedConfig.defaultArtwork || ""}" alt="Album art" />
|
|
@@ -1248,7 +1252,7 @@ function createAudioUIPlugin(config) {
|
|
|
1248
1252
|
<div class="${prefix}__info">
|
|
1249
1253
|
${mergedConfig.showTitle ? `<div class="${prefix}__title-wrapper"><div class="${prefix}__title">-</div></div>` : ""}
|
|
1250
1254
|
<div class="${prefix}__progress">
|
|
1251
|
-
<div class="${prefix}__progress-bar">
|
|
1255
|
+
<div class="${prefix}__progress-bar" role="slider" aria-label="Seek" aria-valuemin="0" aria-valuemax="0" aria-valuenow="0" aria-valuetext="0:00" tabindex="0">
|
|
1252
1256
|
<div class="${prefix}__progress-fill" style="transform: scaleX(0)"></div>
|
|
1253
1257
|
</div>
|
|
1254
1258
|
</div>
|
|
@@ -1314,6 +1318,7 @@ function createAudioUIPlugin(config) {
|
|
|
1314
1318
|
if (playPauseBtn) {
|
|
1315
1319
|
playPauseBtn.innerHTML = playing ? ICONS.pause : ICONS.play;
|
|
1316
1320
|
playPauseBtn.title = playing ? "Pause" : "Play";
|
|
1321
|
+
playPauseBtn.setAttribute("aria-label", playing ? "Pause" : "Play");
|
|
1317
1322
|
}
|
|
1318
1323
|
const currentTime = api.getState("currentTime") || 0;
|
|
1319
1324
|
const duration = api.getState("duration") || 0;
|
|
@@ -1336,6 +1341,12 @@ function createAudioUIPlugin(config) {
|
|
|
1336
1341
|
if (durationEl) {
|
|
1337
1342
|
durationEl.textContent = formatTime(duration);
|
|
1338
1343
|
}
|
|
1344
|
+
const progressBar = container?.querySelector(`.${prefix}__progress-bar`);
|
|
1345
|
+
if (progressBar) {
|
|
1346
|
+
progressBar.setAttribute("aria-valuemax", String(Math.floor(duration)));
|
|
1347
|
+
progressBar.setAttribute("aria-valuenow", String(Math.floor(currentTime)));
|
|
1348
|
+
progressBar.setAttribute("aria-valuetext", formatTime(currentTime));
|
|
1349
|
+
}
|
|
1339
1350
|
const title = api.getState("title");
|
|
1340
1351
|
const poster = api.getState("poster");
|
|
1341
1352
|
if (titleEl && title) {
|
|
@@ -1360,21 +1371,34 @@ function createAudioUIPlugin(config) {
|
|
|
1360
1371
|
}
|
|
1361
1372
|
if (volumeBtn) {
|
|
1362
1373
|
volumeBtn.innerHTML = muted || volume === 0 ? ICONS.volumeMuted : ICONS.volumeHigh;
|
|
1374
|
+
volumeBtn.setAttribute("aria-label", muted || volume === 0 ? "Unmute" : "Mute");
|
|
1375
|
+
}
|
|
1376
|
+
const volumeSlider = container?.querySelector(`.${prefix}__volume-slider`);
|
|
1377
|
+
if (volumeSlider) {
|
|
1378
|
+
const displayVolume = Math.round((muted ? 0 : volume) * 100);
|
|
1379
|
+
volumeSlider.setAttribute("aria-valuenow", String(displayVolume));
|
|
1380
|
+
volumeSlider.setAttribute("aria-valuetext", `${displayVolume}%`);
|
|
1363
1381
|
}
|
|
1364
1382
|
const playlist = api.getPlugin("playlist");
|
|
1365
1383
|
if (playlist) {
|
|
1366
1384
|
const state = playlist.getState();
|
|
1367
1385
|
if (shuffleBtn) {
|
|
1368
1386
|
shuffleBtn.classList.toggle(`${prefix}__btn--active`, state.shuffle);
|
|
1387
|
+
shuffleBtn.setAttribute("aria-pressed", String(state.shuffle));
|
|
1388
|
+
shuffleBtn.setAttribute("aria-label", state.shuffle ? "Shuffle on" : "Shuffle off");
|
|
1369
1389
|
}
|
|
1370
1390
|
if (repeatBtn) {
|
|
1371
1391
|
repeatBtn.classList.toggle(`${prefix}__btn--active`, state.repeat !== "none");
|
|
1392
|
+
repeatBtn.setAttribute("aria-pressed", String(state.repeat !== "none"));
|
|
1372
1393
|
if (state.repeat === "one") {
|
|
1373
1394
|
repeatBtn.innerHTML = ICONS.repeatOne;
|
|
1395
|
+
repeatBtn.setAttribute("aria-label", "Repeat one");
|
|
1374
1396
|
} else if (state.repeat === "all") {
|
|
1375
1397
|
repeatBtn.innerHTML = ICONS.repeatAll;
|
|
1398
|
+
repeatBtn.setAttribute("aria-label", "Repeat all");
|
|
1376
1399
|
} else {
|
|
1377
1400
|
repeatBtn.innerHTML = ICONS.repeatOff;
|
|
1401
|
+
repeatBtn.setAttribute("aria-label", "Repeat off");
|
|
1378
1402
|
}
|
|
1379
1403
|
}
|
|
1380
1404
|
}
|
|
@@ -3595,6 +3619,7 @@ class ScarlettPlayer {
|
|
|
3595
3619
|
this.destroyed = false;
|
|
3596
3620
|
this.seekingWhilePlaying = false;
|
|
3597
3621
|
this.seekResumeTimeout = null;
|
|
3622
|
+
this.loadGeneration = 0;
|
|
3598
3623
|
if (typeof options.container === "string") {
|
|
3599
3624
|
const el = document.querySelector(options.container);
|
|
3600
3625
|
if (!el || !(el instanceof HTMLElement)) {
|
|
@@ -3668,6 +3693,7 @@ class ScarlettPlayer {
|
|
|
3668
3693
|
*/
|
|
3669
3694
|
async load(source) {
|
|
3670
3695
|
this.checkDestroyed();
|
|
3696
|
+
const generation = ++this.loadGeneration;
|
|
3671
3697
|
try {
|
|
3672
3698
|
this.logger.info("Loading source", { source });
|
|
3673
3699
|
this.stateManager.update({
|
|
@@ -3686,6 +3712,10 @@ class ScarlettPlayer {
|
|
|
3686
3712
|
await this.pluginManager.destroyPlugin(previousProviderId);
|
|
3687
3713
|
this._currentProvider = null;
|
|
3688
3714
|
}
|
|
3715
|
+
if (generation !== this.loadGeneration) {
|
|
3716
|
+
this.logger.info("Load superseded by newer load call", { source });
|
|
3717
|
+
return;
|
|
3718
|
+
}
|
|
3689
3719
|
const provider = this.pluginManager.selectProvider(source);
|
|
3690
3720
|
if (!provider) {
|
|
3691
3721
|
this.errorHandler.throw(
|
|
@@ -3701,18 +3731,28 @@ class ScarlettPlayer {
|
|
|
3701
3731
|
this._currentProvider = provider;
|
|
3702
3732
|
this.logger.info("Provider selected", { provider: provider.id });
|
|
3703
3733
|
await this.pluginManager.initPlugin(provider.id);
|
|
3734
|
+
if (generation !== this.loadGeneration) {
|
|
3735
|
+
this.logger.info("Load superseded by newer load call", { source });
|
|
3736
|
+
return;
|
|
3737
|
+
}
|
|
3704
3738
|
this.stateManager.set("source", { src: source, type: this.detectMimeType(source) });
|
|
3705
3739
|
if (typeof provider.loadSource === "function") {
|
|
3706
3740
|
await provider.loadSource(source);
|
|
3707
3741
|
}
|
|
3742
|
+
if (generation !== this.loadGeneration) {
|
|
3743
|
+
this.logger.info("Load superseded by newer load call", { source });
|
|
3744
|
+
return;
|
|
3745
|
+
}
|
|
3708
3746
|
if (this.stateManager.getValue("autoplay")) {
|
|
3709
3747
|
await this.play();
|
|
3710
3748
|
}
|
|
3711
3749
|
} catch (error) {
|
|
3712
|
-
this.
|
|
3713
|
-
|
|
3714
|
-
|
|
3715
|
-
|
|
3750
|
+
if (generation === this.loadGeneration) {
|
|
3751
|
+
this.errorHandler.handle(error, {
|
|
3752
|
+
operation: "load",
|
|
3753
|
+
source
|
|
3754
|
+
});
|
|
3755
|
+
}
|
|
3716
3756
|
}
|
|
3717
3757
|
}
|
|
3718
3758
|
/**
|