aboutsummaryrefslogtreecommitdiff
path: root/src/view
diff options
context:
space:
mode:
Diffstat (limited to 'src/view')
-rw-r--r--src/view/sequencer.ts75
-rw-r--r--src/view/sequencer/block.ts9
2 files changed, 63 insertions, 21 deletions
diff --git a/src/view/sequencer.ts b/src/view/sequencer.ts
index 3bca278..74eb0ea 100644
--- a/src/view/sequencer.ts
+++ b/src/view/sequencer.ts
@@ -1,18 +1,33 @@
import h, { classNames } from 'lib/h'
import * as soundsLib from 'sounds'
+import { Sound } from 'sounds'
import * as play from 'view/sequencer/play'
import * as addRemoveBeat from 'view/sequencer/addRemoveBeat'
import * as block from 'view/sequencer/block'
export function view() {
let index = -1
- let blocks = [true]
+ let blocks = [{
+ [Sound.Bass]: true,
+ [Sound.Snare]: false,
+ [Sound.HitHatClosed]: false,
+ }]
let blocksNode = h('div',
{ className: 'g-Sequencer__Blocks' },
- block.view({
- checked: true,
- onCheck: checked => blocks[0] = checked
- })
+ block.column([
+ {
+ checked: false,
+ onCheck: checked => blocks[0][Sound.HitHatClosed] = checked
+ },
+ {
+ checked: false,
+ onCheck: checked => blocks[0][Sound.Snare] = checked
+ },
+ {
+ checked: true,
+ onCheck: checked => blocks[0][Sound.Bass] = checked
+ }
+ ])
)
let onNextStep = (sounds: soundsLib.Sounds) => {
@@ -24,9 +39,17 @@ export function view() {
if (oldBlock !== undefined) oldBlock.classList.remove('g-Sequencer__Block--Beat')
let newBlock = blocksNode.childNodes[newIndex] as HTMLElement
+
+ // Trigger reflow between removing and adding the classname.
+ // Allow to re-trigger the animation if there is only one column.
+ // See https://css-tricks.com/restart-css-animation/
+ void newBlock.offsetWidth
+
newBlock.classList.add('g-Sequencer__Block--Beat')
- if (blocks[newIndex]) soundsLib.playKick(sounds)
+ soundsLib.all().forEach(sound => {
+ if (blocks[newIndex][sound]) soundsLib.play(sounds, sound)
+ })
}
let sequencer = h('div', { className: 'g-Sequencer' },
@@ -46,25 +69,26 @@ export function view() {
blocks.pop()
},
onAdd: index => {
- blocks.push(false)
- blocksNode.appendChild(block.view({
- checked: false,
- onCheck: checked => blocks[index] = checked
- }))
+ blocks.push({
+ [Sound.Bass]: false,
+ [Sound.Snare]: false,
+ [Sound.HitHatClosed]: false,
+ })
+ blocksNode.appendChild(block.column(
+ soundsLib.all().map(sound => ({
+ checked: false,
+ onCheck: checked => blocks[index][sound] = checked
+ }))
+ ))
}
}),
h('div',
{ className: 'g-Sequencer__Grid' },
h('ol',
- { className: 'g-Sequencer__Sounds' },
- h('li',
- { onclick: async () => {
- let sounds = await soundsLib.load()
- soundsLib.playKick(sounds)
- }
- },
- 'Bass'
- )
+ { className: 'g-Sequencer__Column' },
+ soundItem('Hit-hat (closed)', Sound.HitHatClosed),
+ soundItem('Snare', Sound.Snare),
+ soundItem('Bass', Sound.Bass)
),
blocksNode
)
@@ -72,3 +96,14 @@ export function view() {
return sequencer
}
+
+function soundItem(name: string, sound: Sound): Element {
+ return h('li',
+ { onclick: async () => {
+ let sounds = await soundsLib.load()
+ soundsLib.play(sounds, sound)
+ }
+ },
+ name
+ )
+}
diff --git a/src/view/sequencer/block.ts b/src/view/sequencer/block.ts
index 5776120..ff8d2db 100644
--- a/src/view/sequencer/block.ts
+++ b/src/view/sequencer/block.ts
@@ -5,7 +5,14 @@ interface Params {
onCheck: (checked: boolean) => void
}
-export function view({ checked, onCheck }: Params) {
+export function column(xs: Array<Params>) {
+ return h('ol',
+ { className: 'g-Sequencer__Column' },
+ ...xs.map(params => h('li', {}, block(params)))
+ )
+}
+
+function block({ checked, onCheck }: Params) {
return h('div',
{ className: classNames({
'g-Sequencer__Block': true,