aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authors-ol <s+removethis@s-ol.nu>2022-03-21 20:36:45 +0000
committers-ol <s+removethis@s-ol.nu>2022-03-21 20:36:45 +0000
commit8ce1d7ff9d23765c379b9fb8853e0dbf251eb826 (patch)
treebe6da08db4cb732e5ab93645cc63f161de754e57
parentadd README (diff)
downloadisomorphic-kb-explorer-8ce1d7ff9d23765c379b9fb8853e0dbf251eb826.tar.gz
isomorphic-kb-explorer-8ce1d7ff9d23765c379b9fb8853e0dbf251eb826.zip
toolbar, focus, editable size
-rw-r--r--app/app.js167
-rw-r--r--app/style.js19
2 files changed, 134 insertions, 52 deletions
diff --git a/app/app.js b/app/app.js
index 4a00707..98831c8 100644
--- a/app/app.js
+++ b/app/app.js
@@ -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 {