diff options
| author | s-ol <s+removethis@s-ol.nu> | 2022-03-21 20:36:45 +0000 |
|---|---|---|
| committer | s-ol <s+removethis@s-ol.nu> | 2022-03-21 20:36:45 +0000 |
| commit | 8ce1d7ff9d23765c379b9fb8853e0dbf251eb826 (patch) | |
| tree | be6da08db4cb732e5ab93645cc63f161de754e57 | |
| parent | add README (diff) | |
| download | isomorphic-kb-explorer-8ce1d7ff9d23765c379b9fb8853e0dbf251eb826.tar.gz isomorphic-kb-explorer-8ce1d7ff9d23765c379b9fb8853e0dbf251eb826.zip | |
toolbar, focus, editable size
| -rw-r--r-- | app/app.js | 167 | ||||
| -rw-r--r-- | app/style.js | 19 |
2 files changed, 134 insertions, 52 deletions
@@ -1,5 +1,5 @@ import React from 'react'; -import { pos, width, height } from './style'; +import { css, pos, width, height } from './style'; import * as notes from './notes'; const statbyte = (stat, chan) => (stat << 4) | chan; @@ -156,22 +156,78 @@ const ChordView = ({ chord }) => { ); }; +css(` +nav { + display: flex; + flex-wrap: wrap; + justfiy-content: space-between; +} + +nav > .group, nav > .spacer { + display: flex; + align-items: baseline; + padding: 0.25em 1em; + gap: 1em; + + border: 0 solid #363636; + border-width: 1px 0 1px 0; +} + +nav > .group:nth-child(2n) { + background: #363636; +} + +nav > .spacer { flex: 1; } +`); + +css(` +main { + position: relative; + padding: 0.5em; + margin: 1em 0; + + display: flex; + justify-content: space-evenly; +} + +main .focus-msg { + position: absolute; + inset: 0; + + display: flex; + font-size: 5em; + justify-content: space-around; + align-items: center; + text-align: center; + + border: 4px solid white; + background: #212121; + pointer-events: none; + + opacity: 0.8; + transition: opacity 0.4s; +} + +main:focus-within .focus-msg { + opacity: 0; +} +`); + export default class App extends React.Component { state = { layout: 'wicki_hayden', scale: 'major', offset: 60, state: {}, + w: 12, + h: 4, }; - componentDidMount() { - document.addEventListener("keydown", this.onkeydown); - document.addEventListener("keyup", this.onkeyup); - } + ref = React.createRef(); - componentWillUnmount() { - document.removeEventListener("keydown", this.onkeydown); - document.removeEventListener("keyup", this.onkeyup); + componentDidMount() { + this.ref.current.addEventListener("keydown", this.onkeydown); + this.ref.current.addEventListener("keyup", this.onkeyup); } componentDidUpdate(prevProps) { @@ -214,10 +270,15 @@ export default class App extends React.Component { this.send(NOTE_OFF, note); } - onlayout = (e) => this.setState({ layout: e.target.value }) - onscale = (e) => this.setState({ scale: e.target.value }) + set(key) { + return (e) => { + let value = e.target.value; + if (key === 'w' || key === 'h') value = +value; + this.setState({ [key]: value }); + }; + } - onoffset = (e) => this.setState({ offset: null }); + onoffset = (offset) => (e) => this.setState({ offset }); onmessage = (e) => { const message = parse(e); @@ -259,41 +320,60 @@ export default class App extends React.Component { render() { const { configure, showMidi } = this.props; - const { scale, offset, layout, state } = this.state; + const { w, h, scale, offset, layout, state } = this.state; const chord = Object.entries(state).filter(([note, on]) => on).map(([k, _]) => k); chord.sort(); return ( <div className="app"> - <button onClick={configure}>midi settings</button> - <div className="option"> - <label>layout:</label> - <select name="layout" onChange={this.onlayout} value={layout}> - <option value="wicki_hayden">Wicki-Hayden</option> - <option value="harmonic">Harmonic Table</option> - <option value="gerhard">Gerhard</option> - </select> - </div> - <div className="option"> - <label>scale:</label> - <select name="layout" onChange={this.onscale} value={scale}> - <option value="none">None</option> - <option value="major">Major</option> - <option value="minor_nat">Natural Minor</option> - <option value="minor_harm">Harmonic Minor</option> - <option value="minor_mel">Melodic Minor</option> - <option value="minor_hung">Hungarian Minor</option> - <option value="whole">Whole-Tone</option> - <option value="penta">Pentatonic</option> - </select> - <button onClick={this.onoffset}>set offset</button> - </div> - - <div className="main"> + <nav> + <div className="group"> + <button onClick={configure}>midi settings</button> + </div> + <div className="group"> + <label>layout:</label> + <select name="layout" value={layout} onChange={this.set('layout')}> + <option value="wicki_hayden">Wicki-Hayden</option> + <option value="harmonic">Harmonic Table</option> + <option value="gerhard">Gerhard</option> + </select> + </div> + <div className="group"> + <label>scale:</label> + <button onClick={this.onoffset(null)}> + {notes.music[offset % 12]} + </button> + <select name="layout" value={scale} onChange={this.set('scale')}> + <option value="none">None</option> + <option value="major">Major</option> + <option value="minor_nat">Natural Minor</option> + <option value="minor_harm">Harmonic Minor</option> + <option value="minor_mel">Melodic Minor</option> + <option value="minor_hung">Hungarian Minor</option> + <option value="whole">Whole-Tone</option> + <option value="penta">Pentatonic</option> + </select> + </div> + <div className="group"> + <label>octave:</label> + <button onClick={this.onoffset(offset - 12)}>-</button> + {Math.floor(offset / 12)} + <button onClick={this.onoffset(offset + 12)}>+</button> + </div> + <div className="group"> + <label>size:</label> + <input className="small" type="number" min="1" value={w} onChange={this.set('w')} /> + {'x'} + <input className="small" type="number" min="1" value={h} onChange={this.set('h')} /> + </div> + <div className="spacer" /> + </nav> + + <main ref={this.ref} tabIndex="0"> <Keyboard - w={12} - h={4} + w={w} + h={h} noteon={this.noteon} noteoff={this.noteoff} showMidi={showMidi} @@ -302,10 +382,11 @@ export default class App extends React.Component { offset={offset} state={state} /> - <ChordView - chord={chord} - /> - </div> + <ChordView chord={chord} /> + <div className="focus-msg"> + <span>click here to activate<br/>keyboard input</span> + </div> + </main> </div> ); } diff --git a/app/style.js b/app/style.js index 0897b16..5e84f5c 100644 --- a/app/style.js +++ b/app/style.js @@ -57,23 +57,24 @@ button, input, select { border: 1px solid #eeeeee; color: #eeeeee; padding: 0.25em; - margin: 0.125em 0; border-radius: 0.5em; } -.app, .keyboard, .chord { - position: relative; +input.small { + width: 4em; } -.main { - display: flex; - justify-content: space-evenly; +button { + padding: 0.25em 0.5em; } -.option label { +label { display: inline-block; - width: 4em; - margin-right: 1em; + font-weight: bold; +} + +.app, .keyboard, .chord { + position: relative; } .hexagon { |
