char-slop/chordpad.vibed.software
git clone https://git.t4t.associates/char-slop/chordpad.vibed.software
040fec5
main
1import { readSection } from "../import/hookpad.ts" ; 2import type { TheoryTab } from "../import/theorytab.ts" ; 3 4const SCALE_NAMES :Record < string , string > = { harmonicMinor :"harmonic minor" }; 5const pretty = ( symbol :string ) => 6symbol 7. replace ( / ([A-G])b / g , "$1♭" ) 8. replace ( / b(?=\d) / g , "♭" ) 9. replaceAll ( "#" , "♯" ); 10 11/** ask which sections of a TheoryTab to import: resolves to them, or null if cancelled */ 12export function chooseSections ( tab :TheoryTab ) :Promise < TheoryTab [ "sections" ] | null > { 13return new Promise ( resolve => { 14const done = ( choice :TheoryTab [ "sections" ] | null ) => { 15dialog . close (); 16dialog . remove (); 17resolve ( choice ); 18}; 19 20const option = ( 21label :string , 22detail :string , 23preview :string , 24sections :TheoryTab [ "sections" ], 25) => ( 26< button type = "button" class = "tt-option" _onclick = {() => done ( sections )}> 27< b >{ label }</ b > 28< span class = "tt-detail" >{ detail}< / span> 29< span class = "tt-preview" >{ preview }< /span> 30</ button > 31); 32 33const read = tab . sections . map ( s => ({ ... s , read : readSection ( s . song ) })); 34const bars = ( r : ( typeof read )[ number ][ "read" ]) => Math . ceil ( r . length / r . beatsPerBar ); 35const filled = read . filter ( s => s . read . chords . length || s . read . notes . length ); 36 37const dialog = ( 38< dialog class = "dialog tt-dialog" _oncancel = {() => done ( null )}> 39< h2 >{ tab . title }</ h2 > 40< div class = "tt-options" > 41{ option ( 42"all sections" , 43` ${ filled . reduce (( n , s ) => n + bars ( s . read ), 0 )} bars` , 44"" , 45tab . sections , 46)} 47{ filled . map ( s => 48option ( 49s . name , 50` ${ s . read . key . tonic } ${ SCALE_NAMES [ s . read . key . scale ] ?? s . read . key . scale } · ${ bars ( s . read )} bars` , 51s . read . chords 52. slice ( 0 , 8 ) 53. map ( c => ( c . symbol ? pretty ( c . symbol ) : "…" )) 54. join ( " " ), 55[ s ], 56), 57)} 58< / div> 59< div class = "dialog-actions" > 60< button type = "button" _onclick = {() => done ( null )}> 61cancel 62</ button > 63< /div> 64</ dialog > 65) as HTMLDialogElement ; 66 67document . body . append ( dialog ); 68dialog . showModal (); 69}); 70}