@uimaxbai/am-lyrics 1.3.0 → 1.4.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/README.md +0 -5
- package/dist/src/AmLyrics.d.ts +5 -7
- package/dist/src/AmLyrics.d.ts.map +1 -1
- package/dist/src/am-lyrics.js +468 -348
- package/dist/src/am-lyrics.js.map +1 -1
- package/dist/src/react.js +468 -348
- package/dist/src/react.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/AmLyrics.ts +547 -399
- package/fix.cjs +0 -7
- package/patch.diff +0 -210
- package/patch2.diff +0 -26
package/dist/src/react.js
CHANGED
|
@@ -322,7 +322,7 @@ class GoogleService {
|
|
|
322
322
|
}
|
|
323
323
|
}
|
|
324
324
|
|
|
325
|
-
const VERSION = '1.
|
|
325
|
+
const VERSION = '1.4.0';
|
|
326
326
|
const INSTRUMENTAL_THRESHOLD_MS = 7000; // Show dots for gaps >= 7s
|
|
327
327
|
const FETCH_TIMEOUT_MS = 8000; // Timeout for all lyrics fetch requests
|
|
328
328
|
const SEEK_THRESHOLD_MS = 500;
|
|
@@ -345,32 +345,17 @@ function fetchWithTimeout(url, options = {}, timeoutMs = FETCH_TIMEOUT_MS) {
|
|
|
345
345
|
}
|
|
346
346
|
const KPOE_SERVERS = [
|
|
347
347
|
'https://lyricsplus.binimum.org',
|
|
348
|
-
'https://lyricsplus.atomix.one',
|
|
349
348
|
'https://lyricsplus-seven.vercel.app',
|
|
350
349
|
'https://lyricsplus.prjktla.workers.dev',
|
|
351
350
|
'https://lyrics-plus-backend.vercel.app',
|
|
352
351
|
];
|
|
353
352
|
const DEFAULT_KPOE_SOURCE_ORDER = 'apple,lyricsplus,musixmatch,spotify,qq,deezer,musixmatch-word';
|
|
354
|
-
const TIDAL_SERVERS = [
|
|
355
|
-
'https://arran.monochrome.tf',
|
|
356
|
-
'https://api.monochrome.tf/',
|
|
357
|
-
'https://triton.squid.wtf',
|
|
358
|
-
'https://wolf.qqdl.site',
|
|
359
|
-
'https://maus.qqdl.site',
|
|
360
|
-
'https://vogel.qqdl.site',
|
|
361
|
-
'https://katze.qqdl.site',
|
|
362
|
-
'https://hund.qqdl.site',
|
|
363
|
-
'https://tidal.kinoplus.online',
|
|
364
|
-
'https://hifi-one.spotisaver.net',
|
|
365
|
-
'https://hifi-two.spotisaver.net',
|
|
366
|
-
];
|
|
367
353
|
const GENIUS_WORKER_URL = 'https://fetch-genius.samidy.workers.dev/';
|
|
368
354
|
let AmLyrics$1 = class AmLyrics extends i {
|
|
369
355
|
constructor() {
|
|
370
356
|
super(...arguments);
|
|
371
357
|
this.downloadFormat = 'auto';
|
|
372
358
|
this.highlightColor = '#ffffff';
|
|
373
|
-
this.hoverBackgroundColor = 'rgba(255, 255, 255, 0.13)';
|
|
374
359
|
this.autoScroll = true;
|
|
375
360
|
this.interpolate = true;
|
|
376
361
|
this.showRomanization = false;
|
|
@@ -415,6 +400,10 @@ let AmLyrics$1 = class AmLyrics extends i {
|
|
|
415
400
|
// Syllable animation tracking
|
|
416
401
|
this.lastActiveIndex = 0;
|
|
417
402
|
this.visibleLineIds = new Set();
|
|
403
|
+
// Cached element tracking to avoid repeated querySelectorAll calls
|
|
404
|
+
this.preActiveLineElements = [];
|
|
405
|
+
this.positionedLineElements = [];
|
|
406
|
+
this.activeGapLineElements = [];
|
|
418
407
|
// Bound handler references for proper event listener removal
|
|
419
408
|
this._boundHandleUserScroll = this.handleUserScroll.bind(this);
|
|
420
409
|
this._boundAnimateProgress = this.animateProgress.bind(this);
|
|
@@ -487,6 +476,31 @@ let AmLyrics$1 = class AmLyrics extends i {
|
|
|
487
476
|
}
|
|
488
477
|
set currentTime(value) {
|
|
489
478
|
const oldValue = this._currentTime;
|
|
479
|
+
// If the new time is significantly smaller than the old time (e.g. song looped)
|
|
480
|
+
if (value < oldValue && oldValue - value > 1000 && this.lyrics) {
|
|
481
|
+
this.activeLineIndices = [];
|
|
482
|
+
this.activeMainWordIndices.clear();
|
|
483
|
+
this.activeBackgroundWordIndices.clear();
|
|
484
|
+
this.mainWordProgress.clear();
|
|
485
|
+
this.backgroundWordProgress.clear();
|
|
486
|
+
this.mainWordAnimations.clear();
|
|
487
|
+
this.backgroundWordAnimations.clear();
|
|
488
|
+
this.preActiveLineElements = [];
|
|
489
|
+
this.positionedLineElements = [];
|
|
490
|
+
this.activeGapLineElements = [];
|
|
491
|
+
// Stop all running animations and clear highlights immediately
|
|
492
|
+
if (this.lyricsContainer) {
|
|
493
|
+
const activeLines = this.lyricsContainer.querySelectorAll('.lyrics-line.active, .lyrics-line.pre-active');
|
|
494
|
+
activeLines.forEach(line => {
|
|
495
|
+
line.classList.remove('active', 'pre-active');
|
|
496
|
+
AmLyrics.resetSyllables(line);
|
|
497
|
+
});
|
|
498
|
+
const activeGaps = this.lyricsContainer.querySelectorAll('.lyrics-gap.active, .lyrics-gap.gap-exiting');
|
|
499
|
+
activeGaps.forEach(gap => gap.classList.remove('active', 'gap-exiting'));
|
|
500
|
+
// Reset gap cache since we manually messed with the elements
|
|
501
|
+
this.gapElementCache.clear();
|
|
502
|
+
}
|
|
503
|
+
}
|
|
490
504
|
this._currentTime = value;
|
|
491
505
|
if (oldValue !== value && this.lyrics) {
|
|
492
506
|
this._onTimeChanged(oldValue, value);
|
|
@@ -548,6 +562,9 @@ let AmLyrics$1 = class AmLyrics extends i {
|
|
|
548
562
|
this.lyricsContainer.removeEventListener('wheel', this._boundHandleUserScroll);
|
|
549
563
|
this.lyricsContainer.removeEventListener('touchmove', this._boundHandleUserScroll);
|
|
550
564
|
}
|
|
565
|
+
this.preActiveLineElements = [];
|
|
566
|
+
this.positionedLineElements = [];
|
|
567
|
+
this.activeGapLineElements = [];
|
|
551
568
|
}
|
|
552
569
|
async fetchLyrics() {
|
|
553
570
|
// Cancel any in-flight fetch to prevent stale results from racing
|
|
@@ -582,16 +599,7 @@ let AmLyrics$1 = class AmLyrics extends i {
|
|
|
582
599
|
}
|
|
583
600
|
}
|
|
584
601
|
if (collectedSources.length === 0 && resolvedMetadata?.metadata) {
|
|
585
|
-
|
|
586
|
-
if (tidalResult && tidalResult.lines.length > 0) {
|
|
587
|
-
collectedSources.push({
|
|
588
|
-
lines: tidalResult.lines,
|
|
589
|
-
source: 'Tidal',
|
|
590
|
-
});
|
|
591
|
-
}
|
|
592
|
-
}
|
|
593
|
-
// Fallback: LRCLIB
|
|
594
|
-
if (collectedSources.length === 0 && resolvedMetadata?.metadata) {
|
|
602
|
+
// Fallback: LRCLIB
|
|
595
603
|
const lrclibResult = await AmLyrics.fetchLyricsFromLrclib(resolvedMetadata.metadata);
|
|
596
604
|
if (lrclibResult && lrclibResult.lines.length > 0) {
|
|
597
605
|
collectedSources.push({
|
|
@@ -611,15 +619,17 @@ let AmLyrics$1 = class AmLyrics extends i {
|
|
|
611
619
|
}
|
|
612
620
|
this.hasFetchedAllProviders =
|
|
613
621
|
collectedSources.length === 0 ||
|
|
614
|
-
collectedSources.some(s => s.source === 'LRCLIB' ||
|
|
615
|
-
s.source === 'Tidal' ||
|
|
616
|
-
s.source === 'Genius');
|
|
622
|
+
collectedSources.some(s => s.source === 'LRCLIB' || s.source === 'Genius');
|
|
617
623
|
this._updateFooter();
|
|
618
624
|
if (collectedSources.length > 0) {
|
|
619
625
|
this.availableSources = AmLyrics.mergeAndSortSources(collectedSources);
|
|
620
626
|
this.currentSourceIndex = 0;
|
|
621
|
-
|
|
622
|
-
this.
|
|
627
|
+
const sourceResult = this.availableSources[0];
|
|
628
|
+
this.lyrics = sourceResult.lines;
|
|
629
|
+
this.lyricsSource = sourceResult.source;
|
|
630
|
+
if (sourceResult.songwriters) {
|
|
631
|
+
this.songwriters = sourceResult.songwriters;
|
|
632
|
+
}
|
|
623
633
|
await this.onLyricsLoaded();
|
|
624
634
|
return;
|
|
625
635
|
}
|
|
@@ -641,6 +651,9 @@ let AmLyrics$1 = class AmLyrics extends i {
|
|
|
641
651
|
this.backgroundWordProgress.clear();
|
|
642
652
|
this.mainWordAnimations.clear();
|
|
643
653
|
this.backgroundWordAnimations.clear();
|
|
654
|
+
this.preActiveLineElements = [];
|
|
655
|
+
this.positionedLineElements = [];
|
|
656
|
+
this.activeGapLineElements = [];
|
|
644
657
|
if (this.lyricsContainer) {
|
|
645
658
|
this.isProgrammaticScroll = true;
|
|
646
659
|
this.lyricsContainer.scrollTop = 0;
|
|
@@ -670,36 +683,30 @@ let AmLyrics$1 = class AmLyrics extends i {
|
|
|
670
683
|
return 2;
|
|
671
684
|
if (lower.includes('musixmatch') && hasWordSync)
|
|
672
685
|
return 3;
|
|
673
|
-
if (lower.includes('tidal') && hasWordSync)
|
|
674
|
-
return 4;
|
|
675
686
|
if (lower.includes('lrclib') && hasWordSync)
|
|
676
|
-
return
|
|
687
|
+
return 4;
|
|
677
688
|
if (hasWordSync)
|
|
678
|
-
return
|
|
689
|
+
return 5;
|
|
679
690
|
if (lower.includes('apple') && !hasWordSync && !isUnsynced)
|
|
680
|
-
return
|
|
691
|
+
return 6;
|
|
681
692
|
if (isQQ && !hasWordSync && !isUnsynced)
|
|
682
|
-
return
|
|
693
|
+
return 7;
|
|
683
694
|
if (lower.includes('musixmatch') && !hasWordSync && !isUnsynced)
|
|
684
|
-
return
|
|
685
|
-
if (lower.includes('tidal') && !hasWordSync && !isUnsynced)
|
|
686
|
-
return 10;
|
|
695
|
+
return 8;
|
|
687
696
|
if (lower.includes('lrclib') && !hasWordSync && !isUnsynced)
|
|
688
|
-
return
|
|
697
|
+
return 9;
|
|
689
698
|
if (!hasWordSync && !isUnsynced)
|
|
690
|
-
return
|
|
699
|
+
return 10;
|
|
691
700
|
if (lower.includes('apple') && isUnsynced)
|
|
692
|
-
return
|
|
701
|
+
return 11;
|
|
693
702
|
if (isQQ && isUnsynced)
|
|
694
|
-
return
|
|
703
|
+
return 12;
|
|
695
704
|
if (lower.includes('musixmatch') && isUnsynced)
|
|
696
|
-
return
|
|
697
|
-
if (lower.includes('tidal') && isUnsynced)
|
|
698
|
-
return 16;
|
|
705
|
+
return 13;
|
|
699
706
|
if (lower.includes('lrclib') && isUnsynced)
|
|
700
|
-
return
|
|
707
|
+
return 14;
|
|
701
708
|
if (lower.includes('genius'))
|
|
702
|
-
return
|
|
709
|
+
return 15;
|
|
703
710
|
return 20;
|
|
704
711
|
}
|
|
705
712
|
static mergeAndSortSources(collectedSources) {
|
|
@@ -730,13 +737,6 @@ let AmLyrics$1 = class AmLyrics extends i {
|
|
|
730
737
|
const resolvedMetadata = await this.resolveSongMetadata();
|
|
731
738
|
if (resolvedMetadata?.metadata) {
|
|
732
739
|
const newSources = [];
|
|
733
|
-
// Try Tidal if not fetched
|
|
734
|
-
if (!this.availableSources.some(s => s.source.toLowerCase().includes('tidal'))) {
|
|
735
|
-
const tidalResult = await AmLyrics.fetchLyricsFromTidal(resolvedMetadata.metadata, resolvedMetadata.catalogIsrc);
|
|
736
|
-
if (tidalResult && tidalResult.lines.length > 0) {
|
|
737
|
-
newSources.push({ lines: tidalResult.lines, source: 'Tidal' });
|
|
738
|
-
}
|
|
739
|
-
}
|
|
740
740
|
// Try LRCLIB if not fetched
|
|
741
741
|
if (!this.availableSources.some(s => s.source.toLowerCase().includes('lrclib'))) {
|
|
742
742
|
const lrclibResult = await AmLyrics.fetchLyricsFromLrclib(resolvedMetadata.metadata);
|
|
@@ -771,8 +771,12 @@ let AmLyrics$1 = class AmLyrics extends i {
|
|
|
771
771
|
if (this.availableSources.length > 1) {
|
|
772
772
|
this.currentSourceIndex =
|
|
773
773
|
(this.currentSourceIndex + 1) % this.availableSources.length;
|
|
774
|
-
|
|
775
|
-
this.
|
|
774
|
+
const sourceResult = this.availableSources[this.currentSourceIndex];
|
|
775
|
+
this.lyrics = sourceResult.lines;
|
|
776
|
+
this.lyricsSource = sourceResult.source;
|
|
777
|
+
if (sourceResult.songwriters) {
|
|
778
|
+
this.songwriters = sourceResult.songwriters;
|
|
779
|
+
}
|
|
776
780
|
await this.onLyricsLoaded();
|
|
777
781
|
}
|
|
778
782
|
}
|
|
@@ -781,6 +785,7 @@ let AmLyrics$1 = class AmLyrics extends i {
|
|
|
781
785
|
title: this.songTitle?.trim() ?? '',
|
|
782
786
|
artist: this.songArtist?.trim() ?? '',
|
|
783
787
|
album: this.songAlbum?.trim() || undefined,
|
|
788
|
+
songwriters: this.songwriters?.trim() || undefined,
|
|
784
789
|
durationMs: undefined,
|
|
785
790
|
};
|
|
786
791
|
if (typeof this.songDurationMs === 'number' && this.songDurationMs > 0) {
|
|
@@ -820,6 +825,9 @@ let AmLyrics$1 = class AmLyrics extends i {
|
|
|
820
825
|
if (!metadata.album && catalogResult.album) {
|
|
821
826
|
metadata.album = catalogResult.album;
|
|
822
827
|
}
|
|
828
|
+
if (!metadata.songwriters && catalogResult.songwriters) {
|
|
829
|
+
metadata.songwriters = catalogResult.songwriters;
|
|
830
|
+
}
|
|
823
831
|
if (metadata.durationMs == null &&
|
|
824
832
|
typeof catalogResult.durationMs === 'number' &&
|
|
825
833
|
catalogResult.durationMs > 0) {
|
|
@@ -1010,9 +1018,13 @@ let AmLyrics$1 = class AmLyrics extends i {
|
|
|
1010
1018
|
const ttmlRes = await fetchWithTimeout(result.lyricsUrl);
|
|
1011
1019
|
if (ttmlRes.ok) {
|
|
1012
1020
|
const ttmlText = await ttmlRes.text();
|
|
1013
|
-
const
|
|
1014
|
-
if (
|
|
1015
|
-
allResults.push({
|
|
1021
|
+
const parseResult = AmLyrics.parseTTML(ttmlText);
|
|
1022
|
+
if (parseResult && parseResult.lines.length > 0) {
|
|
1023
|
+
allResults.push({
|
|
1024
|
+
lines: parseResult.lines,
|
|
1025
|
+
source: 'BiniLyrics',
|
|
1026
|
+
songwriters: parseResult.songwriters,
|
|
1027
|
+
});
|
|
1016
1028
|
return allResults;
|
|
1017
1029
|
}
|
|
1018
1030
|
}
|
|
@@ -1044,11 +1056,12 @@ let AmLyrics$1 = class AmLyrics extends i {
|
|
|
1044
1056
|
const ttmlRes = await fetchWithTimeout(result.lyricsUrl);
|
|
1045
1057
|
if (ttmlRes.ok) {
|
|
1046
1058
|
const ttmlText = await ttmlRes.text();
|
|
1047
|
-
const
|
|
1048
|
-
if (
|
|
1059
|
+
const parseResult = AmLyrics.parseTTML(ttmlText);
|
|
1060
|
+
if (parseResult && parseResult.lines.length > 0) {
|
|
1049
1061
|
allResults.push({
|
|
1050
|
-
lines,
|
|
1062
|
+
lines: parseResult.lines,
|
|
1051
1063
|
source: 'BiniLyrics',
|
|
1064
|
+
songwriters: parseResult.songwriters,
|
|
1052
1065
|
});
|
|
1053
1066
|
return allResults;
|
|
1054
1067
|
}
|
|
@@ -1181,77 +1194,6 @@ let AmLyrics$1 = class AmLyrics extends i {
|
|
|
1181
1194
|
}
|
|
1182
1195
|
return lines;
|
|
1183
1196
|
}
|
|
1184
|
-
/**
|
|
1185
|
-
* Fetch lyrics from Tidal API.
|
|
1186
|
-
* Picks 2 random servers, tries search + lyrics on each.
|
|
1187
|
-
*/
|
|
1188
|
-
static async fetchLyricsFromTidal(metadata, isrc) {
|
|
1189
|
-
const title = metadata.title?.trim();
|
|
1190
|
-
const artist = metadata.artist?.trim();
|
|
1191
|
-
if (!title || !artist)
|
|
1192
|
-
return null;
|
|
1193
|
-
// Pick 3 random unique servers for better reliability
|
|
1194
|
-
const shuffled = [...TIDAL_SERVERS].sort(() => Math.random() - 0.5);
|
|
1195
|
-
const serversToTry = shuffled.slice(0, 3);
|
|
1196
|
-
for (const base of serversToTry) {
|
|
1197
|
-
try {
|
|
1198
|
-
const normalizedBase = base.endsWith('/') ? base.slice(0, -1) : base;
|
|
1199
|
-
// Step 1: Search for the track
|
|
1200
|
-
const searchQuery = `${title} ${artist}`;
|
|
1201
|
-
const searchParams = new URLSearchParams({ s: searchQuery });
|
|
1202
|
-
// eslint-disable-next-line no-await-in-loop
|
|
1203
|
-
const searchResponse = await fetchWithTimeout(`${normalizedBase}/search/?${searchParams.toString()}`);
|
|
1204
|
-
if (!searchResponse.ok) {
|
|
1205
|
-
// eslint-disable-next-line no-continue
|
|
1206
|
-
continue;
|
|
1207
|
-
}
|
|
1208
|
-
// eslint-disable-next-line no-await-in-loop
|
|
1209
|
-
const searchData = await searchResponse.json();
|
|
1210
|
-
const items = searchData?.data?.items;
|
|
1211
|
-
if (!Array.isArray(items) || items.length === 0) {
|
|
1212
|
-
// eslint-disable-next-line no-continue
|
|
1213
|
-
continue;
|
|
1214
|
-
}
|
|
1215
|
-
// Find best match: prefer ISRC match, then first result
|
|
1216
|
-
let bestTrack = items[0];
|
|
1217
|
-
if (isrc) {
|
|
1218
|
-
const isrcMatch = items.find((item) => item.isrc && item.isrc.toLowerCase() === isrc.toLowerCase());
|
|
1219
|
-
if (isrcMatch) {
|
|
1220
|
-
bestTrack = isrcMatch;
|
|
1221
|
-
}
|
|
1222
|
-
}
|
|
1223
|
-
const trackId = bestTrack?.id;
|
|
1224
|
-
if (!trackId) {
|
|
1225
|
-
// eslint-disable-next-line no-continue
|
|
1226
|
-
continue;
|
|
1227
|
-
}
|
|
1228
|
-
// Step 2: Fetch lyrics
|
|
1229
|
-
// eslint-disable-next-line no-await-in-loop
|
|
1230
|
-
const lyricsResponse = await fetchWithTimeout(`${normalizedBase}/lyrics/?id=${trackId}`);
|
|
1231
|
-
if (!lyricsResponse.ok) {
|
|
1232
|
-
// eslint-disable-next-line no-continue
|
|
1233
|
-
continue;
|
|
1234
|
-
}
|
|
1235
|
-
// eslint-disable-next-line no-await-in-loop
|
|
1236
|
-
const lyricsData = await lyricsResponse.json();
|
|
1237
|
-
const subtitles = lyricsData?.lyrics?.subtitles;
|
|
1238
|
-
if (subtitles && typeof subtitles === 'string') {
|
|
1239
|
-
const lines = AmLyrics.parseLrcSubtitles(subtitles);
|
|
1240
|
-
if (lines.length > 0) {
|
|
1241
|
-
const provider = lyricsData?.lyrics?.lyricsProvider || 'Tidal';
|
|
1242
|
-
return {
|
|
1243
|
-
lines,
|
|
1244
|
-
source: `Tidal (${provider})`,
|
|
1245
|
-
};
|
|
1246
|
-
}
|
|
1247
|
-
}
|
|
1248
|
-
}
|
|
1249
|
-
catch {
|
|
1250
|
-
// Try next server
|
|
1251
|
-
}
|
|
1252
|
-
}
|
|
1253
|
-
return null;
|
|
1254
|
-
}
|
|
1255
1197
|
/**
|
|
1256
1198
|
* Fetch lyrics from LRCLIB.
|
|
1257
1199
|
* Uses search endpoint, prefers synced lyrics.
|
|
@@ -1434,6 +1376,19 @@ let AmLyrics$1 = class AmLyrics extends i {
|
|
|
1434
1376
|
agentMap[id] = type;
|
|
1435
1377
|
}
|
|
1436
1378
|
}
|
|
1379
|
+
let songwriters;
|
|
1380
|
+
const songwritersNodes = doc.getElementsByTagName('songwriter');
|
|
1381
|
+
if (songwritersNodes.length > 0) {
|
|
1382
|
+
const names = [];
|
|
1383
|
+
for (let i = 0; i < songwritersNodes.length; i += 1) {
|
|
1384
|
+
if (songwritersNodes[i].textContent) {
|
|
1385
|
+
names.push(songwritersNodes[i].textContent);
|
|
1386
|
+
}
|
|
1387
|
+
}
|
|
1388
|
+
if (names.length > 0) {
|
|
1389
|
+
songwriters = names.join(', ');
|
|
1390
|
+
}
|
|
1391
|
+
}
|
|
1437
1392
|
const translationNodes = doc.getElementsByTagName('translation');
|
|
1438
1393
|
for (let i = 0; i < translationNodes.length; i += 1) {
|
|
1439
1394
|
const texts = translationNodes[i].getElementsByTagName('text');
|
|
@@ -1550,7 +1505,7 @@ let AmLyrics$1 = class AmLyrics extends i {
|
|
|
1550
1505
|
text: bgText,
|
|
1551
1506
|
timestamp: timeToMs(bgSpan.getAttribute('begin')),
|
|
1552
1507
|
endtime: timeToMs(bgSpan.getAttribute('end')),
|
|
1553
|
-
part:
|
|
1508
|
+
part: !/\s$/.test(bgText),
|
|
1554
1509
|
});
|
|
1555
1510
|
}
|
|
1556
1511
|
// eslint-disable-next-line no-continue
|
|
@@ -1573,7 +1528,7 @@ let AmLyrics$1 = class AmLyrics extends i {
|
|
|
1573
1528
|
text,
|
|
1574
1529
|
timestamp: timeToMs(span.getAttribute('begin')),
|
|
1575
1530
|
endtime: timeToMs(span.getAttribute('end')),
|
|
1576
|
-
part:
|
|
1531
|
+
part: !/\s$/.test(text),
|
|
1577
1532
|
});
|
|
1578
1533
|
}
|
|
1579
1534
|
}
|
|
@@ -1659,7 +1614,7 @@ let AmLyrics$1 = class AmLyrics extends i {
|
|
|
1659
1614
|
oppositeTurn: alignment === 'end',
|
|
1660
1615
|
});
|
|
1661
1616
|
}
|
|
1662
|
-
return lines;
|
|
1617
|
+
return { lines, songwriters };
|
|
1663
1618
|
}
|
|
1664
1619
|
catch (e) {
|
|
1665
1620
|
// eslint-disable-next-line no-console
|
|
@@ -1824,7 +1779,10 @@ let AmLyrics$1 = class AmLyrics extends i {
|
|
|
1824
1779
|
if (!newActiveLines.includes(lineIndex)) {
|
|
1825
1780
|
const lineElement = this._getLineElement(lineIndex);
|
|
1826
1781
|
if (lineElement) {
|
|
1827
|
-
lineElement.classList.remove('active');
|
|
1782
|
+
lineElement.classList.remove('active', 'pre-active');
|
|
1783
|
+
const preIdx = this.preActiveLineElements.indexOf(lineElement);
|
|
1784
|
+
if (preIdx !== -1)
|
|
1785
|
+
this.preActiveLineElements.splice(preIdx, 1);
|
|
1828
1786
|
AmLyrics.resetSyllables(lineElement);
|
|
1829
1787
|
}
|
|
1830
1788
|
}
|
|
@@ -1836,6 +1794,9 @@ let AmLyrics$1 = class AmLyrics extends i {
|
|
|
1836
1794
|
if (lineElement) {
|
|
1837
1795
|
lineElement.classList.add('active');
|
|
1838
1796
|
lineElement.classList.remove('pre-active');
|
|
1797
|
+
const preIdx = this.preActiveLineElements.indexOf(lineElement);
|
|
1798
|
+
if (preIdx !== -1)
|
|
1799
|
+
this.preActiveLineElements.splice(preIdx, 1);
|
|
1839
1800
|
}
|
|
1840
1801
|
}
|
|
1841
1802
|
}
|
|
@@ -1855,10 +1816,9 @@ let AmLyrics$1 = class AmLyrics extends i {
|
|
|
1855
1816
|
}
|
|
1856
1817
|
}
|
|
1857
1818
|
// Also update syllables in active gap lines (breathing dots)
|
|
1858
|
-
const
|
|
1859
|
-
activeGaps.forEach(gapLine => {
|
|
1819
|
+
for (const gapLine of this.activeGapLineElements) {
|
|
1860
1820
|
AmLyrics.updateSyllablesForLine(gapLine, newTime);
|
|
1861
|
-
}
|
|
1821
|
+
}
|
|
1862
1822
|
// Imperatively manage gap active state
|
|
1863
1823
|
if (this.gapElementCache.size > 0) {
|
|
1864
1824
|
for (const [, gap] of this.gapElementCache) {
|
|
@@ -1869,9 +1829,21 @@ let AmLyrics$1 = class AmLyrics extends i {
|
|
|
1869
1829
|
const isExiting = gap.classList.contains('gap-exiting');
|
|
1870
1830
|
const exitLeadMs = GAP_EXIT_LEAD_MS;
|
|
1871
1831
|
const shouldStartExiting = isActive && !isExiting && newTime >= gapEndTime - exitLeadMs;
|
|
1872
|
-
if (shouldBeActive && !isActive && !isExiting) {
|
|
1832
|
+
if (shouldBeActive && (!isActive || isSeek) && !isExiting) {
|
|
1873
1833
|
gap.classList.remove('gap-exiting');
|
|
1834
|
+
if (isSeek && isActive) {
|
|
1835
|
+
gap.classList.remove('active');
|
|
1836
|
+
// eslint-disable-next-line no-void
|
|
1837
|
+
void gap.offsetWidth; // Force reflow
|
|
1838
|
+
}
|
|
1839
|
+
const gapDuration = gapEndTime - gapStartTime;
|
|
1840
|
+
const baseLoopDelay = AmLyrics.getGapLoopDelay(gapDuration);
|
|
1841
|
+
const totalDelay = baseLoopDelay + (newTime - gapStartTime);
|
|
1842
|
+
gap.style.setProperty('--gap-loop-delay', `-${totalDelay}ms`);
|
|
1874
1843
|
gap.classList.add('active');
|
|
1844
|
+
if (!this.activeGapLineElements.includes(gap)) {
|
|
1845
|
+
this.activeGapLineElements.push(gap);
|
|
1846
|
+
}
|
|
1875
1847
|
const dotSyllables = gap.querySelectorAll('.lyrics-syllable');
|
|
1876
1848
|
dotSyllables.forEach(dot => {
|
|
1877
1849
|
const dotStart = parseFloat(dot.getAttribute('data-start-time') || '0');
|
|
@@ -1879,24 +1851,34 @@ let AmLyrics$1 = class AmLyrics extends i {
|
|
|
1879
1851
|
if (newTime > dotEnd) {
|
|
1880
1852
|
dot.classList.add('finished');
|
|
1881
1853
|
if (!dot.classList.contains('highlight')) {
|
|
1882
|
-
AmLyrics.updateSyllableAnimation(dot);
|
|
1854
|
+
AmLyrics.updateSyllableAnimation(dot, newTime - dotStart);
|
|
1883
1855
|
}
|
|
1884
1856
|
}
|
|
1885
1857
|
else if (newTime >= dotStart && newTime <= dotEnd) {
|
|
1886
|
-
AmLyrics.updateSyllableAnimation(dot);
|
|
1858
|
+
AmLyrics.updateSyllableAnimation(dot, newTime - dotStart);
|
|
1887
1859
|
}
|
|
1888
1860
|
});
|
|
1889
1861
|
}
|
|
1890
1862
|
else if (shouldStartExiting) {
|
|
1891
|
-
gap
|
|
1863
|
+
// Cancel gap-loop first, force reflow, then start gap-ended
|
|
1864
|
+
// so the browser sees a clean animation swap
|
|
1892
1865
|
gap.classList.remove('active');
|
|
1866
|
+
// eslint-disable-next-line no-void
|
|
1867
|
+
void gap.offsetWidth;
|
|
1868
|
+
gap.classList.add('gap-exiting');
|
|
1869
|
+
const gapIdx = this.activeGapLineElements.indexOf(gap);
|
|
1870
|
+
if (gapIdx !== -1)
|
|
1871
|
+
this.activeGapLineElements.splice(gapIdx, 1);
|
|
1893
1872
|
setTimeout(() => {
|
|
1894
1873
|
gap.classList.remove('gap-exiting');
|
|
1895
1874
|
}, GAP_EXIT_LEAD_MS);
|
|
1896
1875
|
}
|
|
1897
|
-
else if (
|
|
1876
|
+
else if (!shouldBeActive && (isActive || isExiting)) {
|
|
1898
1877
|
gap.classList.remove('active');
|
|
1899
1878
|
gap.classList.remove('gap-exiting');
|
|
1879
|
+
const gapIdx = this.activeGapLineElements.indexOf(gap);
|
|
1880
|
+
if (gapIdx !== -1)
|
|
1881
|
+
this.activeGapLineElements.splice(gapIdx, 1);
|
|
1900
1882
|
}
|
|
1901
1883
|
else if (isExiting && newTime < gapEndTime - exitLeadMs) {
|
|
1902
1884
|
gap.classList.remove('gap-exiting');
|
|
@@ -1914,20 +1896,41 @@ let AmLyrics$1 = class AmLyrics extends i {
|
|
|
1914
1896
|
const isExiting = gap.classList.contains('gap-exiting');
|
|
1915
1897
|
const exitLeadMs = GAP_EXIT_LEAD_MS;
|
|
1916
1898
|
const shouldStartExiting = isActive && !isExiting && newTime >= gapEndTime - exitLeadMs;
|
|
1917
|
-
if (shouldBeActive && !isActive && !isExiting) {
|
|
1899
|
+
if (shouldBeActive && (!isActive || isSeek) && !isExiting) {
|
|
1918
1900
|
gap.classList.remove('gap-exiting');
|
|
1901
|
+
if (isSeek && isActive) {
|
|
1902
|
+
gap.classList.remove('active');
|
|
1903
|
+
// eslint-disable-next-line no-void
|
|
1904
|
+
void gap.offsetWidth; // Force reflow
|
|
1905
|
+
}
|
|
1906
|
+
const gapDuration = gapEndTime - gapStartTime;
|
|
1907
|
+
const baseLoopDelay = AmLyrics.getGapLoopDelay(gapDuration);
|
|
1908
|
+
const totalDelay = baseLoopDelay + (newTime - gapStartTime);
|
|
1909
|
+
gap.style.setProperty('--gap-loop-delay', `-${totalDelay}ms`);
|
|
1919
1910
|
gap.classList.add('active');
|
|
1911
|
+
if (!this.activeGapLineElements.includes(gap)) {
|
|
1912
|
+
this.activeGapLineElements.push(gap);
|
|
1913
|
+
}
|
|
1920
1914
|
}
|
|
1921
1915
|
else if (shouldStartExiting) {
|
|
1922
|
-
gap
|
|
1916
|
+
// Cancel gap-loop first, force reflow, then start gap-ended
|
|
1923
1917
|
gap.classList.remove('active');
|
|
1918
|
+
// eslint-disable-next-line no-void
|
|
1919
|
+
void gap.offsetWidth;
|
|
1920
|
+
gap.classList.add('gap-exiting');
|
|
1921
|
+
const gapIdx = this.activeGapLineElements.indexOf(gap);
|
|
1922
|
+
if (gapIdx !== -1)
|
|
1923
|
+
this.activeGapLineElements.splice(gapIdx, 1);
|
|
1924
1924
|
setTimeout(() => {
|
|
1925
1925
|
gap.classList.remove('gap-exiting');
|
|
1926
1926
|
}, GAP_EXIT_LEAD_MS);
|
|
1927
1927
|
}
|
|
1928
|
-
else if (
|
|
1928
|
+
else if (!shouldBeActive && (isActive || isExiting)) {
|
|
1929
1929
|
gap.classList.remove('active');
|
|
1930
1930
|
gap.classList.remove('gap-exiting');
|
|
1931
|
+
const gapIdx = this.activeGapLineElements.indexOf(gap);
|
|
1932
|
+
if (gapIdx !== -1)
|
|
1933
|
+
this.activeGapLineElements.splice(gapIdx, 1);
|
|
1931
1934
|
}
|
|
1932
1935
|
else if (isExiting && newTime < gapEndTime - exitLeadMs) {
|
|
1933
1936
|
gap.classList.remove('gap-exiting');
|
|
@@ -1942,6 +1945,25 @@ let AmLyrics$1 = class AmLyrics extends i {
|
|
|
1942
1945
|
else if (this.lastInstrumentalIndex !== null) {
|
|
1943
1946
|
this.lastInstrumentalIndex = null;
|
|
1944
1947
|
}
|
|
1948
|
+
// Check footer active state
|
|
1949
|
+
const lastLyric = this.lyrics && this.lyrics.length > 0
|
|
1950
|
+
? this.lyrics[this.lyrics.length - 1]
|
|
1951
|
+
: null;
|
|
1952
|
+
const footer = this.lyricsContainer.querySelector('.lyrics-footer');
|
|
1953
|
+
if (footer && lastLyric && lastLyric.endtime > 0) {
|
|
1954
|
+
const isFooterActive = newTime > lastLyric.endtime + 200; // Snappier 200ms buffer
|
|
1955
|
+
if (isFooterActive && !footer.classList.contains('active')) {
|
|
1956
|
+
footer.classList.add('active');
|
|
1957
|
+
if (this.autoScroll &&
|
|
1958
|
+
!this.isUserScrolling &&
|
|
1959
|
+
!this.isClickSeeking) {
|
|
1960
|
+
this.focusLine(footer);
|
|
1961
|
+
}
|
|
1962
|
+
}
|
|
1963
|
+
else if (!isFooterActive && footer.classList.contains('active')) {
|
|
1964
|
+
footer.classList.remove('active');
|
|
1965
|
+
}
|
|
1966
|
+
}
|
|
1945
1967
|
// Pre-scroll: scroll to upcoming line ~0.5s before it starts
|
|
1946
1968
|
if (this.autoScroll &&
|
|
1947
1969
|
!this.isUserScrolling &&
|
|
@@ -1964,6 +1986,9 @@ let AmLyrics$1 = class AmLyrics extends i {
|
|
|
1964
1986
|
preActiveLineIndex = i;
|
|
1965
1987
|
if (!isBackToBack) {
|
|
1966
1988
|
nextLineEl.classList.add('pre-active');
|
|
1989
|
+
if (!this.preActiveLineElements.includes(nextLineEl)) {
|
|
1990
|
+
this.preActiveLineElements.push(nextLineEl);
|
|
1991
|
+
}
|
|
1967
1992
|
}
|
|
1968
1993
|
this.clearPreActiveClasses(i);
|
|
1969
1994
|
const slowScrollDuration = Math.max(SCROLL_ANIMATION_DURATION_MS, timeUntilStart);
|
|
@@ -1993,6 +2018,9 @@ let AmLyrics$1 = class AmLyrics extends i {
|
|
|
1993
2018
|
if (lineEl)
|
|
1994
2019
|
lineEl.classList.add('active');
|
|
1995
2020
|
}
|
|
2021
|
+
// Trigger a faux time-change so that updateSyllablesForLine fires
|
|
2022
|
+
// to setup inline syllable CSS wipe animations for whatever the current time is
|
|
2023
|
+
this._onTimeChanged(0, this.currentTime);
|
|
1996
2024
|
}
|
|
1997
2025
|
}
|
|
1998
2026
|
// Handle duration reset (-1 stops playback and resets currentTime to 0)
|
|
@@ -2005,6 +2033,9 @@ let AmLyrics$1 = class AmLyrics extends i {
|
|
|
2005
2033
|
this.backgroundWordProgress.clear();
|
|
2006
2034
|
this.mainWordAnimations.clear();
|
|
2007
2035
|
this.backgroundWordAnimations.clear();
|
|
2036
|
+
this.preActiveLineElements = [];
|
|
2037
|
+
this.positionedLineElements = [];
|
|
2038
|
+
this.activeGapLineElements = [];
|
|
2008
2039
|
this.setUserScrolling(false);
|
|
2009
2040
|
// Cancel any running animations
|
|
2010
2041
|
if (this.animationFrameId) {
|
|
@@ -2058,7 +2089,7 @@ let AmLyrics$1 = class AmLyrics extends i {
|
|
|
2058
2089
|
const gap = this.lyrics[targetLineIndex].timestamp -
|
|
2059
2090
|
this.lyrics[prevPrimaryIndex].endtime;
|
|
2060
2091
|
if (gap > 200) {
|
|
2061
|
-
scrollDuration = Math.min(Math.max(gap * 0.
|
|
2092
|
+
scrollDuration = Math.min(Math.max(gap * 0.85, SCROLL_ANIMATION_DURATION_MS), 4000);
|
|
2062
2093
|
}
|
|
2063
2094
|
}
|
|
2064
2095
|
this.focusLine(targetLine, forceScroll, scrollDuration);
|
|
@@ -2120,6 +2151,9 @@ let AmLyrics$1 = class AmLyrics extends i {
|
|
|
2120
2151
|
this.cachedLineData = null;
|
|
2121
2152
|
this.lineElementCache.clear();
|
|
2122
2153
|
this.gapElementCache.clear();
|
|
2154
|
+
this.preActiveLineElements = [];
|
|
2155
|
+
this.positionedLineElements = [];
|
|
2156
|
+
this.activeGapLineElements = [];
|
|
2123
2157
|
}
|
|
2124
2158
|
_updateCachedIsUnsynced() {
|
|
2125
2159
|
this.cachedIsUnsynced =
|
|
@@ -2132,13 +2166,23 @@ let AmLyrics$1 = class AmLyrics extends i {
|
|
|
2132
2166
|
return;
|
|
2133
2167
|
this.cachedLineData = this.lyrics.map(line => {
|
|
2134
2168
|
const wordGroups = [];
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2169
|
+
let currentGroupBuffer = [];
|
|
2170
|
+
line.text.forEach((syllable, idx) => {
|
|
2171
|
+
currentGroupBuffer.push(syllable);
|
|
2172
|
+
const nextSyllable = line.text[idx + 1];
|
|
2173
|
+
const endsWithDelimiter = !nextSyllable ||
|
|
2174
|
+
syllable.part === false ||
|
|
2175
|
+
/\s$/.test(syllable.text) ||
|
|
2176
|
+
(nextSyllable &&
|
|
2177
|
+
syllable.isBackground !==
|
|
2178
|
+
nextSyllable.isBackground);
|
|
2179
|
+
if (endsWithDelimiter) {
|
|
2180
|
+
wordGroups.push(currentGroupBuffer);
|
|
2181
|
+
currentGroupBuffer = [];
|
|
2141
2182
|
}
|
|
2183
|
+
});
|
|
2184
|
+
if (currentGroupBuffer.length > 0) {
|
|
2185
|
+
wordGroups.push(currentGroupBuffer);
|
|
2142
2186
|
}
|
|
2143
2187
|
const groupGrowable = new Array(wordGroups.length).fill(false);
|
|
2144
2188
|
const groupGlowing = new Array(wordGroups.length).fill(false);
|
|
@@ -2147,6 +2191,7 @@ let AmLyrics$1 = class AmLyrics extends i {
|
|
|
2147
2191
|
const vwCharOffset = new Array(wordGroups.length).fill(0);
|
|
2148
2192
|
const vwStartMs = new Array(wordGroups.length).fill(0);
|
|
2149
2193
|
const vwEndMs = new Array(wordGroups.length).fill(0);
|
|
2194
|
+
let lineIsRTL = false;
|
|
2150
2195
|
let vwStart = 0;
|
|
2151
2196
|
while (vwStart < wordGroups.length) {
|
|
2152
2197
|
let vwEnd = vwStart;
|
|
@@ -2168,9 +2213,11 @@ let AmLyrics$1 = class AmLyrics extends i {
|
|
|
2168
2213
|
const combinedDuration = combinedEnd - combinedStart;
|
|
2169
2214
|
const isCJK = /[\u4e00-\u9fff\u3040-\u309f\u30a0-\u30ff\uac00-\ud7af]/.test(combinedText);
|
|
2170
2215
|
const isRTL = /[\u0600-\u06FF\u0750-\u077F\u08A0-\u08FF\u0590-\u05FF]/.test(combinedText);
|
|
2216
|
+
if (isRTL)
|
|
2217
|
+
lineIsRTL = true;
|
|
2171
2218
|
const hasHyphen = combinedText.includes('-');
|
|
2172
2219
|
const wordLen = combinedText.length;
|
|
2173
|
-
let isGrowableVW = !isCJK && !isRTL && !hasHyphen && wordLen > 0 && wordLen <=
|
|
2220
|
+
let isGrowableVW = !isCJK && !isRTL && !hasHyphen && wordLen > 0 && wordLen <= 7;
|
|
2174
2221
|
if (isGrowableVW) {
|
|
2175
2222
|
if (wordLen < 3) {
|
|
2176
2223
|
isGrowableVW =
|
|
@@ -2181,7 +2228,8 @@ let AmLyrics$1 = class AmLyrics extends i {
|
|
|
2181
2228
|
combinedDuration >= 850 && combinedDuration >= wordLen * 190;
|
|
2182
2229
|
}
|
|
2183
2230
|
}
|
|
2184
|
-
const
|
|
2231
|
+
const isLineSynced = line.isWordSynced === false || line.text.some(s => s.lineSynced);
|
|
2232
|
+
const isGlowingVW = isGrowableVW && !isLineSynced;
|
|
2185
2233
|
let charOff = 0;
|
|
2186
2234
|
for (let gi = vwStart; gi <= vwEnd; gi += 1) {
|
|
2187
2235
|
groupGrowable[gi] = isGrowableVW;
|
|
@@ -2205,6 +2253,7 @@ let AmLyrics$1 = class AmLyrics extends i {
|
|
|
2205
2253
|
vwCharOffset,
|
|
2206
2254
|
vwStartMs,
|
|
2207
2255
|
vwEndMs,
|
|
2256
|
+
lineIsRTL,
|
|
2208
2257
|
};
|
|
2209
2258
|
});
|
|
2210
2259
|
}
|
|
@@ -2285,15 +2334,17 @@ let AmLyrics$1 = class AmLyrics extends i {
|
|
|
2285
2334
|
clearPreActiveClasses(exceptLineIndex = null) {
|
|
2286
2335
|
if (!this.lyricsContainer)
|
|
2287
2336
|
return;
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
.forEach(element => {
|
|
2291
|
-
const lineElement = element;
|
|
2337
|
+
const keptLines = [];
|
|
2338
|
+
for (const lineElement of this.preActiveLineElements) {
|
|
2292
2339
|
const lineIndex = AmLyrics.getLineIndexFromElement(lineElement);
|
|
2293
|
-
if (lineIndex
|
|
2340
|
+
if (lineIndex === exceptLineIndex) {
|
|
2341
|
+
keptLines.push(lineElement);
|
|
2342
|
+
}
|
|
2343
|
+
else {
|
|
2294
2344
|
lineElement.classList.remove('pre-active');
|
|
2295
2345
|
}
|
|
2296
|
-
}
|
|
2346
|
+
}
|
|
2347
|
+
this.preActiveLineElements = keptLines;
|
|
2297
2348
|
}
|
|
2298
2349
|
getPrimaryActiveLineIndex(activeIndices) {
|
|
2299
2350
|
if (activeIndices.length === 0)
|
|
@@ -2743,6 +2794,7 @@ let AmLyrics$1 = class AmLyrics extends i {
|
|
|
2743
2794
|
// Clean up any lingering scroll animations before smooth scroll
|
|
2744
2795
|
for (const line of animatingLines) {
|
|
2745
2796
|
line.classList.remove('scroll-animate');
|
|
2797
|
+
line.style.removeProperty('will-change');
|
|
2746
2798
|
line.style.removeProperty('--scroll-delta');
|
|
2747
2799
|
line.style.removeProperty('--lyrics-line-delay');
|
|
2748
2800
|
line.style.removeProperty('--scroll-duration');
|
|
@@ -2801,6 +2853,7 @@ let AmLyrics$1 = class AmLyrics extends i {
|
|
|
2801
2853
|
// --- Step 4: Re-add scroll-animate class to start fresh animations ---
|
|
2802
2854
|
for (const line of newAnimatingLines) {
|
|
2803
2855
|
line.classList.add('scroll-animate');
|
|
2856
|
+
line.style.willChange = 'transform';
|
|
2804
2857
|
animatingLines.push(line);
|
|
2805
2858
|
}
|
|
2806
2859
|
animState.isAnimating = true;
|
|
@@ -2817,6 +2870,7 @@ let AmLyrics$1 = class AmLyrics extends i {
|
|
|
2817
2870
|
for (let i = 0; i < animatingLines.length; i += 1) {
|
|
2818
2871
|
const line = animatingLines[i];
|
|
2819
2872
|
line.classList.remove('scroll-animate');
|
|
2873
|
+
line.style.removeProperty('will-change');
|
|
2820
2874
|
line.style.removeProperty('--scroll-delta');
|
|
2821
2875
|
line.style.removeProperty('--lyrics-line-delay');
|
|
2822
2876
|
line.style.removeProperty('--scroll-duration');
|
|
@@ -2845,12 +2899,14 @@ let AmLyrics$1 = class AmLyrics extends i {
|
|
|
2845
2899
|
'next-3',
|
|
2846
2900
|
'next-4',
|
|
2847
2901
|
];
|
|
2848
|
-
// Remove old position classes
|
|
2849
|
-
this.
|
|
2850
|
-
.
|
|
2851
|
-
|
|
2902
|
+
// Remove old position classes from tracked elements
|
|
2903
|
+
for (const el of this.positionedLineElements) {
|
|
2904
|
+
el.classList.remove(...positionClasses);
|
|
2905
|
+
}
|
|
2906
|
+
this.positionedLineElements = [];
|
|
2852
2907
|
// Add new position classes
|
|
2853
2908
|
lineToScroll.classList.add('lyrics-activest');
|
|
2909
|
+
this.positionedLineElements.push(lineToScroll);
|
|
2854
2910
|
const lineElements = Array.from(this.lyricsContainer.querySelectorAll('.lyrics-line'));
|
|
2855
2911
|
const scrollLineIndex = lineElements.indexOf(lineToScroll);
|
|
2856
2912
|
for (let i = Math.max(0, scrollLineIndex - 4); i <= Math.min(lineElements.length - 1, scrollLineIndex + 4); i += 1) {
|
|
@@ -2865,6 +2921,7 @@ let AmLyrics$1 = class AmLyrics extends i {
|
|
|
2865
2921
|
element.classList.add(`prev-${Math.abs(position)}`);
|
|
2866
2922
|
else
|
|
2867
2923
|
element.classList.add(`next-${position}`);
|
|
2924
|
+
this.positionedLineElements.push(element);
|
|
2868
2925
|
}
|
|
2869
2926
|
}
|
|
2870
2927
|
}
|
|
@@ -2885,7 +2942,7 @@ let AmLyrics$1 = class AmLyrics extends i {
|
|
|
2885
2942
|
return;
|
|
2886
2943
|
}
|
|
2887
2944
|
// Skip scroll if near the bottom of content (prevents footer jitter)
|
|
2888
|
-
if (!forceScroll) {
|
|
2945
|
+
if (!forceScroll && !activeLine.classList.contains('lyrics-footer')) {
|
|
2889
2946
|
const parent = this.lyricsContainer;
|
|
2890
2947
|
const atBottom = parent.scrollTop + parent.clientHeight >= parent.scrollHeight - 50;
|
|
2891
2948
|
if (atBottom) {
|
|
@@ -2909,7 +2966,7 @@ let AmLyrics$1 = class AmLyrics extends i {
|
|
|
2909
2966
|
* Update syllable highlight animation - apply CSS wipe animation
|
|
2910
2967
|
* (Exact copy from YouLyPlus _updateSyllableAnimation)
|
|
2911
2968
|
*/
|
|
2912
|
-
static updateSyllableAnimation(syllable) {
|
|
2969
|
+
static updateSyllableAnimation(syllable, elapsedTimeMs = 0) {
|
|
2913
2970
|
if (syllable.classList.contains('highlight'))
|
|
2914
2971
|
return;
|
|
2915
2972
|
const { classList } = syllable;
|
|
@@ -2937,8 +2994,8 @@ let AmLyrics$1 = class AmLyrics extends i {
|
|
|
2937
2994
|
const baseDelayPerChar = finalDuration * 0.09;
|
|
2938
2995
|
const growDurationMs = finalDuration * 1.5;
|
|
2939
2996
|
allWordCharSpans.forEach(span => {
|
|
2940
|
-
const
|
|
2941
|
-
const
|
|
2997
|
+
const matrixScale = span.dataset.matrixScale || '1.1';
|
|
2998
|
+
const charOffsetX = span.dataset.charOffsetX || '0';
|
|
2942
2999
|
const shadowIntensity = span.dataset.shadowIntensity || '0.6';
|
|
2943
3000
|
const translateYPeak = span.dataset.translateYPeak || '-2';
|
|
2944
3001
|
const syllableCharIndex = parseFloat(span.dataset.syllableCharIndex || '0');
|
|
@@ -2946,13 +3003,13 @@ let AmLyrics$1 = class AmLyrics extends i {
|
|
|
2946
3003
|
charAnimationsMap.set(span, `grow-dynamic ${growDurationMs}ms ease-in-out ${growDelay}ms forwards`);
|
|
2947
3004
|
styleUpdates.push({
|
|
2948
3005
|
element: span,
|
|
2949
|
-
property: '--
|
|
2950
|
-
value:
|
|
3006
|
+
property: '--matrix-scale',
|
|
3007
|
+
value: matrixScale,
|
|
2951
3008
|
});
|
|
2952
3009
|
styleUpdates.push({
|
|
2953
3010
|
element: span,
|
|
2954
|
-
property: '--
|
|
2955
|
-
value:
|
|
3011
|
+
property: '--char-offset-x',
|
|
3012
|
+
value: `${charOffsetX}px`,
|
|
2956
3013
|
});
|
|
2957
3014
|
styleUpdates.push({
|
|
2958
3015
|
element: span,
|
|
@@ -2962,7 +3019,7 @@ let AmLyrics$1 = class AmLyrics extends i {
|
|
|
2962
3019
|
styleUpdates.push({
|
|
2963
3020
|
element: span,
|
|
2964
3021
|
property: '--translate-y-peak',
|
|
2965
|
-
value: `${translateYPeak}`,
|
|
3022
|
+
value: `${translateYPeak}px`,
|
|
2966
3023
|
});
|
|
2967
3024
|
});
|
|
2968
3025
|
}
|
|
@@ -2971,7 +3028,7 @@ let AmLyrics$1 = class AmLyrics extends i {
|
|
|
2971
3028
|
charSpans.forEach((span, charIndex) => {
|
|
2972
3029
|
const startPct = parseFloat(span.dataset.wipeStart || '0');
|
|
2973
3030
|
const durationPct = parseFloat(span.dataset.wipeDuration || '0');
|
|
2974
|
-
const wipeDelay = syllableDurationMs * startPct;
|
|
3031
|
+
const wipeDelay = syllableDurationMs * startPct - elapsedTimeMs;
|
|
2975
3032
|
const wipeDuration = syllableDurationMs * durationPct;
|
|
2976
3033
|
const useStartAnimation = isFirstInContainer && charIndex === 0;
|
|
2977
3034
|
let charWipeAnimation = 'wipe';
|
|
@@ -2987,9 +3044,9 @@ let AmLyrics$1 = class AmLyrics extends i {
|
|
|
2987
3044
|
animationParts.push(existingAnimation.split(',')[0].trim());
|
|
2988
3045
|
}
|
|
2989
3046
|
if (charIndex > 0) {
|
|
2990
|
-
const arrivalTime = span.dataset.preWipeArrival
|
|
3047
|
+
const arrivalTime = (span.dataset.preWipeArrival
|
|
2991
3048
|
? parseFloat(span.dataset.preWipeArrival)
|
|
2992
|
-
:
|
|
3049
|
+
: syllableDurationMs * startPct) - elapsedTimeMs;
|
|
2993
3050
|
const constantDuration = parseFloat(span.dataset.preWipeDuration || '100');
|
|
2994
3051
|
const animDelay = arrivalTime - constantDuration;
|
|
2995
3052
|
if (constantDuration > 0) {
|
|
@@ -3019,12 +3076,13 @@ let AmLyrics$1 = class AmLyrics extends i {
|
|
|
3019
3076
|
return;
|
|
3020
3077
|
const currentWipeAnimation = isGap ? 'fade-gap' : wipeAnimation;
|
|
3021
3078
|
// eslint-disable-next-line no-param-reassign
|
|
3022
|
-
syllable.style.animation = `${currentWipeAnimation} ${visualDuration}ms ${isGap ? 'ease-out' : 'linear'} forwards`;
|
|
3079
|
+
syllable.style.animation = `${currentWipeAnimation} ${visualDuration}ms ${isGap ? 'ease-out' : 'linear'} ${-elapsedTimeMs}ms forwards`;
|
|
3023
3080
|
}
|
|
3024
3081
|
// --- WRITE PHASE ---
|
|
3025
3082
|
classList.remove('pre-highlight');
|
|
3026
3083
|
classList.add('highlight');
|
|
3027
3084
|
for (const [span, animationString] of charAnimationsMap.entries()) {
|
|
3085
|
+
span.style.willChange = 'transform';
|
|
3028
3086
|
span.style.animation = animationString;
|
|
3029
3087
|
}
|
|
3030
3088
|
// Apply style updates
|
|
@@ -3051,6 +3109,7 @@ let AmLyrics$1 = class AmLyrics extends i {
|
|
|
3051
3109
|
syllable.querySelectorAll('span.char').forEach(span => {
|
|
3052
3110
|
const el = span;
|
|
3053
3111
|
el.style.animation = '';
|
|
3112
|
+
el.style.willChange = '';
|
|
3054
3113
|
el.style.transition = 'none';
|
|
3055
3114
|
el.style.backgroundColor = 'var(--lyplus-text-secondary)';
|
|
3056
3115
|
});
|
|
@@ -3064,6 +3123,7 @@ let AmLyrics$1 = class AmLyrics extends i {
|
|
|
3064
3123
|
const el = span;
|
|
3065
3124
|
el.style.removeProperty('background-color');
|
|
3066
3125
|
el.style.removeProperty('transition');
|
|
3126
|
+
el.style.removeProperty('will-change');
|
|
3067
3127
|
});
|
|
3068
3128
|
});
|
|
3069
3129
|
}
|
|
@@ -3093,7 +3153,7 @@ let AmLyrics$1 = class AmLyrics extends i {
|
|
|
3093
3153
|
const syllable = syllables[i];
|
|
3094
3154
|
const startTime = parseFloat(syllable.getAttribute('data-start-time') || '0');
|
|
3095
3155
|
const endTime = parseFloat(syllable.getAttribute('data-end-time') || '0');
|
|
3096
|
-
if (startTime) {
|
|
3156
|
+
if (Number.isFinite(startTime) && Number.isFinite(endTime)) {
|
|
3097
3157
|
const { classList } = syllable;
|
|
3098
3158
|
const hasHighlight = classList.contains('highlight');
|
|
3099
3159
|
const hasFinished = classList.contains('finished');
|
|
@@ -3117,7 +3177,7 @@ let AmLyrics$1 = class AmLyrics extends i {
|
|
|
3117
3177
|
if (currentTimeMs >= startTime && currentTimeMs <= endTime) {
|
|
3118
3178
|
// Currently active
|
|
3119
3179
|
if (!hasHighlight) {
|
|
3120
|
-
AmLyrics.updateSyllableAnimation(syllable);
|
|
3180
|
+
AmLyrics.updateSyllableAnimation(syllable, currentTimeMs - startTime);
|
|
3121
3181
|
}
|
|
3122
3182
|
if (hasFinished) {
|
|
3123
3183
|
classList.remove('finished');
|
|
@@ -3127,7 +3187,7 @@ let AmLyrics$1 = class AmLyrics extends i {
|
|
|
3127
3187
|
// Finished
|
|
3128
3188
|
if (!hasFinished) {
|
|
3129
3189
|
if (!hasHighlight) {
|
|
3130
|
-
AmLyrics.updateSyllableAnimation(syllable);
|
|
3190
|
+
AmLyrics.updateSyllableAnimation(syllable, currentTimeMs - startTime);
|
|
3131
3191
|
}
|
|
3132
3192
|
classList.add('finished');
|
|
3133
3193
|
}
|
|
@@ -3379,7 +3439,6 @@ let AmLyrics$1 = class AmLyrics extends i {
|
|
|
3379
3439
|
}
|
|
3380
3440
|
// Set both old internal CSS variables (for backward compatibility)
|
|
3381
3441
|
// and new public CSS variables (which take precedence)
|
|
3382
|
-
this.style.setProperty('--hover-background-color', this.hoverBackgroundColor);
|
|
3383
3442
|
this.style.setProperty('--highlight-color', this.highlightColor);
|
|
3384
3443
|
const sourceLabel = this.lyricsSource ?? 'Unavailable';
|
|
3385
3444
|
const isUnsynced = this.cachedIsUnsynced;
|
|
@@ -3432,21 +3491,24 @@ let AmLyrics$1 = class AmLyrics extends i {
|
|
|
3432
3491
|
>${syllable.romanizedText}</span
|
|
3433
3492
|
>`
|
|
3434
3493
|
: '';
|
|
3435
|
-
return b `<span class="lyrics-word"
|
|
3436
|
-
|
|
3437
|
-
|
|
3438
|
-
|
|
3439
|
-
|
|
3494
|
+
return b `<span class="lyrics-word"
|
|
3495
|
+
><span
|
|
3496
|
+
class="lyrics-syllable-wrap${bgRomanizedText
|
|
3497
|
+
? ' has-transliteration'
|
|
3498
|
+
: ''}"
|
|
3499
|
+
><span
|
|
3500
|
+
class="lyrics-syllable no-chars${syllable.lineSynced
|
|
3501
|
+
? ' line-synced'
|
|
3440
3502
|
: ''}"
|
|
3441
3503
|
data-start-time="${startTimeMs}"
|
|
3442
3504
|
data-end-time="${endTimeMs}"
|
|
3443
3505
|
data-duration="${durationMs}"
|
|
3444
3506
|
data-syllable-index="${syllableIndex}"
|
|
3507
|
+
data-wipe-ratio="1"
|
|
3445
3508
|
>${syllable.text}</span
|
|
3446
|
-
|
|
3447
|
-
|
|
3448
|
-
|
|
3449
|
-
</span>`;
|
|
3509
|
+
>${bgRomanizedText}</span
|
|
3510
|
+
></span
|
|
3511
|
+
>`;
|
|
3450
3512
|
})}
|
|
3451
3513
|
</p>`
|
|
3452
3514
|
: '';
|
|
@@ -3464,8 +3526,11 @@ let AmLyrics$1 = class AmLyrics extends i {
|
|
|
3464
3526
|
const vwFullText = lineData?.vwFullText ?? [];
|
|
3465
3527
|
const vwFullDuration = lineData?.vwFullDuration ?? [];
|
|
3466
3528
|
const vwCharOffset = lineData?.vwCharOffset ?? [];
|
|
3529
|
+
const lineIsRTL = lineData?.lineIsRTL ?? false;
|
|
3467
3530
|
// Create main vocals using YouLyPlus syllable structure
|
|
3468
|
-
const mainVocalElement = b `<p
|
|
3531
|
+
const mainVocalElement = b `<p
|
|
3532
|
+
class="main-vocal-container ${lineIsRTL ? 'rtl-text' : ''}"
|
|
3533
|
+
>
|
|
3469
3534
|
${wordGroups.map((group, groupIdx) => {
|
|
3470
3535
|
const isGrowable = groupGrowable[groupIdx];
|
|
3471
3536
|
const isGlowing = groupGlowing[groupIdx];
|
|
@@ -3475,12 +3540,21 @@ let AmLyrics$1 = class AmLyrics extends i {
|
|
|
3475
3540
|
const wordNumChars = wordText.length;
|
|
3476
3541
|
const groupCharOffset = isGrowable ? vwCharOffset[groupIdx] : 0;
|
|
3477
3542
|
let sylCharAccumulator = 0;
|
|
3543
|
+
const groupText = group.map(s => s.text).join('');
|
|
3544
|
+
const shouldAllowBreak = groupText.trim().length >= 16 ||
|
|
3545
|
+
/[\u4e00-\u9fff\u3040-\u309f\u30a0-\u30ff\uac00-\ud7af]/.test(groupText);
|
|
3546
|
+
// Calculate dynamic rise duration based on the audio duration of the word
|
|
3547
|
+
const wordStartTimeMs = group[0].timestamp;
|
|
3548
|
+
const wordEndTimeMs = group[group.length - 1].endtime;
|
|
3549
|
+
const actualDurationMs = wordEndTimeMs - wordStartTimeMs;
|
|
3550
|
+
// Base float is 0.8s, plus a portion of the audio duration, capped between 1.0s and 2.5s
|
|
3551
|
+
const riseDuration = Math.max(1.2, Math.min(2.5, 1.2 + (actualDurationMs / 1000) * 0.6));
|
|
3478
3552
|
return b `<span
|
|
3479
|
-
class="lyrics-word
|
|
3480
|
-
? 'glowing'
|
|
3481
|
-
: ''}
|
|
3482
|
-
|
|
3483
|
-
|
|
3553
|
+
class="lyrics-word${isGrowable ? ' growable' : ''}${isGlowing
|
|
3554
|
+
? ' glowing'
|
|
3555
|
+
: ''}${shouldAllowBreak ? ' allow-break' : ''}"
|
|
3556
|
+
style="--rise-duration: ${riseDuration}s"
|
|
3557
|
+
>${group.map((syllable, sylIdx) => {
|
|
3484
3558
|
const startTimeMs = syllable.timestamp;
|
|
3485
3559
|
const endTimeMs = syllable.endtime;
|
|
3486
3560
|
const durationMs = endTimeMs - startTimeMs;
|
|
@@ -3566,17 +3640,22 @@ let AmLyrics$1 = class AmLyrics extends i {
|
|
|
3566
3640
|
data-wipe-duration="${(1 / numCharsInSyllable).toFixed(4)}"
|
|
3567
3641
|
data-horizontal-offset="${horizontalOffset.toFixed(2)}"
|
|
3568
3642
|
data-max-scale="${charMaxScale.toFixed(3)}"
|
|
3643
|
+
data-matrix-scale="${(charMaxScale * 0.98).toFixed(3)}"
|
|
3644
|
+
data-char-offset-x="${(horizontalOffset * 0.98).toFixed(2)}"
|
|
3569
3645
|
data-shadow-intensity="${charShadowIntensity.toFixed(3)}"
|
|
3570
3646
|
data-translate-y-peak="${charTranslateYPeak.toFixed(3)}"
|
|
3571
3647
|
>${char}</span
|
|
3572
3648
|
>`;
|
|
3573
3649
|
})}`;
|
|
3574
3650
|
}
|
|
3575
|
-
return b `<span
|
|
3576
|
-
|
|
3577
|
-
|
|
3578
|
-
? 'line-synced'
|
|
3651
|
+
return b `<span
|
|
3652
|
+
class="lyrics-syllable-wrap${romanizedText
|
|
3653
|
+
? ' has-transliteration'
|
|
3579
3654
|
: ''}"
|
|
3655
|
+
><span
|
|
3656
|
+
class="lyrics-syllable${groupLineSynced
|
|
3657
|
+
? ' line-synced'
|
|
3658
|
+
: ''}${isGrowable ? ' has-chars' : ' no-chars'}"
|
|
3580
3659
|
data-start-time="${startTimeMs}"
|
|
3581
3660
|
data-end-time="${endTimeMs}"
|
|
3582
3661
|
data-duration="${durationMs}"
|
|
@@ -3584,11 +3663,10 @@ let AmLyrics$1 = class AmLyrics extends i {
|
|
|
3584
3663
|
data-syllable-index="${sylIdx}"
|
|
3585
3664
|
data-wipe-ratio="1"
|
|
3586
3665
|
>${syllableContent}</span
|
|
3587
|
-
|
|
3588
|
-
|
|
3589
|
-
|
|
3590
|
-
|
|
3591
|
-
</span>`;
|
|
3666
|
+
>${romanizedText}</span
|
|
3667
|
+
>`;
|
|
3668
|
+
})}</span
|
|
3669
|
+
>`;
|
|
3592
3670
|
})}
|
|
3593
3671
|
</p>`;
|
|
3594
3672
|
// Translation container (if enabled)
|
|
@@ -3610,7 +3688,11 @@ let AmLyrics$1 = class AmLyrics extends i {
|
|
|
3610
3688
|
line.romanizedText &&
|
|
3611
3689
|
!line.text.some(s => s.romanizedText) &&
|
|
3612
3690
|
line.romanizedText.trim() !== fullLineText
|
|
3613
|
-
? b `<div
|
|
3691
|
+
? b `<div
|
|
3692
|
+
class="lyrics-romanization-container ${lineIsRTL
|
|
3693
|
+
? 'rtl-text'
|
|
3694
|
+
: ''}"
|
|
3695
|
+
>
|
|
3614
3696
|
${line.romanizedText}
|
|
3615
3697
|
</div>`
|
|
3616
3698
|
: '';
|
|
@@ -3630,42 +3712,37 @@ let AmLyrics$1 = class AmLyrics extends i {
|
|
|
3630
3712
|
data-end-time="${gapForLine.gapEnd}"
|
|
3631
3713
|
style="--gap-pulse-duration: ${GAP_PULSE_DURATION_MS}ms; --gap-loop-delay: -${gapLoopDelay}ms; --gap-exit-duration: ${GAP_EXIT_LEAD_MS}ms; --gap-exit-scale: ${GAP_MIN_SCALE};"
|
|
3632
3714
|
>
|
|
3633
|
-
<
|
|
3634
|
-
<
|
|
3635
|
-
|
|
3636
|
-
|
|
3637
|
-
|
|
3638
|
-
|
|
3639
|
-
|
|
3640
|
-
|
|
3641
|
-
|
|
3642
|
-
|
|
3643
|
-
|
|
3644
|
-
|
|
3645
|
-
|
|
3646
|
-
|
|
3647
|
-
|
|
3648
|
-
|
|
3649
|
-
|
|
3650
|
-
|
|
3651
|
-
|
|
3652
|
-
|
|
3653
|
-
|
|
3654
|
-
|
|
3655
|
-
|
|
3656
|
-
|
|
3657
|
-
|
|
3658
|
-
|
|
3659
|
-
|
|
3660
|
-
|
|
3661
|
-
|
|
3662
|
-
|
|
3663
|
-
|
|
3664
|
-
></span>
|
|
3665
|
-
</span>
|
|
3666
|
-
</span>
|
|
3667
|
-
</p>
|
|
3668
|
-
</div>
|
|
3715
|
+
<p class="main-vocal-container">
|
|
3716
|
+
<span class="lyrics-word"
|
|
3717
|
+
><span class="lyrics-syllable-wrap"
|
|
3718
|
+
><span
|
|
3719
|
+
class="lyrics-syllable"
|
|
3720
|
+
data-start-time="${gapForLine.gapStart}"
|
|
3721
|
+
data-end-time="${gapForLine.gapStart + dotDuration}"
|
|
3722
|
+
data-duration="${dotDuration}"
|
|
3723
|
+
data-wipe-ratio="1"
|
|
3724
|
+
data-syllable-index="0"
|
|
3725
|
+
></span></span
|
|
3726
|
+
><span class="lyrics-syllable-wrap"
|
|
3727
|
+
><span
|
|
3728
|
+
class="lyrics-syllable"
|
|
3729
|
+
data-start-time="${gapForLine.gapStart + dotDuration}"
|
|
3730
|
+
data-end-time="${gapForLine.gapStart + dotDuration * 2}"
|
|
3731
|
+
data-duration="${dotDuration}"
|
|
3732
|
+
data-wipe-ratio="1"
|
|
3733
|
+
data-syllable-index="1"
|
|
3734
|
+
></span></span
|
|
3735
|
+
><span class="lyrics-syllable-wrap"
|
|
3736
|
+
><span
|
|
3737
|
+
class="lyrics-syllable"
|
|
3738
|
+
data-start-time="${gapForLine.gapStart + dotDuration * 2}"
|
|
3739
|
+
data-end-time="${gapForLine.gapEnd}"
|
|
3740
|
+
data-duration="${dotDuration}"
|
|
3741
|
+
data-wipe-ratio="1"
|
|
3742
|
+
data-syllable-index="2"
|
|
3743
|
+
></span></span
|
|
3744
|
+
></span>
|
|
3745
|
+
</p>
|
|
3669
3746
|
</div>`;
|
|
3670
3747
|
}
|
|
3671
3748
|
return b `
|
|
@@ -3674,7 +3751,7 @@ let AmLyrics$1 = class AmLyrics extends i {
|
|
|
3674
3751
|
id="${lineId}"
|
|
3675
3752
|
class="lyrics-line ${line.alignment === 'end'
|
|
3676
3753
|
? 'singer-right'
|
|
3677
|
-
: 'singer-left'}"
|
|
3754
|
+
: 'singer-left'} ${lineIsRTL ? 'rtl-text' : ''}"
|
|
3678
3755
|
data-start-time="${lineStartTime}"
|
|
3679
3756
|
data-end-time="${lineEndTime}"
|
|
3680
3757
|
@click=${() => this.handleLineClick(line)}
|
|
@@ -3685,11 +3762,11 @@ let AmLyrics$1 = class AmLyrics extends i {
|
|
|
3685
3762
|
}
|
|
3686
3763
|
}}
|
|
3687
3764
|
>
|
|
3688
|
-
<div class="lyrics-line-container">
|
|
3765
|
+
<div class="lyrics-line-container ${lineIsRTL ? 'rtl-text' : ''}">
|
|
3689
3766
|
${bgPlacement === 'before' ? backgroundVocalElement : ''}
|
|
3690
3767
|
${mainVocalElement}
|
|
3691
3768
|
${bgPlacement === 'after' ? backgroundVocalElement : ''}
|
|
3692
|
-
${
|
|
3769
|
+
${lineRomanizationElement} ${translationElement}
|
|
3693
3770
|
</div>
|
|
3694
3771
|
</div>
|
|
3695
3772
|
`;
|
|
@@ -3802,13 +3879,13 @@ let AmLyrics$1 = class AmLyrics extends i {
|
|
|
3802
3879
|
${renderContent()}
|
|
3803
3880
|
${!this.isLoading
|
|
3804
3881
|
? b `
|
|
3805
|
-
<footer class="lyrics-footer">
|
|
3882
|
+
<footer class="lyrics-footer lyrics-line">
|
|
3806
3883
|
<div class="footer-content">
|
|
3807
3884
|
<span
|
|
3808
3885
|
class="source-info"
|
|
3809
3886
|
style="display: flex; align-items: center; gap: 8px;"
|
|
3810
3887
|
>
|
|
3811
|
-
|
|
3888
|
+
<b style="font-weight: 750;">Source</b> ${sourceLabel}
|
|
3812
3889
|
${(this.availableSources &&
|
|
3813
3890
|
this.availableSources.length > 1) ||
|
|
3814
3891
|
!this.hasFetchedAllProviders
|
|
@@ -3851,15 +3928,25 @@ let AmLyrics$1 = class AmLyrics extends i {
|
|
|
3851
3928
|
`
|
|
3852
3929
|
: ''}
|
|
3853
3930
|
</span>
|
|
3854
|
-
|
|
3855
|
-
|
|
3931
|
+
${this.songwriters
|
|
3932
|
+
? b `<span
|
|
3933
|
+
class="songwriters-info"
|
|
3934
|
+
style="margin-top: 4px; font-weight: normal; font-size: 0.9em;"
|
|
3935
|
+
>
|
|
3936
|
+
<b style="font-weight: 750;">Songwriters</b> ${this
|
|
3937
|
+
.songwriters}
|
|
3938
|
+
</span>`
|
|
3939
|
+
: ''}
|
|
3940
|
+
<span class="version-info" style="margin-top: 8px;">
|
|
3941
|
+
<b style="font-weight: 750;">am-lyrics</b> v${VERSION} •
|
|
3856
3942
|
|
|
3857
3943
|
<a
|
|
3858
3944
|
href="https://github.com/uimaxbai/apple-music-web-components"
|
|
3859
3945
|
target="_blank"
|
|
3860
3946
|
rel="noopener noreferrer"
|
|
3861
|
-
|
|
3862
|
-
|
|
3947
|
+
style="display: inline-flex; align-items: center; gap: 4px;"
|
|
3948
|
+
>Star me on GitHub
|
|
3949
|
+
</a>
|
|
3863
3950
|
</span>
|
|
3864
3951
|
</div>
|
|
3865
3952
|
</footer>
|
|
@@ -3896,6 +3983,7 @@ AmLyrics$1.styles = i$3 `
|
|
|
3896
3983
|
--lyplus-font-size-base: 32px;
|
|
3897
3984
|
--lyplus-font-size-base-grow: 24.5;
|
|
3898
3985
|
--lyplus-font-size-subtext: 0.6em;
|
|
3986
|
+
--char-rise-y: calc(-0.035 * var(--lyplus-font-size-base));
|
|
3899
3987
|
|
|
3900
3988
|
--lyplus-blur-amount: 0.07em;
|
|
3901
3989
|
--lyplus-blur-amount-near: 0.035em;
|
|
@@ -3929,7 +4017,6 @@ AmLyrics$1.styles = i$3 `
|
|
|
3929
4017
|
-webkit-overflow-scrolling: touch;
|
|
3930
4018
|
box-sizing: border-box;
|
|
3931
4019
|
scrollbar-width: none;
|
|
3932
|
-
transform: translateZ(0);
|
|
3933
4020
|
}
|
|
3934
4021
|
|
|
3935
4022
|
.lyrics-container::-webkit-scrollbar {
|
|
@@ -3940,11 +4027,13 @@ AmLyrics$1.styles = i$3 `
|
|
|
3940
4027
|
.lyrics-container.touch-scrolling .lyrics-line,
|
|
3941
4028
|
.lyrics-container.touch-scrolling .lyrics-plus-metadata {
|
|
3942
4029
|
transition: none !important;
|
|
4030
|
+
filter: none !important;
|
|
3943
4031
|
}
|
|
3944
4032
|
|
|
3945
4033
|
/* Apply smooth gliding transition for mouse-wheel scrolling */
|
|
3946
4034
|
.lyrics-container.wheel-scrolling .lyrics-line {
|
|
3947
4035
|
transition: transform 0.3s ease-out !important;
|
|
4036
|
+
filter: none !important;
|
|
3948
4037
|
}
|
|
3949
4038
|
|
|
3950
4039
|
.lyrics-line.scroll-animate {
|
|
@@ -3971,18 +4060,13 @@ AmLyrics$1.styles = i$3 `
|
|
|
3971
4060
|
font-size: var(--lyplus-font-size-base);
|
|
3972
4061
|
cursor: pointer;
|
|
3973
4062
|
transform-origin: left;
|
|
3974
|
-
transform: translateZ(1px);
|
|
3975
4063
|
transition:
|
|
3976
4064
|
opacity 0.3s ease,
|
|
3977
4065
|
transform 0.4s cubic-bezier(0.41, 0, 0.12, 0.99)
|
|
3978
4066
|
var(--lyrics-line-delay, 0ms),
|
|
3979
4067
|
filter 0.3s ease;
|
|
3980
|
-
will-change: transform, filter, opacity;
|
|
3981
4068
|
content-visibility: auto;
|
|
3982
4069
|
text-rendering: optimizeLegibility;
|
|
3983
|
-
overflow-wrap: break-word;
|
|
3984
|
-
mix-blend-mode: lighten;
|
|
3985
|
-
border-radius: var(--lyplus-border-radius-base);
|
|
3986
4070
|
}
|
|
3987
4071
|
|
|
3988
4072
|
.lyrics-line:not(.scroll-animate) {
|
|
@@ -4002,8 +4086,7 @@ AmLyrics$1.styles = i$3 `
|
|
|
4002
4086
|
|
|
4003
4087
|
.lyrics-line.active .lyrics-line-container,
|
|
4004
4088
|
.lyrics-line.pre-active .lyrics-line-container {
|
|
4005
|
-
transform: scale3d(1.001, 1.001, 1);
|
|
4006
|
-
will-change: transform;
|
|
4089
|
+
transform: scale3d(1.001, 1.001, 1) translateZ(0);
|
|
4007
4090
|
transition:
|
|
4008
4091
|
transform 0.5s ease,
|
|
4009
4092
|
background-color 0.18s,
|
|
@@ -4048,12 +4131,10 @@ AmLyrics$1.styles = i$3 `
|
|
|
4048
4131
|
.lyrics-line.active {
|
|
4049
4132
|
opacity: 1;
|
|
4050
4133
|
color: var(--lyplus-text-primary);
|
|
4051
|
-
will-change: transform, opacity;
|
|
4052
4134
|
}
|
|
4053
4135
|
|
|
4054
4136
|
.lyrics-line.pre-active {
|
|
4055
4137
|
opacity: 1;
|
|
4056
|
-
will-change: transform, opacity;
|
|
4057
4138
|
}
|
|
4058
4139
|
|
|
4059
4140
|
.lyrics-line.singer-right {
|
|
@@ -4067,6 +4148,18 @@ AmLyrics$1.styles = i$3 `
|
|
|
4067
4148
|
|
|
4068
4149
|
.lyrics-line.rtl-text {
|
|
4069
4150
|
direction: rtl;
|
|
4151
|
+
text-align: right !important;
|
|
4152
|
+
transform-origin: right;
|
|
4153
|
+
}
|
|
4154
|
+
|
|
4155
|
+
.lyrics-line.rtl-text .lyrics-line-container,
|
|
4156
|
+
.lyrics-line.rtl-text .main-vocal-container {
|
|
4157
|
+
transform-origin: right;
|
|
4158
|
+
}
|
|
4159
|
+
|
|
4160
|
+
.lyrics-line.rtl-text .lyrics-romanization-container,
|
|
4161
|
+
.lyrics-line.rtl-text .lyrics-translation-container {
|
|
4162
|
+
text-align: right;
|
|
4070
4163
|
}
|
|
4071
4164
|
|
|
4072
4165
|
/* --- Unsynced (Plain Text) Lyrics Overrides --- */
|
|
@@ -4098,7 +4191,8 @@ AmLyrics$1.styles = i$3 `
|
|
|
4098
4191
|
|
|
4099
4192
|
@media (hover: hover) and (pointer: fine) {
|
|
4100
4193
|
.lyrics-line:hover {
|
|
4101
|
-
|
|
4194
|
+
filter: none !important;
|
|
4195
|
+
opacity: 1 !important;
|
|
4102
4196
|
}
|
|
4103
4197
|
.lyrics-container.is-unsynced .lyrics-line:hover {
|
|
4104
4198
|
background: transparent !important;
|
|
@@ -4128,6 +4222,7 @@ AmLyrics$1.styles = i$3 `
|
|
|
4128
4222
|
|
|
4129
4223
|
/* Unblur all lines when user is scrolling */
|
|
4130
4224
|
.lyrics-container.user-scrolling .lyrics-line {
|
|
4225
|
+
transition: none !important;
|
|
4131
4226
|
filter: none !important;
|
|
4132
4227
|
opacity: 0.8 !important;
|
|
4133
4228
|
}
|
|
@@ -4144,6 +4239,7 @@ AmLyrics$1.styles = i$3 `
|
|
|
4144
4239
|
.lyrics-word:not(.allow-break) {
|
|
4145
4240
|
display: inline-block;
|
|
4146
4241
|
vertical-align: baseline;
|
|
4242
|
+
white-space: nowrap;
|
|
4147
4243
|
}
|
|
4148
4244
|
|
|
4149
4245
|
.lyrics-word.allow-break {
|
|
@@ -4154,7 +4250,7 @@ AmLyrics$1.styles = i$3 `
|
|
|
4154
4250
|
display: inline;
|
|
4155
4251
|
}
|
|
4156
4252
|
|
|
4157
|
-
.lyrics-syllable-wrap
|
|
4253
|
+
.lyrics-syllable-wrap.has-transliteration {
|
|
4158
4254
|
display: inline-flex;
|
|
4159
4255
|
flex-direction: column;
|
|
4160
4256
|
align-items: start;
|
|
@@ -4182,7 +4278,7 @@ AmLyrics$1.styles = i$3 `
|
|
|
4182
4278
|
transition: transform 1s ease !important;
|
|
4183
4279
|
}
|
|
4184
4280
|
|
|
4185
|
-
.lyrics-syllable.finished
|
|
4281
|
+
.lyrics-syllable.finished.has-chars {
|
|
4186
4282
|
background-color: transparent;
|
|
4187
4283
|
}
|
|
4188
4284
|
|
|
@@ -4191,19 +4287,16 @@ AmLyrics$1.styles = i$3 `
|
|
|
4191
4287
|
}
|
|
4192
4288
|
|
|
4193
4289
|
.lyrics-line.active:not(.lyrics-gap) .lyrics-syllable {
|
|
4194
|
-
transform: translateY(0.001%) translateZ(1px);
|
|
4195
4290
|
transition:
|
|
4196
4291
|
transform 1s ease,
|
|
4197
4292
|
background-color 0.5s,
|
|
4198
4293
|
color 0.5s;
|
|
4199
|
-
will-change: transform, background;
|
|
4200
4294
|
}
|
|
4201
4295
|
|
|
4202
4296
|
/* --- Wipe Highlight Effect --- */
|
|
4297
|
+
.lyrics-line.active:not(.lyrics-gap) .lyrics-syllable.highlight.no-chars,
|
|
4203
4298
|
.lyrics-line.active:not(.lyrics-gap)
|
|
4204
|
-
.lyrics-syllable.highlight
|
|
4205
|
-
.lyrics-line.active:not(.lyrics-gap)
|
|
4206
|
-
.lyrics-syllable.pre-highlight:not(:has(.char)) {
|
|
4299
|
+
.lyrics-syllable.pre-highlight.no-chars {
|
|
4207
4300
|
background-repeat: no-repeat;
|
|
4208
4301
|
background-image:
|
|
4209
4302
|
linear-gradient(
|
|
@@ -4245,11 +4338,19 @@ AmLyrics$1.styles = i$3 `
|
|
|
4245
4338
|
right;
|
|
4246
4339
|
}
|
|
4247
4340
|
|
|
4341
|
+
/* Non-growable words float up with a gentle curve */
|
|
4248
4342
|
.lyrics-line.active:not(.lyrics-gap)
|
|
4249
4343
|
.lyrics-word:not(.growable)
|
|
4250
|
-
.lyrics-syllable.highlight
|
|
4344
|
+
.lyrics-syllable.highlight {
|
|
4345
|
+
transform: translateY(-3.5%);
|
|
4346
|
+
transition:
|
|
4347
|
+
transform var(--rise-duration, 1.5s) cubic-bezier(0.22, 1, 0.36, 1),
|
|
4348
|
+
background-color 0.5s,
|
|
4349
|
+
color 0.5s;
|
|
4350
|
+
}
|
|
4351
|
+
|
|
4251
4352
|
.lyrics-word.growable .lyrics-syllable.cleanup .char {
|
|
4252
|
-
transform: translateY(-3.5%)
|
|
4353
|
+
transform: translateY(-3.5%);
|
|
4253
4354
|
}
|
|
4254
4355
|
|
|
4255
4356
|
.lyrics-line.active:not(.lyrics-gap) .lyrics-syllable.highlight.finished {
|
|
@@ -4276,7 +4377,7 @@ AmLyrics$1.styles = i$3 `
|
|
|
4276
4377
|
}
|
|
4277
4378
|
|
|
4278
4379
|
/* Syllable with chars: make syllable transparent, chars handle color */
|
|
4279
|
-
.lyrics-line .lyrics-syllable
|
|
4380
|
+
.lyrics-line .lyrics-syllable.has-chars:not(.finished) {
|
|
4280
4381
|
background-color: transparent;
|
|
4281
4382
|
color: transparent;
|
|
4282
4383
|
}
|
|
@@ -4289,6 +4390,7 @@ AmLyrics$1.styles = i$3 `
|
|
|
4289
4390
|
font-feature-settings: 'liga' 0;
|
|
4290
4391
|
background-clip: text;
|
|
4291
4392
|
-webkit-background-clip: text;
|
|
4393
|
+
backface-visibility: hidden;
|
|
4292
4394
|
transition:
|
|
4293
4395
|
color 0.7s,
|
|
4294
4396
|
background-color 0.7s,
|
|
@@ -4324,11 +4426,9 @@ AmLyrics$1.styles = i$3 `
|
|
|
4324
4426
|
-0.5em 0%,
|
|
4325
4427
|
-0.25em 0%;
|
|
4326
4428
|
transform-origin: 50% 80%;
|
|
4327
|
-
transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
|
4328
4429
|
transition:
|
|
4329
4430
|
transform 0.7s ease,
|
|
4330
4431
|
color 0.18s;
|
|
4331
|
-
will-change: background, transform;
|
|
4332
4432
|
}
|
|
4333
4433
|
|
|
4334
4434
|
.lyrics-line.active .lyrics-syllable span.char.highlight {
|
|
@@ -4380,6 +4480,8 @@ AmLyrics$1.styles = i$3 `
|
|
|
4380
4480
|
box-sizing: content-box;
|
|
4381
4481
|
background-clip: unset;
|
|
4382
4482
|
transform-origin: top;
|
|
4483
|
+
content-visibility: visible !important;
|
|
4484
|
+
contain: none !important;
|
|
4383
4485
|
transition:
|
|
4384
4486
|
opacity 160ms ease-out,
|
|
4385
4487
|
transform var(--scroll-duration, 280ms) var(--lyrics-line-delay, 0ms);
|
|
@@ -4390,41 +4492,35 @@ AmLyrics$1.styles = i$3 `
|
|
|
4390
4492
|
transition:
|
|
4391
4493
|
opacity 160ms ease-out,
|
|
4392
4494
|
transform var(--scroll-duration, 280ms);
|
|
4393
|
-
will-change: opacity;
|
|
4394
4495
|
}
|
|
4395
4496
|
|
|
4396
4497
|
/* Exiting state: quickly collapse width and height so dots don't distort page, or remove max-height transition */
|
|
4397
4498
|
.lyrics-gap.gap-exiting {
|
|
4398
4499
|
opacity: 1;
|
|
4399
|
-
transition: transform var(--scroll-duration, 280ms);
|
|
4400
4500
|
}
|
|
4401
4501
|
|
|
4402
4502
|
.lyrics-gap .main-vocal-container {
|
|
4403
|
-
transform: translateY(-25%) scale(1)
|
|
4503
|
+
transform: translateY(-25%) scale(1);
|
|
4404
4504
|
transition: transform 400ms cubic-bezier(0.22, 1, 0.36, 1);
|
|
4405
4505
|
}
|
|
4406
4506
|
|
|
4407
|
-
/* Jump animation plays during exit */
|
|
4408
|
-
.lyrics-gap.gap-exiting .main-vocal-container {
|
|
4409
|
-
animation: gap-ended var(--gap-exit-duration, 360ms)
|
|
4410
|
-
cubic-bezier(0.33, 1, 0.68, 1) forwards;
|
|
4411
|
-
}
|
|
4412
|
-
|
|
4413
4507
|
.lyrics-gap:not(.active):not(.gap-exiting) .main-vocal-container {
|
|
4414
|
-
transform: translateY(-25%) scale(0)
|
|
4415
|
-
}
|
|
4416
|
-
|
|
4417
|
-
.lyrics-gap:not(.active):not(.gap-exiting)
|
|
4418
|
-
.main-vocal-container
|
|
4419
|
-
.lyrics-word {
|
|
4420
|
-
animation-play-state: paused;
|
|
4508
|
+
transform: translateY(-25%) scale(0);
|
|
4421
4509
|
}
|
|
4422
4510
|
|
|
4423
|
-
|
|
4511
|
+
/* Pulse — must come BEFORE .gap-exiting so exiting wins via specificity+order */
|
|
4512
|
+
.lyrics-gap.active .main-vocal-container {
|
|
4424
4513
|
animation: gap-loop var(--gap-pulse-duration, 4000ms) ease-in-out infinite
|
|
4425
4514
|
alternate;
|
|
4426
4515
|
animation-delay: var(--gap-loop-delay, 0ms);
|
|
4427
|
-
|
|
4516
|
+
}
|
|
4517
|
+
|
|
4518
|
+
/* Jump animation plays during exit — disable transition so animation wins.
|
|
4519
|
+
Placed AFTER .active so it wins when both classes are present briefly. */
|
|
4520
|
+
.lyrics-gap.gap-exiting .main-vocal-container {
|
|
4521
|
+
animation: gap-ended var(--gap-exit-duration, 360ms)
|
|
4522
|
+
cubic-bezier(0.33, 1, 0.68, 1) forwards;
|
|
4523
|
+
transition: none !important;
|
|
4428
4524
|
}
|
|
4429
4525
|
|
|
4430
4526
|
.lyrics-gap .lyrics-syllable {
|
|
@@ -4475,20 +4571,17 @@ AmLyrics$1.styles = i$3 `
|
|
|
4475
4571
|
background-clip: unset;
|
|
4476
4572
|
}
|
|
4477
4573
|
|
|
4478
|
-
.lyrics-gap.active .lyrics-syllable.highlight,
|
|
4479
4574
|
.lyrics-gap.active .lyrics-syllable.finished,
|
|
4480
|
-
.lyrics-gap.gap-exiting .lyrics-syllable,
|
|
4481
|
-
.lyrics-gap:not(.active).post-active-line
|
|
4482
|
-
|
|
4575
|
+
.lyrics-gap.gap-exiting .lyrics-syllable.finished,
|
|
4576
|
+
.lyrics-gap:not(.active):not(.gap-exiting).post-active-line
|
|
4577
|
+
.lyrics-syllable,
|
|
4578
|
+
.lyrics-gap:not(.active):not(.gap-exiting).lyrics-activest
|
|
4579
|
+
.lyrics-syllable {
|
|
4483
4580
|
background-color: var(--lyplus-text-primary);
|
|
4484
4581
|
animation: none !important;
|
|
4485
4582
|
opacity: 1;
|
|
4486
4583
|
}
|
|
4487
4584
|
|
|
4488
|
-
.lyrics-gap.active .lyrics-syllable.finished {
|
|
4489
|
-
animation: none !important;
|
|
4490
|
-
}
|
|
4491
|
-
|
|
4492
4585
|
/* ==========================================================================
|
|
4493
4586
|
METADATA & FOOTER STYLES
|
|
4494
4587
|
========================================================================== */
|
|
@@ -4517,12 +4610,49 @@ AmLyrics$1.styles = i$3 `
|
|
|
4517
4610
|
align-items: center;
|
|
4518
4611
|
flex-wrap: wrap;
|
|
4519
4612
|
text-align: left;
|
|
4520
|
-
font-size:
|
|
4521
|
-
color: rgba(255, 255, 255, 0.
|
|
4522
|
-
padding:
|
|
4523
|
-
border-top: 1px solid rgba(255, 255, 255, 0.1);
|
|
4613
|
+
font-size: 1.2em;
|
|
4614
|
+
color: rgba(255, 255, 255, 0.6);
|
|
4615
|
+
padding: 20px 0 50vh 0;
|
|
4524
4616
|
margin-top: 10px;
|
|
4525
|
-
font-weight:
|
|
4617
|
+
font-weight: 400;
|
|
4618
|
+
opacity: 0.8;
|
|
4619
|
+
transition:
|
|
4620
|
+
opacity 0.3s ease,
|
|
4621
|
+
transform 0.5s cubic-bezier(0.41, 0, 0.12, 0.99),
|
|
4622
|
+
filter 0.3s ease;
|
|
4623
|
+
transform-origin: left;
|
|
4624
|
+
}
|
|
4625
|
+
|
|
4626
|
+
.lyrics-footer.lyrics-line {
|
|
4627
|
+
font-size: 1.2em;
|
|
4628
|
+
padding: 20px var(--lyplus-padding-line) 50vh var(--lyplus-padding-line);
|
|
4629
|
+
cursor: default;
|
|
4630
|
+
}
|
|
4631
|
+
|
|
4632
|
+
.lyrics-footer.active {
|
|
4633
|
+
opacity: 1;
|
|
4634
|
+
color: rgba(255, 255, 255, 0.5); /* Grey instead of primary */
|
|
4635
|
+
}
|
|
4636
|
+
|
|
4637
|
+
.lyrics-footer.scroll-animate {
|
|
4638
|
+
transition: none !important;
|
|
4639
|
+
animation-name: lyrics-scroll;
|
|
4640
|
+
animation-duration: var(--scroll-duration, 280ms);
|
|
4641
|
+
animation-timing-function: cubic-bezier(0.41, 0, 0.12, 0.99);
|
|
4642
|
+
animation-fill-mode: both;
|
|
4643
|
+
animation-delay: var(--lyrics-line-delay, 0ms);
|
|
4644
|
+
}
|
|
4645
|
+
|
|
4646
|
+
.lyrics-container.blur-inactive-enabled:not(.not-focused)
|
|
4647
|
+
.lyrics-footer:not(.active) {
|
|
4648
|
+
filter: blur(var(--lyplus-blur-amount));
|
|
4649
|
+
opacity: 0.5;
|
|
4650
|
+
}
|
|
4651
|
+
|
|
4652
|
+
.lyrics-container.user-scrolling .lyrics-footer {
|
|
4653
|
+
transition: none !important;
|
|
4654
|
+
filter: none !important;
|
|
4655
|
+
opacity: 0.8 !important;
|
|
4526
4656
|
}
|
|
4527
4657
|
|
|
4528
4658
|
.lyrics-footer p {
|
|
@@ -4530,12 +4660,14 @@ AmLyrics$1.styles = i$3 `
|
|
|
4530
4660
|
}
|
|
4531
4661
|
|
|
4532
4662
|
.lyrics-footer a {
|
|
4533
|
-
color:
|
|
4534
|
-
text-
|
|
4663
|
+
color: var(--lyplus-text-primary); /* Stand out using primary color */
|
|
4664
|
+
text-underline-offset: 2px;
|
|
4665
|
+
opacity: 0.8;
|
|
4666
|
+
transition: opacity 0.2s;
|
|
4535
4667
|
}
|
|
4536
4668
|
|
|
4537
4669
|
.lyrics-footer a:hover {
|
|
4538
|
-
|
|
4670
|
+
opacity: 1;
|
|
4539
4671
|
}
|
|
4540
4672
|
|
|
4541
4673
|
.footer-content {
|
|
@@ -4659,6 +4791,7 @@ AmLyrics$1.styles = i$3 `
|
|
|
4659
4791
|
|
|
4660
4792
|
.lyrics-romanization-container.rtl-text {
|
|
4661
4793
|
direction: rtl !important;
|
|
4794
|
+
text-align: right;
|
|
4662
4795
|
}
|
|
4663
4796
|
|
|
4664
4797
|
.lyrics-romanization-container .lyrics-syllable {
|
|
@@ -4872,23 +5005,22 @@ AmLyrics$1.styles = i$3 `
|
|
|
4872
5005
|
/* Gap dot animations */
|
|
4873
5006
|
@keyframes gap-loop {
|
|
4874
5007
|
from {
|
|
4875
|
-
transform: scale(1.12);
|
|
5008
|
+
transform: translateY(-25%) scale(1.12);
|
|
4876
5009
|
}
|
|
4877
5010
|
to {
|
|
4878
|
-
transform: scale(var(--gap-exit-scale, 0.85));
|
|
5011
|
+
transform: translateY(-25%) scale(var(--gap-exit-scale, 0.85));
|
|
4879
5012
|
}
|
|
4880
5013
|
}
|
|
4881
5014
|
|
|
4882
5015
|
@keyframes gap-ended {
|
|
4883
5016
|
0% {
|
|
4884
|
-
transform: translateY(-25%) scale(var(--gap-exit-scale, 0.85))
|
|
4885
|
-
translateZ(0);
|
|
5017
|
+
transform: translateY(-25%) scale(var(--gap-exit-scale, 0.85));
|
|
4886
5018
|
}
|
|
4887
5019
|
35% {
|
|
4888
|
-
transform: translateY(-
|
|
5020
|
+
transform: translateY(-25%) scale(1.2);
|
|
4889
5021
|
}
|
|
4890
5022
|
100% {
|
|
4891
|
-
transform: translateY(-25%) scale(0)
|
|
5023
|
+
transform: translateY(-25%) scale(0);
|
|
4892
5024
|
}
|
|
4893
5025
|
}
|
|
4894
5026
|
|
|
@@ -4905,17 +5037,18 @@ AmLyrics$1.styles = i$3 `
|
|
|
4905
5037
|
reflow in between) to reliably restart the animation each time */
|
|
4906
5038
|
@keyframes lyrics-scroll {
|
|
4907
5039
|
from {
|
|
4908
|
-
transform:
|
|
5040
|
+
transform: translate3d(0, var(--scroll-delta), 0);
|
|
4909
5041
|
}
|
|
4910
5042
|
to {
|
|
4911
|
-
transform:
|
|
5043
|
+
transform: translate3d(0, 0, 0);
|
|
4912
5044
|
}
|
|
4913
5045
|
}
|
|
4914
5046
|
|
|
4915
|
-
/* Character grow animation
|
|
5047
|
+
/* Character grow animation — translate3d+scale3d for smooth transform,
|
|
5048
|
+
drop-shadow for glow (text-shadow doesn't work with background-clip:text) */
|
|
4916
5049
|
@keyframes grow-dynamic {
|
|
4917
5050
|
0% {
|
|
4918
|
-
transform:
|
|
5051
|
+
transform: translate3d(0, 0, 0) scale3d(1, 1, 1);
|
|
4919
5052
|
filter: drop-shadow(
|
|
4920
5053
|
0 0 0
|
|
4921
5054
|
color-mix(in srgb, var(--lyplus-lyrics-palette), transparent 100%)
|
|
@@ -4923,27 +5056,12 @@ AmLyrics$1.styles = i$3 `
|
|
|
4923
5056
|
}
|
|
4924
5057
|
25%,
|
|
4925
5058
|
30% {
|
|
4926
|
-
transform:
|
|
4927
|
-
|
|
4928
|
-
|
|
4929
|
-
|
|
4930
|
-
|
|
4931
|
-
|
|
4932
|
-
calc(var(--max-scale) * calc(var(--lyplus-font-size-base-grow) / 25)),
|
|
4933
|
-
0,
|
|
4934
|
-
0,
|
|
4935
|
-
0,
|
|
4936
|
-
0,
|
|
4937
|
-
1,
|
|
4938
|
-
0,
|
|
4939
|
-
calc(
|
|
4940
|
-
var(--char-offset-x, 0) *
|
|
4941
|
-
calc(var(--lyplus-font-size-base-grow) / 25)
|
|
4942
|
-
),
|
|
4943
|
-
var(--translate-y-peak, -2),
|
|
4944
|
-
0,
|
|
4945
|
-
1
|
|
4946
|
-
);
|
|
5059
|
+
transform: translate3d(
|
|
5060
|
+
var(--char-offset-x, 0px),
|
|
5061
|
+
var(--translate-y-peak, -2px),
|
|
5062
|
+
0
|
|
5063
|
+
)
|
|
5064
|
+
scale3d(var(--matrix-scale, 1.1), var(--matrix-scale, 1.1), 1);
|
|
4947
5065
|
filter: drop-shadow(
|
|
4948
5066
|
0 0 0.1em
|
|
4949
5067
|
color-mix(
|
|
@@ -4953,8 +5071,10 @@ AmLyrics$1.styles = i$3 `
|
|
|
4953
5071
|
)
|
|
4954
5072
|
);
|
|
4955
5073
|
}
|
|
5074
|
+
75%,
|
|
4956
5075
|
100% {
|
|
4957
|
-
transform:
|
|
5076
|
+
transform: translate3d(0, var(--char-rise-y, -1.12px), 0)
|
|
5077
|
+
scale3d(1, 1, 1);
|
|
4958
5078
|
filter: drop-shadow(
|
|
4959
5079
|
0 0 0
|
|
4960
5080
|
color-mix(in srgb, var(--lyplus-lyrics-palette), transparent 100%)
|
|
@@ -5086,15 +5206,15 @@ __decorate([
|
|
|
5086
5206
|
__decorate([
|
|
5087
5207
|
n({ type: String, attribute: 'song-album' })
|
|
5088
5208
|
], AmLyrics$1.prototype, "songAlbum", void 0);
|
|
5209
|
+
__decorate([
|
|
5210
|
+
n({ type: String, attribute: 'songwriters' })
|
|
5211
|
+
], AmLyrics$1.prototype, "songwriters", void 0);
|
|
5089
5212
|
__decorate([
|
|
5090
5213
|
n({ type: Number, attribute: 'song-duration' })
|
|
5091
5214
|
], AmLyrics$1.prototype, "songDurationMs", void 0);
|
|
5092
5215
|
__decorate([
|
|
5093
5216
|
n({ type: String, attribute: 'highlight-color' })
|
|
5094
5217
|
], AmLyrics$1.prototype, "highlightColor", void 0);
|
|
5095
|
-
__decorate([
|
|
5096
|
-
n({ type: String, attribute: 'hover-background-color' })
|
|
5097
|
-
], AmLyrics$1.prototype, "hoverBackgroundColor", void 0);
|
|
5098
5218
|
__decorate([
|
|
5099
5219
|
n({ type: String, attribute: 'font-family' })
|
|
5100
5220
|
], AmLyrics$1.prototype, "fontFamily", void 0);
|