vidply 1.0.20 → 1.0.21

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.
@@ -11,27 +11,27 @@
11
11
  "format": "esm"
12
12
  },
13
13
  "src/i18n/languages/en.js": {
14
- "bytes": 6319,
14
+ "bytes": 6566,
15
15
  "imports": [],
16
16
  "format": "esm"
17
17
  },
18
18
  "src/i18n/languages/de.js": {
19
- "bytes": 7774,
19
+ "bytes": 8063,
20
20
  "imports": [],
21
21
  "format": "esm"
22
22
  },
23
23
  "src/i18n/languages/es.js": {
24
- "bytes": 7346,
24
+ "bytes": 7619,
25
25
  "imports": [],
26
26
  "format": "esm"
27
27
  },
28
28
  "src/i18n/languages/fr.js": {
29
- "bytes": 7560,
29
+ "bytes": 7826,
30
30
  "imports": [],
31
31
  "format": "esm"
32
32
  },
33
33
  "src/i18n/languages/ja.js": {
34
- "bytes": 7972,
34
+ "bytes": 8251,
35
35
  "imports": [],
36
36
  "format": "esm"
37
37
  },
@@ -99,7 +99,7 @@
99
99
  "format": "esm"
100
100
  },
101
101
  "src/controls/ControlBar.js": {
102
- "bytes": 129888,
102
+ "bytes": 129940,
103
103
  "imports": [
104
104
  {
105
105
  "path": "src/utils/DOMUtils.js",
@@ -269,22 +269,22 @@
269
269
  "format": "esm"
270
270
  },
271
271
  "src/renderers/HTML5Renderer.js": {
272
- "bytes": 8660,
272
+ "bytes": 9169,
273
273
  "imports": [],
274
274
  "format": "esm"
275
275
  },
276
276
  "src/renderers/YouTubeRenderer.js": {
277
- "bytes": 7186,
277
+ "bytes": 7465,
278
278
  "imports": [],
279
279
  "format": "esm"
280
280
  },
281
281
  "src/renderers/VimeoRenderer.js": {
282
- "bytes": 6699,
282
+ "bytes": 6978,
283
283
  "imports": [],
284
284
  "format": "esm"
285
285
  },
286
286
  "src/renderers/HLSRenderer.js": {
287
- "bytes": 8757,
287
+ "bytes": 9492,
288
288
  "imports": [
289
289
  {
290
290
  "path": "src/renderers/HTML5Renderer.js",
@@ -295,7 +295,7 @@
295
295
  "format": "esm"
296
296
  },
297
297
  "src/core/Player.js": {
298
- "bytes": 205467,
298
+ "bytes": 208826,
299
299
  "imports": [
300
300
  {
301
301
  "path": "src/utils/EventEmitter.js",
@@ -386,7 +386,7 @@
386
386
  "format": "esm"
387
387
  },
388
388
  "src/features/PlaylistManager.js": {
389
- "bytes": 28703,
389
+ "bytes": 32072,
390
390
  "imports": [
391
391
  {
392
392
  "path": "src/utils/DOMUtils.js",
@@ -397,6 +397,11 @@
397
397
  "path": "src/icons/Icons.js",
398
398
  "kind": "import-statement",
399
399
  "original": "../icons/Icons.js"
400
+ },
401
+ {
402
+ "path": "src/i18n/i18n.js",
403
+ "kind": "import-statement",
404
+ "original": "../i18n/i18n.js"
400
405
  }
401
406
  ],
402
407
  "format": "esm"
@@ -429,7 +434,7 @@
429
434
  "entryPoint": "src/index.js",
430
435
  "inputs": {
431
436
  "src/renderers/HTML5Renderer.js": {
432
- "bytesInOutput": 4675
437
+ "bytesInOutput": 4803
433
438
  },
434
439
  "src/utils/EventEmitter.js": {
435
440
  "bytesInOutput": 436
@@ -438,19 +443,19 @@
438
443
  "bytesInOutput": 1581
439
444
  },
440
445
  "src/i18n/languages/en.js": {
441
- "bytesInOutput": 5230
446
+ "bytesInOutput": 5426
442
447
  },
443
448
  "src/i18n/languages/de.js": {
444
- "bytesInOutput": 6298
449
+ "bytesInOutput": 6510
445
450
  },
446
451
  "src/i18n/languages/es.js": {
447
- "bytesInOutput": 6411
452
+ "bytesInOutput": 6637
448
453
  },
449
454
  "src/i18n/languages/fr.js": {
450
- "bytesInOutput": 6680
455
+ "bytesInOutput": 6895
451
456
  },
452
457
  "src/i18n/languages/ja.js": {
453
- "bytesInOutput": 11448
458
+ "bytesInOutput": 11757
454
459
  },
455
460
  "src/i18n/translations.js": {
456
461
  "bytesInOutput": 64
@@ -468,7 +473,7 @@
468
473
  "bytesInOutput": 222
469
474
  },
470
475
  "src/controls/ControlBar.js": {
471
- "bytesInOutput": 54429
476
+ "bytesInOutput": 54457
472
477
  },
473
478
  "src/utils/StorageManager.js": {
474
479
  "bytesInOutput": 1606
@@ -495,25 +500,25 @@
495
500
  "bytesInOutput": 41981
496
501
  },
497
502
  "src/core/Player.js": {
498
- "bytesInOutput": 73997
503
+ "bytesInOutput": 74975
499
504
  },
500
505
  "src/renderers/YouTubeRenderer.js": {
501
- "bytesInOutput": 4140
506
+ "bytesInOutput": 4203
502
507
  },
503
508
  "src/renderers/VimeoRenderer.js": {
504
- "bytesInOutput": 4205
509
+ "bytesInOutput": 4268
505
510
  },
506
511
  "src/renderers/HLSRenderer.js": {
507
- "bytesInOutput": 5389
512
+ "bytesInOutput": 5583
508
513
  },
509
514
  "src/features/PlaylistManager.js": {
510
- "bytesInOutput": 13260
515
+ "bytesInOutput": 14667
511
516
  },
512
517
  "src/index.js": {
513
518
  "bytesInOutput": 1869
514
519
  }
515
520
  },
516
- "bytes": 285961
521
+ "bytes": 289980
517
522
  }
518
523
  }
519
524
  }
package/dist/vidply.js CHANGED
@@ -141,14 +141,21 @@ var VidPly = (() => {
141
141
  });
142
142
  }
143
143
  play() {
144
+ const scrollX = window.scrollX;
145
+ const scrollY = window.scrollY;
144
146
  const promise = this.media.play();
147
+ window.scrollTo(scrollX, scrollY);
145
148
  if (promise !== void 0) {
146
149
  promise.catch((error) => {
147
150
  this.player.log("Play failed:", error, "warn");
148
151
  if (this.player.options.autoplay && !this.player.state.muted) {
149
152
  this.player.log("Retrying play with muted audio", "info");
150
153
  this.media.muted = true;
151
- this.media.play().catch((err) => {
154
+ const retryScrollX = window.scrollX;
155
+ const retryScrollY = window.scrollY;
156
+ this.media.play().then(() => {
157
+ window.scrollTo(retryScrollX, retryScrollY);
158
+ }).catch((err) => {
152
159
  this.player.handleError(err);
153
160
  });
154
161
  }
@@ -578,6 +585,14 @@ var VidPly = (() => {
578
585
  minutes: "{count} minutes",
579
586
  second: "{count} second",
580
587
  seconds: "{count} seconds"
588
+ },
589
+ playlist: {
590
+ title: "Playlist",
591
+ trackOf: "Track {current} of {total}",
592
+ nowPlaying: "Now playing: Track {current} of {total}. {title}{artist}",
593
+ by: " by ",
594
+ untitled: "Untitled",
595
+ trackUntitled: "Track {number}"
581
596
  }
582
597
  };
583
598
 
@@ -737,6 +752,14 @@ var VidPly = (() => {
737
752
  minutes: "{count} Minuten",
738
753
  second: "{count} Sekunde",
739
754
  seconds: "{count} Sekunden"
755
+ },
756
+ playlist: {
757
+ title: "Wiedergabeliste",
758
+ trackOf: "Titel {current} von {total}",
759
+ nowPlaying: "L\xE4uft gerade: Titel {current} von {total}. {title}{artist}",
760
+ by: " von ",
761
+ untitled: "Ohne Titel",
762
+ trackUntitled: "Titel {number}"
740
763
  }
741
764
  };
742
765
 
@@ -896,6 +919,14 @@ var VidPly = (() => {
896
919
  minutes: "{count} minutos",
897
920
  second: "{count} segundo",
898
921
  seconds: "{count} segundos"
922
+ },
923
+ playlist: {
924
+ title: "Lista de reproducci\xF3n",
925
+ trackOf: "Pista {current} de {total}",
926
+ nowPlaying: "Reproduciendo ahora: Pista {current} de {total}. {title}{artist}",
927
+ by: " por ",
928
+ untitled: "Sin t\xEDtulo",
929
+ trackUntitled: "Pista {number}"
899
930
  }
900
931
  };
901
932
 
@@ -1055,6 +1086,14 @@ var VidPly = (() => {
1055
1086
  minutes: "{count} minutes",
1056
1087
  second: "{count} seconde",
1057
1088
  seconds: "{count} secondes"
1089
+ },
1090
+ playlist: {
1091
+ title: "Liste de lecture",
1092
+ trackOf: "Piste {current} sur {total}",
1093
+ nowPlaying: "Lecture en cours : Piste {current} sur {total}. {title}{artist}",
1094
+ by: " par ",
1095
+ untitled: "Sans titre",
1096
+ trackUntitled: "Piste {number}"
1058
1097
  }
1059
1098
  };
1060
1099
 
@@ -1214,6 +1253,14 @@ var VidPly = (() => {
1214
1253
  minutes: "{count}\u5206",
1215
1254
  second: "{count}\u79D2",
1216
1255
  seconds: "{count}\u79D2"
1256
+ },
1257
+ playlist: {
1258
+ title: "\u30D7\u30EC\u30A4\u30EA\u30B9\u30C8",
1259
+ trackOf: "\u30C8\u30E9\u30C3\u30AF {current}/{total}",
1260
+ nowPlaying: "\u518D\u751F\u4E2D: \u30C8\u30E9\u30C3\u30AF {current}/{total}. {title}{artist}",
1261
+ by: " - ",
1262
+ untitled: "\u30BF\u30A4\u30C8\u30EB\u306A\u3057",
1263
+ trackUntitled: "\u30C8\u30E9\u30C3\u30AF {number}"
1217
1264
  }
1218
1265
  };
1219
1266
 
@@ -2700,7 +2747,8 @@ var VidPly = (() => {
2700
2747
  attributes: {
2701
2748
  "type": "button",
2702
2749
  "aria-label": i18n.t("player.quality"),
2703
- "aria-expanded": "false"
2750
+ "aria-expanded": "false",
2751
+ "title": i18n.t("player.quality")
2704
2752
  }
2705
2753
  });
2706
2754
  button.appendChild(createIconElement("hd"));
@@ -7243,7 +7291,10 @@ var VidPly = (() => {
7243
7291
  }
7244
7292
  play() {
7245
7293
  if (this.isReady && this.youtube) {
7294
+ const scrollX = window.scrollX;
7295
+ const scrollY = window.scrollY;
7246
7296
  this.youtube.playVideo();
7297
+ window.scrollTo(scrollX, scrollY);
7247
7298
  }
7248
7299
  }
7249
7300
  pause() {
@@ -7437,9 +7488,12 @@ var VidPly = (() => {
7437
7488
  }
7438
7489
  play() {
7439
7490
  if (this.isReady && this.vimeo) {
7491
+ const scrollX = window.scrollX;
7492
+ const scrollY = window.scrollY;
7440
7493
  this.vimeo.play().catch((error) => {
7441
7494
  this.player.log("Play error:", error, "warn");
7442
7495
  });
7496
+ window.scrollTo(scrollX, scrollY);
7443
7497
  }
7444
7498
  }
7445
7499
  pause() {
@@ -7512,6 +7566,11 @@ var VidPly = (() => {
7512
7566
  }
7513
7567
  }
7514
7568
  canPlayNatively() {
7569
+ const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
7570
+ const isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;
7571
+ if (!isSafari && !isIOS) {
7572
+ return false;
7573
+ }
7515
7574
  const video = document.createElement("video");
7516
7575
  return video.canPlayType("application/vnd.apple.mpegurl") !== "";
7517
7576
  }
@@ -7686,7 +7745,10 @@ var VidPly = (() => {
7686
7745
  }
7687
7746
  }
7688
7747
  play() {
7748
+ const scrollX = window.scrollX;
7749
+ const scrollY = window.scrollY;
7689
7750
  const promise = this.media.play();
7751
+ window.scrollTo(scrollX, scrollY);
7690
7752
  if (promise !== void 0) {
7691
7753
  promise.catch((error) => {
7692
7754
  this.player.log("Play failed:", error, "warn");
@@ -8036,6 +8098,16 @@ var VidPly = (() => {
8036
8098
  className: `${this.options.classPrefix}-video-wrapper`
8037
8099
  });
8038
8100
  this.element.parentNode.insertBefore(this.container, this.element);
8101
+ if (this.element.tagName === "AUDIO" && this.options.poster) {
8102
+ this.trackArtworkElement = DOMUtils.createElement("div", {
8103
+ className: `${this.options.classPrefix}-track-artwork`,
8104
+ attributes: {
8105
+ "aria-hidden": "true"
8106
+ }
8107
+ });
8108
+ this.trackArtworkElement.style.backgroundImage = `url(${this.options.poster})`;
8109
+ this.container.appendChild(this.trackArtworkElement);
8110
+ }
8039
8111
  this.container.appendChild(this.videoWrapper);
8040
8112
  this.videoWrapper.appendChild(this.element);
8041
8113
  this.element.controls = false;
@@ -8344,6 +8416,8 @@ var VidPly = (() => {
8344
8416
  * @param {string} config.type - Media MIME type
8345
8417
  * @param {string} [config.poster] - Poster image URL
8346
8418
  * @param {Array} [config.tracks] - Text tracks (captions, chapters, etc.)
8419
+ * @param {string} [config.audioDescriptionSrc] - Audio description video URL
8420
+ * @param {string} [config.signLanguageSrc] - Sign language video URL
8347
8421
  */
8348
8422
  async load(config) {
8349
8423
  try {
@@ -8351,6 +8425,8 @@ var VidPly = (() => {
8351
8425
  if (this.renderer) {
8352
8426
  this.pause();
8353
8427
  }
8428
+ const scrollX = window.scrollX || window.pageXOffset;
8429
+ const scrollY = window.scrollY || window.pageYOffset;
8354
8430
  const existingTracks = this.trackElements;
8355
8431
  existingTracks.forEach((track) => track.remove());
8356
8432
  this.invalidateTrackCache();
@@ -8375,6 +8451,17 @@ var VidPly = (() => {
8375
8451
  });
8376
8452
  this.invalidateTrackCache();
8377
8453
  }
8454
+ const wasSignLanguageEnabled = this.state.signLanguageEnabled;
8455
+ const wasAudioDescriptionEnabled = this.state.audioDescriptionEnabled;
8456
+ this.audioDescriptionSrc = config.audioDescriptionSrc || null;
8457
+ this.signLanguageSrc = config.signLanguageSrc || null;
8458
+ this.originalSrc = config.src;
8459
+ if (wasAudioDescriptionEnabled) {
8460
+ this.disableAudioDescription();
8461
+ }
8462
+ if (wasSignLanguageEnabled) {
8463
+ this.disableSignLanguage();
8464
+ }
8378
8465
  const shouldChangeRenderer = this.shouldChangeRenderer(config.src);
8379
8466
  if (shouldChangeRenderer && this.renderer) {
8380
8467
  this.renderer.destroy();
@@ -8386,21 +8473,35 @@ var VidPly = (() => {
8386
8473
  this.renderer.media = this.element;
8387
8474
  this.element.load();
8388
8475
  }
8476
+ window.scrollTo(scrollX, scrollY);
8389
8477
  if (this.captionManager) {
8390
8478
  this.captionManager.destroy();
8391
8479
  this.captionManager = new CaptionManager(this);
8392
8480
  }
8393
8481
  if (this.transcriptManager) {
8394
- const wasVisible = this.transcriptManager.isVisible;
8482
+ const wasTranscriptVisible = this.transcriptManager.isVisible;
8395
8483
  this.transcriptManager.destroy();
8396
8484
  this.transcriptManager = new TranscriptManager(this);
8397
- if (wasVisible) {
8485
+ if (wasTranscriptVisible && this.controlBar && this.controlBar.hasCaptionTracks()) {
8398
8486
  this.transcriptManager.showTranscript();
8399
8487
  }
8400
8488
  }
8401
8489
  if (this.controlBar) {
8402
8490
  this.updateControlBar();
8403
8491
  }
8492
+ window.scrollTo(scrollX, scrollY);
8493
+ if (wasSignLanguageEnabled && this.signLanguageSrc) {
8494
+ setTimeout(() => {
8495
+ this.enableSignLanguage();
8496
+ window.scrollTo(scrollX, scrollY);
8497
+ }, 150);
8498
+ }
8499
+ if (wasAudioDescriptionEnabled && this.audioDescriptionSrc) {
8500
+ setTimeout(() => {
8501
+ this.enableAudioDescription();
8502
+ window.scrollTo(scrollX, scrollY);
8503
+ }, 150);
8504
+ }
8404
8505
  this.emit("sourcechange", config);
8405
8506
  this.log("Media loaded successfully");
8406
8507
  } catch (error) {
@@ -8422,6 +8523,7 @@ var VidPly = (() => {
8422
8523
  controlBar.createControls();
8423
8524
  controlBar.attachEvents();
8424
8525
  controlBar.setupAutoHide();
8526
+ controlBar.setupOverflowDetection();
8425
8527
  }
8426
8528
  shouldChangeRenderer(src) {
8427
8529
  if (!this.renderer) return true;
@@ -11166,6 +11268,7 @@ var VidPly = (() => {
11166
11268
  this.trackInfoElement = null;
11167
11269
  this.navigationFeedback = null;
11168
11270
  this.isPanelVisible = this.options.showPanel !== false;
11271
+ this.isChangingTrack = false;
11169
11272
  this.handleTrackEnd = this.handleTrackEnd.bind(this);
11170
11273
  this.handleTrackError = this.handleTrackError.bind(this);
11171
11274
  this.player.playlistManager = this;
@@ -11289,12 +11392,15 @@ var VidPly = (() => {
11289
11392
  return;
11290
11393
  }
11291
11394
  const track = this.tracks[index];
11395
+ this.isChangingTrack = true;
11292
11396
  this.currentIndex = index;
11293
11397
  this.player.load({
11294
11398
  src: track.src,
11295
11399
  type: track.type,
11296
11400
  poster: track.poster,
11297
- tracks: track.tracks || []
11401
+ tracks: track.tracks || [],
11402
+ audioDescriptionSrc: track.audioDescriptionSrc || null,
11403
+ signLanguageSrc: track.signLanguageSrc || null
11298
11404
  });
11299
11405
  this.updateTrackInfo(track);
11300
11406
  this.updatePlaylistUI();
@@ -11303,6 +11409,9 @@ var VidPly = (() => {
11303
11409
  item: track,
11304
11410
  total: this.tracks.length
11305
11411
  });
11412
+ setTimeout(() => {
11413
+ this.isChangingTrack = false;
11414
+ }, 150);
11306
11415
  }
11307
11416
  /**
11308
11417
  * Play a specific track
@@ -11315,12 +11424,15 @@ var VidPly = (() => {
11315
11424
  return;
11316
11425
  }
11317
11426
  const track = this.tracks[index];
11427
+ this.isChangingTrack = true;
11318
11428
  this.currentIndex = index;
11319
11429
  this.player.load({
11320
11430
  src: track.src,
11321
11431
  type: track.type,
11322
11432
  poster: track.poster,
11323
- tracks: track.tracks || []
11433
+ tracks: track.tracks || [],
11434
+ audioDescriptionSrc: track.audioDescriptionSrc || null,
11435
+ signLanguageSrc: track.signLanguageSrc || null
11324
11436
  });
11325
11437
  this.updateTrackInfo(track);
11326
11438
  this.updatePlaylistUI();
@@ -11331,6 +11443,9 @@ var VidPly = (() => {
11331
11443
  });
11332
11444
  setTimeout(() => {
11333
11445
  this.player.play();
11446
+ setTimeout(() => {
11447
+ this.isChangingTrack = false;
11448
+ }, 50);
11334
11449
  }, 100);
11335
11450
  }
11336
11451
  /**
@@ -11365,6 +11480,9 @@ var VidPly = (() => {
11365
11480
  * Handle track end
11366
11481
  */
11367
11482
  handleTrackEnd() {
11483
+ if (this.isChangingTrack) {
11484
+ return;
11485
+ }
11368
11486
  if (this.options.autoAdvance) {
11369
11487
  this.next();
11370
11488
  }
@@ -11433,6 +11551,21 @@ var VidPly = (() => {
11433
11551
  console.warn("VidPly Playlist: No container found");
11434
11552
  return;
11435
11553
  }
11554
+ if (this.player.element.tagName === "AUDIO") {
11555
+ this.trackArtworkElement = DOMUtils.createElement("div", {
11556
+ className: "vidply-track-artwork",
11557
+ attributes: {
11558
+ "aria-hidden": "true"
11559
+ }
11560
+ });
11561
+ this.trackArtworkElement.style.display = "none";
11562
+ const videoWrapper = this.container.querySelector(".vidply-video-wrapper");
11563
+ if (videoWrapper) {
11564
+ this.container.insertBefore(this.trackArtworkElement, videoWrapper);
11565
+ } else {
11566
+ this.container.appendChild(this.trackArtworkElement);
11567
+ }
11568
+ }
11436
11569
  this.trackInfoElement = DOMUtils.createElement("div", {
11437
11570
  className: "vidply-track-info",
11438
11571
  attributes: {
@@ -11457,7 +11590,7 @@ var VidPly = (() => {
11457
11590
  attributes: {
11458
11591
  id: `${this.uniqueId}-panel`,
11459
11592
  role: "region",
11460
- "aria-label": "Media playlist",
11593
+ "aria-label": i18n.t("playlist.title"),
11461
11594
  "aria-labelledby": `${this.uniqueId}-heading`
11462
11595
  }
11463
11596
  });
@@ -11471,16 +11604,39 @@ var VidPly = (() => {
11471
11604
  if (!this.trackInfoElement) return;
11472
11605
  const trackNumber = this.currentIndex + 1;
11473
11606
  const totalTracks = this.tracks.length;
11474
- const trackTitle = track.title || "Untitled";
11607
+ const trackTitle = track.title || i18n.t("playlist.untitled");
11475
11608
  const trackArtist = track.artist || "";
11476
- const announcement = `Now playing: Track ${trackNumber} of ${totalTracks}. ${trackTitle}${trackArtist ? " by " + trackArtist : ""}`;
11609
+ const artistPart = trackArtist ? i18n.t("playlist.by") + trackArtist : "";
11610
+ const announcement = i18n.t("playlist.nowPlaying", {
11611
+ current: trackNumber,
11612
+ total: totalTracks,
11613
+ title: trackTitle,
11614
+ artist: artistPart
11615
+ });
11616
+ const trackOfText = i18n.t("playlist.trackOf", {
11617
+ current: trackNumber,
11618
+ total: totalTracks
11619
+ });
11477
11620
  this.trackInfoElement.innerHTML = `
11478
11621
  <span class="vidply-sr-only">${DOMUtils.escapeHTML(announcement)}</span>
11479
- <div class="vidply-track-number" aria-hidden="true">Track ${trackNumber} of ${totalTracks}</div>
11622
+ <div class="vidply-track-number" aria-hidden="true">${DOMUtils.escapeHTML(trackOfText)}</div>
11480
11623
  <div class="vidply-track-title" aria-hidden="true">${DOMUtils.escapeHTML(trackTitle)}</div>
11481
11624
  ${trackArtist ? `<div class="vidply-track-artist" aria-hidden="true">${DOMUtils.escapeHTML(trackArtist)}</div>` : ""}
11482
11625
  `;
11483
11626
  this.trackInfoElement.style.display = "block";
11627
+ this.updateTrackArtwork(track);
11628
+ }
11629
+ /**
11630
+ * Update track artwork display (for audio playlists)
11631
+ */
11632
+ updateTrackArtwork(track) {
11633
+ if (!this.trackArtworkElement) return;
11634
+ if (track.poster) {
11635
+ this.trackArtworkElement.style.backgroundImage = `url(${track.poster})`;
11636
+ this.trackArtworkElement.style.display = "block";
11637
+ } else {
11638
+ this.trackArtworkElement.style.display = "none";
11639
+ }
11484
11640
  }
11485
11641
  /**
11486
11642
  * Render playlist
@@ -11494,7 +11650,7 @@ var VidPly = (() => {
11494
11650
  id: `${this.uniqueId}-heading`
11495
11651
  }
11496
11652
  });
11497
- header.textContent = `Playlist (${this.tracks.length})`;
11653
+ header.textContent = `${i18n.t("playlist.title")} (${this.tracks.length})`;
11498
11654
  this.playlistPanel.appendChild(header);
11499
11655
  const instructions = DOMUtils.createElement("div", {
11500
11656
  className: "vidply-sr-only",
@@ -11524,9 +11680,12 @@ var VidPly = (() => {
11524
11680
  * Create playlist item element
11525
11681
  */
11526
11682
  createPlaylistItem(track, index) {
11527
- const trackPosition = `Track ${index + 1} of ${this.tracks.length}`;
11528
- const trackTitle = track.title || `Track ${index + 1}`;
11529
- const trackArtist = track.artist ? ` by ${track.artist}` : "";
11683
+ const trackPosition = i18n.t("playlist.trackOf", {
11684
+ current: index + 1,
11685
+ total: this.tracks.length
11686
+ });
11687
+ const trackTitle = track.title || i18n.t("playlist.trackUntitled", { number: index + 1 });
11688
+ const trackArtist = track.artist ? i18n.t("playlist.by") + track.artist : "";
11530
11689
  const isActive = index === this.currentIndex;
11531
11690
  const statusText = isActive ? "Currently playing" : "Not playing";
11532
11691
  const actionText = isActive ? "Press Enter to restart" : "Press Enter to play";
@@ -11688,9 +11847,12 @@ var VidPly = (() => {
11688
11847
  const button = buttons[index];
11689
11848
  if (!button) return;
11690
11849
  const track = this.tracks[index];
11691
- const trackPosition = `Track ${index + 1} of ${this.tracks.length}`;
11692
- const trackTitle = track.title || `Track ${index + 1}`;
11693
- const trackArtist = track.artist ? ` by ${track.artist}` : "";
11850
+ const trackPosition = i18n.t("playlist.trackOf", {
11851
+ current: index + 1,
11852
+ total: this.tracks.length
11853
+ });
11854
+ const trackTitle = track.title || i18n.t("playlist.trackUntitled", { number: index + 1 });
11855
+ const trackArtist = track.artist ? i18n.t("playlist.by") + track.artist : "";
11694
11856
  if (index === this.currentIndex) {
11695
11857
  item.classList.add("vidply-playlist-item-active");
11696
11858
  button.setAttribute("aria-current", "true");
@@ -11784,6 +11946,10 @@ var VidPly = (() => {
11784
11946
  this.trackInfoElement.innerHTML = "";
11785
11947
  this.trackInfoElement.style.display = "none";
11786
11948
  }
11949
+ if (this.trackArtworkElement) {
11950
+ this.trackArtworkElement.style.backgroundImage = "";
11951
+ this.trackArtworkElement.style.display = "none";
11952
+ }
11787
11953
  }
11788
11954
  /**
11789
11955
  * Toggle playlist panel visibility
@@ -11837,6 +12003,9 @@ var VidPly = (() => {
11837
12003
  destroy() {
11838
12004
  this.player.off("ended", this.handleTrackEnd);
11839
12005
  this.player.off("error", this.handleTrackError);
12006
+ if (this.trackArtworkElement) {
12007
+ this.trackArtworkElement.remove();
12008
+ }
11840
12009
  if (this.trackInfoElement) {
11841
12010
  this.trackInfoElement.remove();
11842
12011
  }