import h, { classNames } from 'lib/h' import * as time from 'lib/time' import * as soundsLib from 'sounds' const MIN_BPM: number = 1 const MAX_BPM: number = 1000 interface Params { onNextStep: (sounds: soundsLib.Sounds) => void, onStop: () => void } export function view({ onNextStep, onStop }: Params) { let bpm = 60 let isPlaying = false let lastBeat: undefined | number = undefined return h('div', {}, h('button', { className: 'g-PlayStop', onclick: async (e: Event) => { const target = e.target as HTMLButtonElement isPlaying = !isPlaying target.innerText = isPlaying ? '■' : '▶' let sounds = await soundsLib.load() let step = (timestamp: number) => { if (lastBeat === undefined || timestamp - lastBeat > 1000 * 60 / bpm) { lastBeat = timestamp onNextStep(sounds) } if (isPlaying) window.requestAnimationFrame(step) } if (isPlaying) { window.requestAnimationFrame(step) } else { onStop() } } }, '▶' ) , h('label', { className: 'g-Bpm' }, 'BPM', h('input', { className: 'g-Input', type: 'number', value: bpm, min: MIN_BPM, max: MAX_BPM, oninput: time.debounce( (e: Event) => { const target = e.target as HTMLInputElement const n = parseInt(target.value) if (n >= MIN_BPM && n <= MAX_BPM) { bpm = n } }, 1000 ) } ) ) ) }