@uimaxbai/am-lyrics 1.5.3 → 1.5.4

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.
@@ -1 +1 @@
1
- {"version":3,"file":"AmLyrics.d.ts","sourceRoot":"","sources":["../../src/AmLyrics.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"AmLyrics.d.ts","sourceRoot":"","sources":["../../src/AmLyrics.ts"],"names":[],"mappings":"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"}
@@ -319,7 +319,7 @@ class GoogleService {
319
319
  }
320
320
  }
321
321
 
322
- const VERSION = '1.5.3';
322
+ const VERSION = '1.5.4';
323
323
  const INSTRUMENTAL_THRESHOLD_MS = 7000; // Show dots for gaps >= 7s
324
324
  const FETCH_TIMEOUT_MS = 8000; // Timeout for all lyrics fetch requests
325
325
  const SEEK_THRESHOLD_MS = 500;
@@ -2419,7 +2419,9 @@ class AmLyrics extends i {
2419
2419
  lineIsRTL = true;
2420
2420
  const hasHyphen = combinedText.includes('-');
2421
2421
  const wordLen = combinedText.length;
2422
- let isGrowableVW = !isCJK && !isRTL && !hasHyphen && wordLen > 0 && wordLen <= 7;
2422
+ const canAnimateByChar = !isCJK && !isRTL && !hasHyphen && wordLen > 0;
2423
+ const isLineSynced = line.isWordSynced === false || line.text.some(s => s.lineSynced);
2424
+ let isGrowableVW = canAnimateByChar && wordLen > 0 && wordLen <= 7;
2423
2425
  if (isGrowableVW) {
2424
2426
  if (wordLen < 3) {
2425
2427
  isGrowableVW =
@@ -2430,9 +2432,14 @@ class AmLyrics extends i {
2430
2432
  combinedDuration >= 850 && combinedDuration >= wordLen * 190;
2431
2433
  }
2432
2434
  }
2433
- const isLineSynced = line.isWordSynced === false || line.text.some(s => s.lineSynced);
2435
+ const hasCharRiseDuration = combinedDuration >= Math.max(700, wordLen * 85);
2436
+ const hasLongShortWordDuration = wordLen >= 4 && combinedDuration >= Math.max(1300, wordLen * 260);
2437
+ const isCharRiseVW = canAnimateByChar &&
2438
+ !isLineSynced &&
2439
+ !isGrowableVW &&
2440
+ ((wordLen >= 8 && hasCharRiseDuration) ||
2441
+ (wordLen < 8 && hasLongShortWordDuration));
2434
2442
  const isGlowingVW = isGrowableVW && !isLineSynced;
2435
- const isCharRiseVW = !isGrowableVW && !isLineSynced && !isCJK && !isRTL && wordLen >= 8;
2436
2443
  let charOff = 0;
2437
2444
  for (let gi = vwStart; gi <= vwEnd; gi += 1) {
2438
2445
  groupGrowable[gi] = isGrowableVW;
@@ -3337,12 +3344,24 @@ class AmLyrics extends i {
3337
3344
  const isRTL = classList.contains('rtl-text');
3338
3345
  const charSpans = Array.from(syllable.querySelectorAll('span.char'));
3339
3346
  const wordElement = syllable.parentElement?.parentElement; // syllable-wrap -> word
3340
- const allWordCharSpans = wordElement
3341
- ? Array.from(wordElement.querySelectorAll('span.char'))
3342
- : [];
3347
+ const virtualWordId = wordElement?.dataset
3348
+ .virtualWordId;
3349
+ let wordElements = [];
3350
+ if (virtualWordId && wordElement?.parentElement) {
3351
+ wordElements = Array.from(wordElement.parentElement.querySelectorAll('.lyrics-word')).filter(el => el.dataset.virtualWordId === virtualWordId);
3352
+ }
3353
+ else if (wordElement) {
3354
+ wordElements = [wordElement];
3355
+ }
3356
+ const allWordCharSpans = wordElements.flatMap(word => Array.from(word.querySelectorAll('span.char')));
3343
3357
  const isGrowable = wordElement?.classList.contains('growable');
3344
3358
  const isCharRise = wordElement?.classList.contains('char-rise');
3345
3359
  const isFirstSyllable = syllable.getAttribute('data-syllable-index') === '0';
3360
+ const syllableStartMs = parseFloat(syllable.getAttribute('data-start-time') || '0');
3361
+ const virtualWordStartMs = parseFloat(wordElement?.dataset.virtualWordStart || '');
3362
+ const isFirstInVirtualWord = isFirstSyllable &&
3363
+ (!Number.isFinite(virtualWordStartMs) ||
3364
+ Math.abs(syllableStartMs - virtualWordStartMs) < 0.5);
3346
3365
  const isFirstInContainer = isFirstSyllable; // Simplified
3347
3366
  const isGap = syllable.closest('.lyrics-gap') !== null;
3348
3367
  // Get duration from data attribute
@@ -3354,7 +3373,7 @@ class AmLyrics extends i {
3354
3373
  const charAnimationsMap = new Map();
3355
3374
  const styleUpdates = [];
3356
3375
  // Step 1: Grow Pass
3357
- if (isGrowable && isFirstSyllable && allWordCharSpans.length > 0) {
3376
+ if (isGrowable && isFirstInVirtualWord && allWordCharSpans.length > 0) {
3358
3377
  const finalDuration = wordDurationMs;
3359
3378
  const baseDelayPerChar = finalDuration * 0.09;
3360
3379
  const growDurationMs = finalDuration * 1.5;
@@ -3388,7 +3407,7 @@ class AmLyrics extends i {
3388
3407
  });
3389
3408
  });
3390
3409
  }
3391
- if (isCharRise && isFirstSyllable && allWordCharSpans.length > 0) {
3410
+ if (isCharRise && isFirstInVirtualWord && allWordCharSpans.length > 0) {
3392
3411
  const finalDuration = Math.max(wordDurationMs, syllableDurationMs);
3393
3412
  const baseDelayPerChar = finalDuration * 0.09;
3394
3413
  const riseDurationMs = finalDuration * 1.5;
@@ -3420,14 +3439,15 @@ class AmLyrics extends i {
3420
3439
  existingAnimation.includes('rise-char'))) {
3421
3440
  animationParts.push(existingAnimation.split(',')[0].trim());
3422
3441
  }
3423
- if (charIndex > 0) {
3442
+ if (charIndex > 0 && wipeDelay > 0 && wipeDuration > 0) {
3424
3443
  const arrivalTime = (span.dataset.preWipeArrival
3425
3444
  ? parseFloat(span.dataset.preWipeArrival)
3426
3445
  : syllableDurationMs * startPct) - elapsedTimeMs;
3427
- const constantDuration = parseFloat(span.dataset.preWipeDuration || '100');
3428
- const animDelay = arrivalTime - constantDuration;
3429
- if (constantDuration > 0) {
3430
- animationParts.push(`pre-wipe-char ${constantDuration}ms linear ${animDelay}ms forwards`);
3446
+ const measuredPreWipeDuration = parseFloat(span.dataset.preWipeDuration || '100');
3447
+ const preWipeDuration = Math.min(measuredPreWipeDuration, wipeDuration * 0.9, syllableDurationMs * 0.08, arrivalTime);
3448
+ const animDelay = arrivalTime - preWipeDuration;
3449
+ if (preWipeDuration >= 16) {
3450
+ animationParts.push(`pre-wipe-char ${preWipeDuration}ms linear ${animDelay}ms none`);
3431
3451
  }
3432
3452
  }
3433
3453
  if (wipeDuration > 0) {
@@ -4005,6 +4025,8 @@ class AmLyrics extends i {
4005
4025
  const vwFullText = lineData?.vwFullText ?? [];
4006
4026
  const vwFullDuration = lineData?.vwFullDuration ?? [];
4007
4027
  const vwCharOffset = lineData?.vwCharOffset ?? [];
4028
+ const vwStartMs = lineData?.vwStartMs ?? [];
4029
+ const vwEndMs = lineData?.vwEndMs ?? [];
4008
4030
  const lineIsRTL = lineData?.lineIsRTL ?? false;
4009
4031
  // Create main vocals using YouLyPlus syllable structure
4010
4032
  const mainVocalElement = b `<p
@@ -4024,6 +4046,13 @@ class AmLyrics extends i {
4024
4046
  const groupCharOffset = isAnimatedByChar
4025
4047
  ? vwCharOffset[groupIdx]
4026
4048
  : 0;
4049
+ const virtualWordId = isAnimatedByChar
4050
+ ? `${lineIndex}:${vwStartMs[groupIdx]}:${vwEndMs[groupIdx]}`
4051
+ : '';
4052
+ const virtualWordStart = isAnimatedByChar
4053
+ ? vwStartMs[groupIdx]
4054
+ : '';
4055
+ const virtualWordEnd = isAnimatedByChar ? vwEndMs[groupIdx] : '';
4027
4056
  let sylCharAccumulator = 0;
4028
4057
  const groupText = group.map(s => s.text).join('');
4029
4058
  const shouldAllowBreak = groupText.trim().length >= 16 ||
@@ -4040,6 +4069,9 @@ class AmLyrics extends i {
4040
4069
  : ''}${isGlowing ? ' glowing' : ''}${shouldAllowBreak
4041
4070
  ? ' allow-break'
4042
4071
  : ''}"
4072
+ data-virtual-word-id="${virtualWordId}"
4073
+ data-virtual-word-start="${virtualWordStart}"
4074
+ data-virtual-word-end="${virtualWordEnd}"
4043
4075
  style="--rise-duration: ${riseDuration}s"
4044
4076
  >${group.map((syllable, sylIdx) => {
4045
4077
  const startTimeMs = syllable.timestamp;
@@ -4598,17 +4630,15 @@ AmLyrics.styles = i$3 `
4598
4630
 
4599
4631
  .background-vocal-container {
4600
4632
  max-height: 0;
4601
- overflow: visible;
4633
+ overflow: hidden;
4602
4634
  opacity: 0;
4603
4635
  font-size: var(--lyplus-font-size-subtext);
4604
4636
  line-height: 1.15;
4605
4637
  color: color-mix(in srgb, var(--lyplus-text-secondary) 80%, transparent);
4606
- /* Fast exit (0.25 s) so bg vocals collapse quickly and feel snappy.
4607
- The scroll takes ~0.4 s; finishing the collapse first prevents
4608
- the container from trailing behind the motion. */
4609
4638
  transition:
4610
- max-height 250ms cubic-bezier(0.41, 0, 0.12, 0.99),
4611
- opacity 250ms cubic-bezier(0.41, 0, 0.12, 0.99);
4639
+ max-height var(--scroll-duration, 400ms)
4640
+ cubic-bezier(0.41, 0, 0.12, 0.99),
4641
+ opacity var(--scroll-duration, 400ms) cubic-bezier(0.41, 0, 0.12, 0.99);
4612
4642
  margin: 0;
4613
4643
  pointer-events: none;
4614
4644
  }
@@ -4617,7 +4647,8 @@ AmLyrics.styles = i$3 `
4617
4647
  display: block;
4618
4648
  padding-top: 0;
4619
4649
  padding-bottom: 0;
4620
- transition: padding-top 250ms cubic-bezier(0.41, 0, 0.12, 0.99);
4650
+ transition: padding-top var(--scroll-duration, 400ms)
4651
+ cubic-bezier(0.41, 0, 0.12, 0.99);
4621
4652
  }
4622
4653
 
4623
4654
  .lyrics-line.singer-right .background-vocal-container,
@@ -4632,16 +4663,11 @@ AmLyrics.styles = i$3 `
4632
4663
  .lyrics-line.bg-expanded .background-vocal-container {
4633
4664
  max-height: 4em;
4634
4665
  opacity: 1;
4635
- /* Slower entry (0.6 s) so bg vocals expand smoothly. */
4636
- transition:
4637
- max-height 0.6s ease,
4638
- opacity 0.6s ease;
4639
4666
  will-change: max-height, opacity;
4640
4667
  }
4641
4668
 
4642
4669
  .lyrics-line.bg-expanded .background-vocal-wrap {
4643
4670
  padding-top: 0.26em;
4644
- transition: padding-top 0.6s ease;
4645
4671
  }
4646
4672
 
4647
4673
  /* --- Line States & Modifiers --- */