diff options
author | Joris | 2023-02-19 14:39:02 +0100 |
---|---|---|
committer | Joris | 2023-02-19 14:39:02 +0100 |
commit | e0699eed72c5682bd2395ba4299ff69933c83d48 (patch) | |
tree | b5601a32492b70ec9458738a64bac6d6e15802cc /src/view/form.ts | |
parent | bb058d35c7110dcffe31b4e7afabbe26673a43a8 (diff) |
Diffstat (limited to 'src/view/form.ts')
-rw-r--r-- | src/view/form.ts | 191 |
1 files changed, 140 insertions, 51 deletions
diff --git a/src/view/form.ts b/src/view/form.ts index 5547e0c..e499b05 100644 --- a/src/view/form.ts +++ b/src/view/form.ts @@ -1,5 +1,6 @@ -import { h, withVar, Html, Rx } from 'lib/rx' +import { h, withState, Html, Rx, pure, RxAble } from 'lib/rx' import * as Options from 'view/options' +import * as Chord from 'chord' interface Params { options: Options.Model @@ -7,7 +8,7 @@ interface Params { } export function view({ options, onSubmit }: Params): Html { - return withVar(options, (opts, updateOptions) => + return withState(options, opts => h('form', { className: 'g-Form', onsubmit: opts.map(o => @@ -17,58 +18,71 @@ export function view({ options, onSubmit }: Params): Html { } ) }, - chordCheckbox({ - label: '', - checked: opts.map(o => o.major), - onCheck: (checked => updateOptions(o => { - o.major = checked - return o - })) - }), - chordCheckbox({ - label: '-', - checked: opts.map(o => o.minor), - onCheck: (checked => updateOptions(o => { - o.minor = checked - return o - })) - }), - chordCheckbox({ - label: '7', - checked: opts.map(o => o.seventh), - onCheck: (checked => updateOptions(o => { - o.seventh = checked - return o - })) - }), - chordCheckbox({ - label: '-7', - checked: opts.map(o => o.minorSeventh), - onCheck: (checked => updateOptions(o => { - o.minorSeventh = checked - return o - })) - }), - chordCheckbox({ - label: '7', - checked: opts.map(o => o.majorSeventh), - onCheck: (checked => updateOptions(o => { - o.majorSeventh = checked - return o - })) - }), - numberInput({ - label: 'BPM', + h('table', + { className: 'g-ChordsTable' }, + chordsGroup({ + title: 'Major', + chords: opts.map(o => o.major), + updateChords: (chords: Chord.Chords) => { + opts.update(o => { + o.major = chords + return o + }) + } + }), + chordsGroup({ + title: 'Minor', + chords: opts.map(o => o.minor), + updateChords: (chords: Chord.Chords) => { + opts.update(o => { + o.minor = chords + return o + }) + } + }), + chordsGroup({ + title: '7th', + chords: opts.map(o => o.seventh), + updateChords: (chords: Chord.Chords) => { + opts.update(o => { + o.seventh = chords + return o + }) + } + }), + chordsGroup({ + title: 'Minor 7th', + chords: opts.map(o => o.minorSeventh), + updateChords: (chords: Chord.Chords) => { + opts.update(o => { + o.minorSeventh = chords + return o + }) + } + }), + chordsGroup({ + title: 'Major 7th', + chords: opts.map(o => o.majorSeventh), + updateChords: (chords: Chord.Chords) => { + opts.update(o => { + o.majorSeventh = chords + return o + }) + } + }) + ), + numberInput({ + label: 'BPM', value: opts.map(o => o.bpm.toString()), - onChange: (n => updateOptions(o => { + onChange: (n => opts.update(o => { o.bpm = n return o })) }), - numberInput({ - label: 'Beats per Chord', + numberInput({ + label: 'Beats per Chord', value: opts.map(o => o.beatsPerChord.toString()), - onChange: (n => updateOptions(o => { + onChange: (n => opts.update(o => { o.beatsPerChord = n return o })) @@ -78,10 +92,85 @@ export function view({ options, onSubmit }: Params): Html { ) } +interface ChordsGroupParams { + title: string, + chords: Rx<Chord.Chords>, + updateChords: (chords: Chord.Chords) => void +} + +function chordsGroup({ title, chords, updateChords }: ChordsGroupParams): Html { + const line = + (lineChords: Array<Chord.Chord>, label: (chord: Chord.Chord) => string) => + h('div', + { className: 'g-ChordsLine' }, + chordCheckbox({ + checked: chords.map(cs => lineChords.every(c => cs.has(c))), + onCheck: chords.map(cs => + (checked: boolean) => { + if (checked) { + lineChords.forEach(c => cs.add(c)) + } else { + lineChords.forEach(c => cs.delete(c)) + } + updateChords(cs) + } + ) + }), + lineChords.map(chord => + chordCheckbox({ + label: label(chord), + checked: chords.map(cs => cs.has(chord)), + onCheck: chords.map(cs => + (checked: boolean) => { + if (checked) { + cs.add(chord) + } else { + cs.delete(chord) + } + updateChords(cs) + } + ) + }) + ) + ) + + return h('tr', + h('td', + chordCheckbox({ + label: title, + checked: chords.map(cs => + Chord.sharps.every(c => cs.has(c)) + && Chord.plains.every(c => cs.has(c)) + && Chord.bemols.every(c => cs.has(c)) + ), + onCheck: chords.map(cs => + (checked: boolean) => { + if (checked) { + Chord.sharps.forEach(c => cs.add(c)) + Chord.plains.forEach(c => cs.add(c)) + Chord.bemols.forEach(c => cs.add(c)) + } else { + Chord.sharps.forEach(c => cs.delete(c)) + Chord.plains.forEach(c => cs.delete(c)) + Chord.bemols.forEach(c => cs.delete(c)) + } + updateChords(cs) + } + ) + }) + ), + h('td', + line(Chord.sharps, () => '♯'), + line(Chord.plains, chord => chord), + line(Chord.bemols, () => '♭') + ) + ) +} + interface ChordCheckboxParams { - label: string + label?: string checked: Rx<boolean> - onCheck: (checked: boolean) => void + onCheck: Rx<(checked: boolean) => void> } function chordCheckbox({ label, checked, onCheck }: ChordCheckboxParams): Html { @@ -90,7 +179,7 @@ function chordCheckbox({ label, checked, onCheck }: ChordCheckboxParams): Html { h('input', { type: 'checkbox', checked, - onchange: (event: Event) => onCheck((event.target as HTMLInputElement).checked) + onchange: onCheck.map(f => (event: Event) => f((event.target as HTMLInputElement).checked)) } ), label |