@uimaxbai/am-lyrics 0.4.5 → 0.4.6

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.
@@ -36,6 +36,7 @@ export declare class AmLyrics extends LitElement {
36
36
  private updateActiveLineAndWords;
37
37
  private setupAnimations;
38
38
  private handleLineClick;
39
+ private static getBackgroundTextPlacement;
39
40
  private scrollToActiveLine;
40
41
  private scrollToInstrumental;
41
42
  private animateProgress;
@@ -1 +1 @@
1
- {"version":3,"file":"AmLyrics.d.ts","sourceRoot":"","sources":["../../src/AmLyrics.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,UAAU,EAAE,MAAM,KAAK,CAAC;AA4B5C,qBAAa,QAAS,SAAQ,UAAU;IACtC,MAAM,CAAC,MAAM,0BAmJX;IAGF,KAAK,CAAC,EAAE,MAAM,CAAC;IAGf,OAAO,CAAC,EAAE,MAAM,CAAC;IAGjB,IAAI,CAAC,EAAE,MAAM,CAAC;IAGd,cAAc,SAAU;IAGxB,oBAAoB,SAAa;IAGjC,gBAAgB,UAAS;IAGzB,UAAU,CAAC,EAAE,MAAM,CAAC;IAGpB,UAAU,UAAQ;IAGlB,WAAW,UAAQ;IAGnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAGlB,WAAW,SAAK;IAGhB,OAAO,CAAC,SAAS,CAAS;IAG1B,OAAO,CAAC,MAAM,CAAC,CAAe;IAG9B,OAAO,CAAC,iBAAiB,CAAgB;IAGzC,OAAO,CAAC,qBAAqB,CAAkC;IAG/D,OAAO,CAAC,2BAA2B,CAAkC;IAGrE,OAAO,CAAC,gBAAgB,CAAkC;IAG1D,OAAO,CAAC,sBAAsB,CAAkC;IAEhE,OAAO,CAAC,gBAAgB,CAAC,CAAS;IAElC,OAAO,CAAC,kBAAkB,CAGZ;IAEd,OAAO,CAAC,wBAAwB,CAGlB;IAGd,OAAO,CAAC,eAAe,CAAC,CAAc;IAEtC,OAAO,CAAC,qBAAqB,CAAuB;IAEpD,iBAAiB;IAKjB,oBAAoB;YAON,WAAW;IAqDzB,YAAY;IAIZ,OAAO,CAAC,iBAAiB,EAAE,GAAG,CAAC,MAAM,GAAG,MAAM,GAAG,MAAM,EAAE,OAAO,CAAC;IAmDjE,OAAO,CAAC,MAAM,CAAC,WAAW;IAI1B,OAAO,CAAC,qBAAqB;IAW7B,OAAO,CAAC,qBAAqB;IAiC7B,OAAO,CAAC,sBAAsB;IA8D9B,OAAO,CAAC,wBAAwB;IAwChC,OAAO,CAAC,eAAe;IA4CvB,OAAO,CAAC,eAAe;IAWvB,OAAO,CAAC,kBAAkB;IAyB1B,OAAO,CAAC,oBAAoB;IAmB5B,OAAO,CAAC,eAAe;IA4HvB,MAAM;CA+JP"}
1
+ {"version":3,"file":"AmLyrics.d.ts","sourceRoot":"","sources":["../../src/AmLyrics.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,UAAU,EAAE,MAAM,KAAK,CAAC;AA4B5C,qBAAa,QAAS,SAAQ,UAAU;IACtC,MAAM,CAAC,MAAM,0BA0KX;IAGF,KAAK,CAAC,EAAE,MAAM,CAAC;IAGf,OAAO,CAAC,EAAE,MAAM,CAAC;IAGjB,IAAI,CAAC,EAAE,MAAM,CAAC;IAGd,cAAc,SAAU;IAGxB,oBAAoB,SAAa;IAGjC,gBAAgB,UAAS;IAGzB,UAAU,CAAC,EAAE,MAAM,CAAC;IAGpB,UAAU,UAAQ;IAGlB,WAAW,UAAQ;IAGnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAGlB,WAAW,SAAK;IAGhB,OAAO,CAAC,SAAS,CAAS;IAG1B,OAAO,CAAC,MAAM,CAAC,CAAe;IAG9B,OAAO,CAAC,iBAAiB,CAAgB;IAGzC,OAAO,CAAC,qBAAqB,CAAkC;IAG/D,OAAO,CAAC,2BAA2B,CAAkC;IAGrE,OAAO,CAAC,gBAAgB,CAAkC;IAG1D,OAAO,CAAC,sBAAsB,CAAkC;IAEhE,OAAO,CAAC,gBAAgB,CAAC,CAAS;IAElC,OAAO,CAAC,kBAAkB,CAGZ;IAEd,OAAO,CAAC,wBAAwB,CAGlB;IAGd,OAAO,CAAC,eAAe,CAAC,CAAc;IAEtC,OAAO,CAAC,qBAAqB,CAAuB;IAEpD,iBAAiB;IAKjB,oBAAoB;YAON,WAAW;IAqDzB,YAAY;IAIZ,OAAO,CAAC,iBAAiB,EAAE,GAAG,CAAC,MAAM,GAAG,MAAM,GAAG,MAAM,EAAE,OAAO,CAAC;IAmDjE,OAAO,CAAC,MAAM,CAAC,WAAW;IAI1B,OAAO,CAAC,qBAAqB;IAW7B,OAAO,CAAC,qBAAqB;IAiC7B,OAAO,CAAC,sBAAsB;IA8D9B,OAAO,CAAC,wBAAwB;IAwChC,OAAO,CAAC,eAAe;IA4CvB,OAAO,CAAC,eAAe;IAWvB,OAAO,CAAC,MAAM,CAAC,0BAA0B;IAYzC,OAAO,CAAC,kBAAkB;IAmC1B,OAAO,CAAC,oBAAoB;IA8B5B,OAAO,CAAC,eAAe;IA4HvB,MAAM;CAyKP"}
@@ -78,7 +78,7 @@ const e$1=(e,t,c)=>(c.configurable=true,c.enumerable=true,Reflect.decorate&&"obj
78
78
  * SPDX-License-Identifier: BSD-3-Clause
79
79
  */function e(e,r){return (n,s,i)=>{const o=t=>t.renderRoot?.querySelector(e)??null;return e$1(n,s,{get(){return o(this)}})}}
80
80
 
81
- const VERSION = '0.4.5';
81
+ const VERSION = '0.4.6';
82
82
  const INSTRUMENTAL_THRESHOLD_MS = 3000; // Show ellipsis for gaps >= 3s
83
83
  class AmLyrics extends i {
84
84
  constructor() {
@@ -376,6 +376,15 @@ class AmLyrics extends i {
376
376
  });
377
377
  this.dispatchEvent(event);
378
378
  }
379
+ static getBackgroundTextPlacement(line) {
380
+ if (!line.backgroundText || line.backgroundText.length === 0 || line.text.length === 0) {
381
+ return 'after'; // Default to after if no comparison is possible
382
+ }
383
+ // Compare the start times of the first syllables
384
+ const mainTextStartTime = line.text[0].timestamp;
385
+ const backgroundTextStartTime = line.backgroundText[0].timestamp;
386
+ return backgroundTextStartTime < mainTextStartTime ? 'before' : 'after';
387
+ }
379
388
  scrollToActiveLine() {
380
389
  if (!this.lyricsContainer || this.activeLineIndices.length === 0) {
381
390
  return;
@@ -387,7 +396,15 @@ class AmLyrics extends i {
387
396
  const containerHeight = this.lyricsContainer.clientHeight;
388
397
  const lineTop = activeLineElement.offsetTop;
389
398
  const lineHeight = activeLineElement.clientHeight;
390
- const top = lineTop - containerHeight / 2 + lineHeight / 2;
399
+ // Check if the line has background text placed before the main text
400
+ const hasBackgroundBefore = activeLineElement.querySelector('.background-text.before');
401
+ // Calculate the offset to center the main text content, accounting for background text placement
402
+ let offsetAdjustment = 0;
403
+ if (hasBackgroundBefore) {
404
+ const backgroundElement = hasBackgroundBefore;
405
+ offsetAdjustment = backgroundElement.clientHeight / 2; // Adjust to focus on main content
406
+ }
407
+ const top = lineTop - containerHeight / 2 + lineHeight / 2 - offsetAdjustment;
391
408
  // Use requestAnimationFrame for smoother iOS performance
392
409
  requestAnimationFrame(() => {
393
410
  this.lyricsContainer?.scrollTo({ top, behavior: 'smooth' });
@@ -402,7 +419,15 @@ class AmLyrics extends i {
402
419
  const containerHeight = this.lyricsContainer.clientHeight;
403
420
  const lineTop = target.offsetTop;
404
421
  const lineHeight = target.clientHeight;
405
- const top = lineTop - containerHeight / 2 + lineHeight / 2;
422
+ // Check if the target line has background text placed before the main text
423
+ const hasBackgroundBefore = target.querySelector('.background-text.before');
424
+ // Calculate the offset to center the main text content, accounting for background text placement
425
+ let offsetAdjustment = 0;
426
+ if (hasBackgroundBefore) {
427
+ const backgroundElement = hasBackgroundBefore;
428
+ offsetAdjustment = backgroundElement.clientHeight / 2; // Adjust to focus on main content
429
+ }
430
+ const top = lineTop - containerHeight / 2 + lineHeight / 2 - offsetAdjustment;
406
431
  // Use requestAnimationFrame for smoother iOS performance
407
432
  requestAnimationFrame(() => {
408
433
  this.lyricsContainer?.scrollTo({ top, behavior: 'smooth' });
@@ -537,6 +562,74 @@ class AmLyrics extends i {
537
562
  ? line.backgroundText.some(syl => this.currentTime >= syl.timestamp &&
538
563
  this.currentTime <= syl.endtime)
539
564
  : false;
565
+ const backgroundPlacement = AmLyrics.getBackgroundTextPlacement(line);
566
+ const shouldShowBackground = line.backgroundText &&
567
+ line.backgroundText.length > 0 &&
568
+ (isLineActive || bgIsPlayingNow);
569
+ // Create background text element
570
+ const backgroundTextElement = shouldShowBackground
571
+ ? x `<span class="background-text ${backgroundPlacement}">
572
+ ${line.backgroundText.map((syllable, wordIndex) => {
573
+ const activeBackgroundWordIndex = this.activeBackgroundWordIndices.get(lineIndex) ?? -1;
574
+ const isWordActive = isLineActive && wordIndex === activeBackgroundWordIndex;
575
+ const isWordPassed = isLineActive &&
576
+ (wordIndex < activeBackgroundWordIndex ||
577
+ (activeBackgroundWordIndex === -1 &&
578
+ this.currentTime > syllable.endtime));
579
+ let progress = 0;
580
+ if (isWordActive) {
581
+ progress = this.interpolate
582
+ ? (this.backgroundWordProgress.get(lineIndex) ?? 0)
583
+ : 1;
584
+ }
585
+ else if (isWordPassed) {
586
+ progress = 1;
587
+ }
588
+ return x `<span
589
+ class="progress-text"
590
+ style="--line-progress: ${progress *
591
+ 100}%; margin-right: ${syllable.part
592
+ ? '0'
593
+ : '.5ch'}; --transition-style: ${isLineActive
594
+ ? 'all'
595
+ : 'color'}"
596
+ data-text="${syllable.text}"
597
+ >${syllable.text}</span
598
+ >`;
599
+ })}
600
+ </span>`
601
+ : '';
602
+ // Create main text element
603
+ const mainTextElement = x `<span>
604
+ ${line.text.map((syllable, wordIndex) => {
605
+ const activeMainWordIndex = this.activeMainWordIndices.get(lineIndex) ?? -1;
606
+ const isWordActive = isLineActive && wordIndex === activeMainWordIndex;
607
+ const isWordPassed = isLineActive &&
608
+ (wordIndex < activeMainWordIndex ||
609
+ (activeMainWordIndex === -1 &&
610
+ this.currentTime > syllable.endtime));
611
+ let progress = 0;
612
+ if (isWordActive) {
613
+ progress = this.interpolate
614
+ ? (this.mainWordProgress.get(lineIndex) ?? 0)
615
+ : 1;
616
+ }
617
+ else if (isWordPassed) {
618
+ progress = 1;
619
+ }
620
+ return x `<span
621
+ class="progress-text"
622
+ style="--line-progress: ${progress *
623
+ 100}%; margin-right: ${syllable.part
624
+ ? '0'
625
+ : '.5ch'}; --transition-style: ${isLineActive
626
+ ? 'all'
627
+ : 'color'}"
628
+ data-text="${syllable.text}${syllable.part ? ' ' : ''}"
629
+ >${syllable.text}</span
630
+ >`;
631
+ })}
632
+ </span>`;
540
633
  let maybeInstrumentalBlock = null;
541
634
  if (instrumental && instrumental.insertBeforeIndex === lineIndex) {
542
635
  const remainingSeconds = Math.max(0, Math.ceil((instrumental.gapEnd - this.currentTime) / 1000));
@@ -563,70 +656,9 @@ class AmLyrics extends i {
563
656
  }
564
657
  }}
565
658
  >
566
- <span>
567
- ${line.text.map((syllable, wordIndex) => {
568
- const activeMainWordIndex = this.activeMainWordIndices.get(lineIndex) ?? -1;
569
- const isWordActive = isLineActive && wordIndex === activeMainWordIndex;
570
- const isWordPassed = isLineActive &&
571
- (wordIndex < activeMainWordIndex ||
572
- (activeMainWordIndex === -1 &&
573
- this.currentTime > syllable.endtime));
574
- let progress = 0;
575
- if (isWordActive) {
576
- progress = this.interpolate
577
- ? (this.mainWordProgress.get(lineIndex) ?? 0)
578
- : 1;
579
- }
580
- else if (isWordPassed) {
581
- progress = 1;
582
- }
583
- return x `<span
584
- class="progress-text"
585
- style="--line-progress: ${progress *
586
- 100}%; margin-right: ${syllable.part
587
- ? '0'
588
- : '.5ch'}; --transition-style: ${isLineActive
589
- ? 'all'
590
- : 'color'}"
591
- data-text="${syllable.text}${syllable.part ? ' ' : ''}"
592
- >${syllable.text}</span
593
- >`;
594
- })}
595
- </span>
596
- ${line.backgroundText &&
597
- line.backgroundText.length > 0 &&
598
- (isLineActive || bgIsPlayingNow)
599
- ? x `<span class="background-text">
600
- ${line.backgroundText.map((syllable, wordIndex) => {
601
- const activeBackgroundWordIndex = this.activeBackgroundWordIndices.get(lineIndex) ?? -1;
602
- const isWordActive = isLineActive && wordIndex === activeBackgroundWordIndex;
603
- const isWordPassed = isLineActive &&
604
- (wordIndex < activeBackgroundWordIndex ||
605
- (activeBackgroundWordIndex === -1 &&
606
- this.currentTime > syllable.endtime));
607
- let progress = 0;
608
- if (isWordActive) {
609
- progress = this.interpolate
610
- ? (this.backgroundWordProgress.get(lineIndex) ?? 0)
611
- : 1;
612
- }
613
- else if (isWordPassed) {
614
- progress = 1;
615
- }
616
- return x `<span
617
- class="progress-text"
618
- style="--line-progress: ${progress *
619
- 100}%; margin-right: ${syllable.part
620
- ? '0'
621
- : '.5ch'}; --transition-style: ${isLineActive
622
- ? 'all'
623
- : 'color'}"
624
- data-text="${syllable.text}"
625
- >${syllable.text}</span
626
- >`;
627
- })}
628
- </span>`
629
- : ''}
659
+ ${backgroundPlacement === 'before' ? backgroundTextElement : ''}
660
+ ${mainTextElement}
661
+ ${backgroundPlacement === 'after' ? backgroundTextElement : ''}
630
662
  </div>
631
663
  `;
632
664
  });
@@ -659,6 +691,8 @@ AmLyrics.styles = i$3 `
659
691
  -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu,
660
692
  Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
661
693
  background: transparent;
694
+ height: 100%;
695
+ overflow: hidden; /* Ensure the host doesn't show scrollbars */
662
696
  }
663
697
 
664
698
  .lyrics-container {
@@ -667,9 +701,11 @@ AmLyrics.styles = i$3 `
667
701
  background-color: transparent;
668
702
  width: 100%;
669
703
  height: 100%;
704
+ max-height: 100vh; /* Ensure it doesn't exceed viewport height */
670
705
  overflow-y: auto;
671
706
  scroll-behavior: smooth;
672
707
  -webkit-overflow-scrolling: touch; /* iOS smooth scrolling */
708
+ box-sizing: border-box; /* Include padding in height calculation */
673
709
  }
674
710
 
675
711
  .lyrics-line {
@@ -684,6 +720,12 @@ AmLyrics.styles = i$3 `
684
720
  color: #888; /* Default text color to gray */
685
721
  word-wrap: break-word;
686
722
  overflow-wrap: break-word;
723
+ display: flex;
724
+ flex-direction: column; /* Allow reordering of main and background text */
725
+ }
726
+
727
+ .lyrics-line > span {
728
+ flex-shrink: 0; /* Prevent the main text span from shrinking */
687
729
  }
688
730
 
689
731
  .lyrics-line:hover {
@@ -705,6 +747,7 @@ AmLyrics.styles = i$3 `
705
747
  .progress-text {
706
748
  position: relative;
707
749
  display: inline-block;
750
+ overflow: hidden; /* Hide any overflow from the pseudo-element */
708
751
  }
709
752
 
710
753
  .progress-text::before {
@@ -718,6 +761,7 @@ AmLyrics.styles = i$3 `
718
761
  var(--highlight-color, #000)
719
762
  ); /* CSS variable takes precedence */
720
763
  overflow: hidden;
764
+ white-space: nowrap; /* Prevent text wrapping in the pseudo-element */
721
765
  /* Spring animation */
722
766
  /* transition: width 0.05s ; */
723
767
  word-wrap: break-word;
@@ -741,7 +785,18 @@ AmLyrics.styles = i$3 `
741
785
  color: rgba(136, 136, 136, 0.8);
742
786
  font-size: 0.8em; /* a bit smaller than main line */
743
787
  font-style: normal; /* no italics */
744
- margin: 4px 0 0 0; /* place just below the main line */
788
+ margin: 4px 0; /* default margin for positioning */
789
+ flex-shrink: 0; /* Prevent shrinking */
790
+ }
791
+
792
+ .background-text.before {
793
+ order: -1; /* Place before main text when background starts earlier */
794
+ margin: 0 0 4px 0; /* place above the main line */
795
+ }
796
+
797
+ .background-text.after {
798
+ order: 1; /* Place after main text when background starts later */
799
+ margin: 4px 0 0 0; /* place below the main line */
745
800
  }
746
801
  .progress-text:last-child {
747
802
  margin-right: 0 !important; /* Remove margin for the last word */