@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.
package/dist/src/react.js CHANGED
@@ -322,7 +322,7 @@ class GoogleService {
322
322
  }
323
323
  }
324
324
 
325
- const VERSION = '1.5.3';
325
+ const VERSION = '1.5.4';
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;
@@ -2422,7 +2422,9 @@ let AmLyrics$1 = class AmLyrics extends i {
2422
2422
  lineIsRTL = true;
2423
2423
  const hasHyphen = combinedText.includes('-');
2424
2424
  const wordLen = combinedText.length;
2425
- let isGrowableVW = !isCJK && !isRTL && !hasHyphen && wordLen > 0 && wordLen <= 7;
2425
+ const canAnimateByChar = !isCJK && !isRTL && !hasHyphen && wordLen > 0;
2426
+ const isLineSynced = line.isWordSynced === false || line.text.some(s => s.lineSynced);
2427
+ let isGrowableVW = canAnimateByChar && wordLen > 0 && wordLen <= 7;
2426
2428
  if (isGrowableVW) {
2427
2429
  if (wordLen < 3) {
2428
2430
  isGrowableVW =
@@ -2433,9 +2435,14 @@ let AmLyrics$1 = class AmLyrics extends i {
2433
2435
  combinedDuration >= 850 && combinedDuration >= wordLen * 190;
2434
2436
  }
2435
2437
  }
2436
- const isLineSynced = line.isWordSynced === false || line.text.some(s => s.lineSynced);
2438
+ const hasCharRiseDuration = combinedDuration >= Math.max(700, wordLen * 85);
2439
+ const hasLongShortWordDuration = wordLen >= 4 && combinedDuration >= Math.max(1300, wordLen * 260);
2440
+ const isCharRiseVW = canAnimateByChar &&
2441
+ !isLineSynced &&
2442
+ !isGrowableVW &&
2443
+ ((wordLen >= 8 && hasCharRiseDuration) ||
2444
+ (wordLen < 8 && hasLongShortWordDuration));
2437
2445
  const isGlowingVW = isGrowableVW && !isLineSynced;
2438
- const isCharRiseVW = !isGrowableVW && !isLineSynced && !isCJK && !isRTL && wordLen >= 8;
2439
2446
  let charOff = 0;
2440
2447
  for (let gi = vwStart; gi <= vwEnd; gi += 1) {
2441
2448
  groupGrowable[gi] = isGrowableVW;
@@ -3340,12 +3347,24 @@ let AmLyrics$1 = class AmLyrics extends i {
3340
3347
  const isRTL = classList.contains('rtl-text');
3341
3348
  const charSpans = Array.from(syllable.querySelectorAll('span.char'));
3342
3349
  const wordElement = syllable.parentElement?.parentElement; // syllable-wrap -> word
3343
- const allWordCharSpans = wordElement
3344
- ? Array.from(wordElement.querySelectorAll('span.char'))
3345
- : [];
3350
+ const virtualWordId = wordElement?.dataset
3351
+ .virtualWordId;
3352
+ let wordElements = [];
3353
+ if (virtualWordId && wordElement?.parentElement) {
3354
+ wordElements = Array.from(wordElement.parentElement.querySelectorAll('.lyrics-word')).filter(el => el.dataset.virtualWordId === virtualWordId);
3355
+ }
3356
+ else if (wordElement) {
3357
+ wordElements = [wordElement];
3358
+ }
3359
+ const allWordCharSpans = wordElements.flatMap(word => Array.from(word.querySelectorAll('span.char')));
3346
3360
  const isGrowable = wordElement?.classList.contains('growable');
3347
3361
  const isCharRise = wordElement?.classList.contains('char-rise');
3348
3362
  const isFirstSyllable = syllable.getAttribute('data-syllable-index') === '0';
3363
+ const syllableStartMs = parseFloat(syllable.getAttribute('data-start-time') || '0');
3364
+ const virtualWordStartMs = parseFloat(wordElement?.dataset.virtualWordStart || '');
3365
+ const isFirstInVirtualWord = isFirstSyllable &&
3366
+ (!Number.isFinite(virtualWordStartMs) ||
3367
+ Math.abs(syllableStartMs - virtualWordStartMs) < 0.5);
3349
3368
  const isFirstInContainer = isFirstSyllable; // Simplified
3350
3369
  const isGap = syllable.closest('.lyrics-gap') !== null;
3351
3370
  // Get duration from data attribute
@@ -3357,7 +3376,7 @@ let AmLyrics$1 = class AmLyrics extends i {
3357
3376
  const charAnimationsMap = new Map();
3358
3377
  const styleUpdates = [];
3359
3378
  // Step 1: Grow Pass
3360
- if (isGrowable && isFirstSyllable && allWordCharSpans.length > 0) {
3379
+ if (isGrowable && isFirstInVirtualWord && allWordCharSpans.length > 0) {
3361
3380
  const finalDuration = wordDurationMs;
3362
3381
  const baseDelayPerChar = finalDuration * 0.09;
3363
3382
  const growDurationMs = finalDuration * 1.5;
@@ -3391,7 +3410,7 @@ let AmLyrics$1 = class AmLyrics extends i {
3391
3410
  });
3392
3411
  });
3393
3412
  }
3394
- if (isCharRise && isFirstSyllable && allWordCharSpans.length > 0) {
3413
+ if (isCharRise && isFirstInVirtualWord && allWordCharSpans.length > 0) {
3395
3414
  const finalDuration = Math.max(wordDurationMs, syllableDurationMs);
3396
3415
  const baseDelayPerChar = finalDuration * 0.09;
3397
3416
  const riseDurationMs = finalDuration * 1.5;
@@ -3423,14 +3442,15 @@ let AmLyrics$1 = class AmLyrics extends i {
3423
3442
  existingAnimation.includes('rise-char'))) {
3424
3443
  animationParts.push(existingAnimation.split(',')[0].trim());
3425
3444
  }
3426
- if (charIndex > 0) {
3445
+ if (charIndex > 0 && wipeDelay > 0 && wipeDuration > 0) {
3427
3446
  const arrivalTime = (span.dataset.preWipeArrival
3428
3447
  ? parseFloat(span.dataset.preWipeArrival)
3429
3448
  : syllableDurationMs * startPct) - elapsedTimeMs;
3430
- const constantDuration = parseFloat(span.dataset.preWipeDuration || '100');
3431
- const animDelay = arrivalTime - constantDuration;
3432
- if (constantDuration > 0) {
3433
- animationParts.push(`pre-wipe-char ${constantDuration}ms linear ${animDelay}ms forwards`);
3449
+ const measuredPreWipeDuration = parseFloat(span.dataset.preWipeDuration || '100');
3450
+ const preWipeDuration = Math.min(measuredPreWipeDuration, wipeDuration * 0.9, syllableDurationMs * 0.08, arrivalTime);
3451
+ const animDelay = arrivalTime - preWipeDuration;
3452
+ if (preWipeDuration >= 16) {
3453
+ animationParts.push(`pre-wipe-char ${preWipeDuration}ms linear ${animDelay}ms none`);
3434
3454
  }
3435
3455
  }
3436
3456
  if (wipeDuration > 0) {
@@ -4008,6 +4028,8 @@ let AmLyrics$1 = class AmLyrics extends i {
4008
4028
  const vwFullText = lineData?.vwFullText ?? [];
4009
4029
  const vwFullDuration = lineData?.vwFullDuration ?? [];
4010
4030
  const vwCharOffset = lineData?.vwCharOffset ?? [];
4031
+ const vwStartMs = lineData?.vwStartMs ?? [];
4032
+ const vwEndMs = lineData?.vwEndMs ?? [];
4011
4033
  const lineIsRTL = lineData?.lineIsRTL ?? false;
4012
4034
  // Create main vocals using YouLyPlus syllable structure
4013
4035
  const mainVocalElement = b `<p
@@ -4027,6 +4049,13 @@ let AmLyrics$1 = class AmLyrics extends i {
4027
4049
  const groupCharOffset = isAnimatedByChar
4028
4050
  ? vwCharOffset[groupIdx]
4029
4051
  : 0;
4052
+ const virtualWordId = isAnimatedByChar
4053
+ ? `${lineIndex}:${vwStartMs[groupIdx]}:${vwEndMs[groupIdx]}`
4054
+ : '';
4055
+ const virtualWordStart = isAnimatedByChar
4056
+ ? vwStartMs[groupIdx]
4057
+ : '';
4058
+ const virtualWordEnd = isAnimatedByChar ? vwEndMs[groupIdx] : '';
4030
4059
  let sylCharAccumulator = 0;
4031
4060
  const groupText = group.map(s => s.text).join('');
4032
4061
  const shouldAllowBreak = groupText.trim().length >= 16 ||
@@ -4043,6 +4072,9 @@ let AmLyrics$1 = class AmLyrics extends i {
4043
4072
  : ''}${isGlowing ? ' glowing' : ''}${shouldAllowBreak
4044
4073
  ? ' allow-break'
4045
4074
  : ''}"
4075
+ data-virtual-word-id="${virtualWordId}"
4076
+ data-virtual-word-start="${virtualWordStart}"
4077
+ data-virtual-word-end="${virtualWordEnd}"
4046
4078
  style="--rise-duration: ${riseDuration}s"
4047
4079
  >${group.map((syllable, sylIdx) => {
4048
4080
  const startTimeMs = syllable.timestamp;
@@ -4601,17 +4633,15 @@ AmLyrics$1.styles = i$3 `
4601
4633
 
4602
4634
  .background-vocal-container {
4603
4635
  max-height: 0;
4604
- overflow: visible;
4636
+ overflow: hidden;
4605
4637
  opacity: 0;
4606
4638
  font-size: var(--lyplus-font-size-subtext);
4607
4639
  line-height: 1.15;
4608
4640
  color: color-mix(in srgb, var(--lyplus-text-secondary) 80%, transparent);
4609
- /* Fast exit (0.25 s) so bg vocals collapse quickly and feel snappy.
4610
- The scroll takes ~0.4 s; finishing the collapse first prevents
4611
- the container from trailing behind the motion. */
4612
4641
  transition:
4613
- max-height 250ms cubic-bezier(0.41, 0, 0.12, 0.99),
4614
- opacity 250ms cubic-bezier(0.41, 0, 0.12, 0.99);
4642
+ max-height var(--scroll-duration, 400ms)
4643
+ cubic-bezier(0.41, 0, 0.12, 0.99),
4644
+ opacity var(--scroll-duration, 400ms) cubic-bezier(0.41, 0, 0.12, 0.99);
4615
4645
  margin: 0;
4616
4646
  pointer-events: none;
4617
4647
  }
@@ -4620,7 +4650,8 @@ AmLyrics$1.styles = i$3 `
4620
4650
  display: block;
4621
4651
  padding-top: 0;
4622
4652
  padding-bottom: 0;
4623
- transition: padding-top 250ms cubic-bezier(0.41, 0, 0.12, 0.99);
4653
+ transition: padding-top var(--scroll-duration, 400ms)
4654
+ cubic-bezier(0.41, 0, 0.12, 0.99);
4624
4655
  }
4625
4656
 
4626
4657
  .lyrics-line.singer-right .background-vocal-container,
@@ -4635,16 +4666,11 @@ AmLyrics$1.styles = i$3 `
4635
4666
  .lyrics-line.bg-expanded .background-vocal-container {
4636
4667
  max-height: 4em;
4637
4668
  opacity: 1;
4638
- /* Slower entry (0.6 s) so bg vocals expand smoothly. */
4639
- transition:
4640
- max-height 0.6s ease,
4641
- opacity 0.6s ease;
4642
4669
  will-change: max-height, opacity;
4643
4670
  }
4644
4671
 
4645
4672
  .lyrics-line.bg-expanded .background-vocal-wrap {
4646
4673
  padding-top: 0.26em;
4647
- transition: padding-top 0.6s ease;
4648
4674
  }
4649
4675
 
4650
4676
  /* --- Line States & Modifiers --- */