text rendering component
This commit is contained in:
@@ -0,0 +1,12 @@
|
||||
<div [class.chords]="chordMode!=='hide'" class="song-text">
|
||||
|
||||
<div (click)="onChordClick()" class="menu">
|
||||
<fa-icon [icon]="faLines"></fa-icon>
|
||||
</div>
|
||||
|
||||
<div *ngFor="let section of sections" [class.chorus]="section.type===1" class="section">
|
||||
<div *ngFor="let line of getLines(section)" [class.chord]="line.type===0" class="line">
|
||||
{{line.text}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,48 @@
|
||||
.song-text {
|
||||
white-space: pre-wrap;
|
||||
position: relative;
|
||||
|
||||
&.chords {
|
||||
font-family: 'Ubuntu Mono', monospace;
|
||||
}
|
||||
|
||||
&:hover .menu {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.menu {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
background: #eee;
|
||||
border-radius: 8px;
|
||||
padding: 5px;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
transition: 300ms all ease-in-out;
|
||||
cursor: pointer;
|
||||
opacity: 0;
|
||||
|
||||
&:hover {
|
||||
background: #ddd;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
.section {
|
||||
margin-bottom: 20px;
|
||||
border-left: 3px solid #ddd;
|
||||
}
|
||||
|
||||
.chorus {
|
||||
margin-left: 20px;
|
||||
border-left: none;
|
||||
}
|
||||
|
||||
.chord {
|
||||
font-weight: bold;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
import {async, ComponentFixture, TestBed} from '@angular/core/testing';
|
||||
|
||||
import {SongTextComponent} from './song-text.component';
|
||||
|
||||
describe('SongTextComponent', () => {
|
||||
let component: SongTextComponent;
|
||||
let fixture: ComponentFixture<SongTextComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [SongTextComponent]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(SongTextComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,67 @@
|
||||
import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
|
||||
import {
|
||||
Line,
|
||||
LineType,
|
||||
Section,
|
||||
SectionType,
|
||||
TextRenderingService
|
||||
} from '../../../modules/songs/services/text-rendering.service';
|
||||
import {faGripLines} from '@fortawesome/free-solid-svg-icons/faGripLines';
|
||||
|
||||
export type ChordMode = 'show' | 'hide' | 'onlyFirst'
|
||||
|
||||
@Component({
|
||||
selector: 'app-song-text',
|
||||
templateUrl: './song-text.component.html',
|
||||
styleUrls: ['./song-text.component.less']
|
||||
})
|
||||
export class SongTextComponent implements OnInit {
|
||||
public sections: Section[];
|
||||
public chordMode: ChordMode = 'hide';
|
||||
@Output() public chordModeChanged = new EventEmitter<ChordMode>();
|
||||
public faLines = faGripLines;
|
||||
|
||||
constructor(private textRenderingService: TextRenderingService) {
|
||||
}
|
||||
|
||||
@Input()
|
||||
public set text(value: string) {
|
||||
this.sections = this.textRenderingService.parse(value).sort((a, b) => a.type - b.type);
|
||||
console.log(this.sections)
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
}
|
||||
|
||||
public getLines(section: Section): Line[] {
|
||||
return section.lines.filter(_ => {
|
||||
if (_.type !== LineType.chord) return true;
|
||||
|
||||
switch (this.chordMode) {
|
||||
case 'show':
|
||||
return true;
|
||||
case 'hide':
|
||||
return false;
|
||||
case 'onlyFirst':
|
||||
return section.number === 0 || section.type !== SectionType.Verse;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public onChordClick(): void {
|
||||
const next = this.getNextChordMode();
|
||||
this.chordMode = next;
|
||||
this.chordModeChanged.next(next);
|
||||
}
|
||||
|
||||
private getNextChordMode(): ChordMode {
|
||||
switch (this.chordMode) {
|
||||
case 'show':
|
||||
return 'hide';
|
||||
case 'hide':
|
||||
return 'onlyFirst';
|
||||
case 'onlyFirst':
|
||||
return 'show';
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import {NgModule} from '@angular/core';
|
||||
import {CommonModule} from '@angular/common';
|
||||
import {SongTextComponent} from './song-text.component';
|
||||
import {FontAwesomeModule} from '@fortawesome/angular-fontawesome';
|
||||
|
||||
|
||||
@NgModule({
|
||||
declarations: [SongTextComponent],
|
||||
exports: [SongTextComponent],
|
||||
imports: [
|
||||
CommonModule,
|
||||
FontAwesomeModule
|
||||
]
|
||||
})
|
||||
export class SongTextModule {
|
||||
}
|
||||
Reference in New Issue
Block a user