remove old styles and begin phase out old elements
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
module.exports = {
|
||||
style: {
|
||||
postcss: {
|
||||
plugins: [require('tailwindcss'), require('autoprefixer')],
|
||||
},
|
||||
},
|
||||
};
|
||||
Generated
+581
-204
File diff suppressed because it is too large
Load Diff
+11
-5
@@ -3,7 +3,9 @@
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@reduxjs/toolkit": "^1.4.0",
|
||||
"@craco/craco": "^6.1.1",
|
||||
"@reduxjs/toolkit": "^1.5.1",
|
||||
"@tailwindcss/forms": "^0.3.2",
|
||||
"@testing-library/jest-dom": "^4.2.4",
|
||||
"@testing-library/react": "^9.5.0",
|
||||
"@testing-library/user-event": "^7.2.1",
|
||||
@@ -20,9 +22,9 @@
|
||||
"styled-components": "^5.2.1"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "react-scripts start",
|
||||
"build": "react-scripts build",
|
||||
"test": "react-scripts test",
|
||||
"start": "craco start",
|
||||
"build": "craco build",
|
||||
"test": "craco test",
|
||||
"eject": "react-scripts eject"
|
||||
},
|
||||
"eslintConfig": {
|
||||
@@ -41,6 +43,10 @@
|
||||
]
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-plugin-styled-components": "^1.11.1"
|
||||
"@tailwindcss/postcss7-compat": "^2.0.4",
|
||||
"autoprefixer": "^9.8.6",
|
||||
"babel-plugin-styled-components": "^1.11.1",
|
||||
"postcss": "^7.0.35",
|
||||
"tailwindcss": "npm:@tailwindcss/postcss7-compat@^2.0.4"
|
||||
}
|
||||
}
|
||||
|
||||
-44
@@ -1,44 +0,0 @@
|
||||
.App {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.App-logo {
|
||||
height: 40vmin;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
.App-logo {
|
||||
animation: App-logo-float infinite 3s ease-in-out;
|
||||
}
|
||||
}
|
||||
|
||||
.App-header {
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: calc(10px + 2vmin);
|
||||
}
|
||||
|
||||
.App-link {
|
||||
color: rgb(112, 76, 182);
|
||||
}
|
||||
.App-spacer {
|
||||
min-height: 100vh;
|
||||
min-width: 15vw;
|
||||
border-right: 1px solid black;
|
||||
}
|
||||
|
||||
@keyframes App-logo-float {
|
||||
0% {
|
||||
transform: translateY(0);
|
||||
}
|
||||
50% {
|
||||
transform: translateY(10px);
|
||||
}
|
||||
100% {
|
||||
transform: translateY(0px);
|
||||
}
|
||||
}
|
||||
+3
-8
@@ -1,17 +1,12 @@
|
||||
import React from 'react';
|
||||
import Menu from './features/menu';
|
||||
import TimbreSwitcher from './features/timbre/timbreSwitcher';
|
||||
import './App.css';
|
||||
|
||||
function App() {
|
||||
return (
|
||||
<div className='App'>
|
||||
<header className='App-header'>
|
||||
<div className='App-spacer'>
|
||||
<Menu />
|
||||
</div>
|
||||
<TimbreSwitcher />
|
||||
</header>
|
||||
<div className='grid grid-cols-6 grid-rows-1 gap-4 h-screen'>
|
||||
<Menu className='col-span-1' />
|
||||
<TimbreSwitcher className='col-span-5' />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { useRef, useState, useEffect } from 'react';
|
||||
import './menu.css';
|
||||
import { SelectList } from '../helpers/Helpers';
|
||||
import { Select } from '../utils/components';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import {
|
||||
parameterUpdateIndex,
|
||||
@@ -31,10 +30,11 @@ export default function Menu() {
|
||||
}, [file, dispatch]);
|
||||
|
||||
return (
|
||||
<div className='menu'>
|
||||
<div className='flex flex-col justify-around border-solid border-r-2 border-gray-400 px-4'>
|
||||
<div className='menu-patch-container'>
|
||||
<div className='patch-name'>
|
||||
<input
|
||||
className='block w-full rounded-md bg-gray-100 border-transparent hover:bg-gray-200 focus:bg-white focus:ring-1'
|
||||
placeholder='Patch Name'
|
||||
type='text'
|
||||
maxLength='12'
|
||||
@@ -49,32 +49,32 @@ export default function Menu() {
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div className='patch-load'>
|
||||
<div className='my-1 flex flex-col items-center'>
|
||||
<button
|
||||
className='menu-button'
|
||||
className='mx-4 my-1 bg-gray-100 rounded-md w-32 h-10 border-transparent hover:bg-gray-200'
|
||||
onClick={() => {
|
||||
dispatch(parameterRefreshAll());
|
||||
}}>
|
||||
New Patch
|
||||
</button>
|
||||
<button
|
||||
className='menu-button'
|
||||
className='mx-4 my-1 bg-gray-100 rounded-md w-32 h-10 border-transparent hover:bg-gray-200'
|
||||
onClick={() => {
|
||||
fileRef.current.click();
|
||||
}}>
|
||||
Load Patch
|
||||
</button>
|
||||
<button
|
||||
className='menu-button'
|
||||
className='mx-4 my-1 bg-gray-100 rounded-md w-32 h-10 border-transparent hover:bg-gray-200'
|
||||
onClick={() => {
|
||||
return_file_from_store(state);
|
||||
}}>
|
||||
Save Patch
|
||||
</button>
|
||||
<input
|
||||
className='hidden'
|
||||
type='file'
|
||||
accept='.syx'
|
||||
className='menu-file-input'
|
||||
ref={fileRef}
|
||||
onChange={(e) => {
|
||||
loadFile(e.target.files[0]);
|
||||
@@ -82,7 +82,8 @@ export default function Menu() {
|
||||
/>
|
||||
</div>
|
||||
<div className='patch-settings'>
|
||||
<SelectList
|
||||
<Select
|
||||
className=''
|
||||
value={state.patch.mode}
|
||||
list={[
|
||||
{ value: 'Single' },
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
.menu {
|
||||
height: 100vh;
|
||||
min-width: 15vw;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-wrap: nowrap;
|
||||
justify-content: space-around;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.menu-patch-container > * {
|
||||
margin-top: 10pt;
|
||||
}
|
||||
|
||||
input[type='text'] {
|
||||
font-family: 'Roboto', sans-serif;
|
||||
text-indent: 8pt;
|
||||
width: 70%;
|
||||
padding: 6pt 0;
|
||||
outline: none;
|
||||
border-radius: 4pt;
|
||||
border: 1px solid gainsboro;
|
||||
}
|
||||
input[type='text']:hover {
|
||||
border-color: silver;
|
||||
}
|
||||
input[type='text']:focus {
|
||||
border: 2px solid dodgerblue;
|
||||
}
|
||||
|
||||
.menu-button {
|
||||
width: 65%;
|
||||
display: block;
|
||||
padding: 4pt;
|
||||
margin: 8px auto;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
h2 {
|
||||
text-align: left;
|
||||
font-size: x-large;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.menu-file-input {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.patch-settings {
|
||||
font-size: small;
|
||||
width: 75%;
|
||||
margin: 10pt auto;
|
||||
line-height: 1.5em;
|
||||
}
|
||||
@@ -2,12 +2,11 @@ import React from 'react';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { selectById } from './timbreSlice.js';
|
||||
import { ArpeggA, ArpeggB } from './parameters/Arpeggios';
|
||||
import styles from './Timbre.module.css';
|
||||
|
||||
export default function Arpeggio(props) {
|
||||
const ids = useSelector((state) => selectById(state, props.id));
|
||||
return (
|
||||
<div className={styles.timbreStyle}>
|
||||
<div>
|
||||
<ArpeggA id={ids.arpeggA} />
|
||||
<ArpeggB id={ids.arpeggB} />
|
||||
</div>
|
||||
|
||||
@@ -2,12 +2,11 @@ import React from 'react';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { ModFX, Delay, EQ } from './parameters/ModFX';
|
||||
import { selectById } from './timbreSlice.js';
|
||||
import styles from './Timbre.module.css';
|
||||
|
||||
export default function Effects(props) {
|
||||
const ids = useSelector((state) => selectById(state, props.id));
|
||||
return (
|
||||
<div className={styles.timbreStyle}>
|
||||
<div>
|
||||
<ModFX id={ids.modfx} />
|
||||
<Delay id={ids.delay} />
|
||||
<EQ id={ids.eq} />
|
||||
|
||||
@@ -9,12 +9,11 @@ import Amp from './parameters/Amp';
|
||||
import LFO from './parameters/LFO';
|
||||
import Patches from './parameters/Patches';
|
||||
import { selectById } from './timbreSlice.js';
|
||||
import styles from './Timbre.module.css';
|
||||
|
||||
export default function Timbre(props) {
|
||||
const ids = useSelector((state) => selectById(state, props.id));
|
||||
return (
|
||||
<div className={styles.timbreStyle}>
|
||||
<div>
|
||||
<VCO
|
||||
name='VCO 1'
|
||||
id={ids.vco1}
|
||||
@@ -118,7 +117,7 @@ export default function Timbre(props) {
|
||||
<Amp name='Amp' id={ids.amp} />
|
||||
<EG name='EG 1' id={ids.eg1} />
|
||||
<EG name='EG 2' id={ids.eg2} />
|
||||
<div className={styles.lineBreak} />
|
||||
<div />
|
||||
<LFO
|
||||
name='LFO 1'
|
||||
id={ids.lfo1}
|
||||
|
||||
@@ -1,130 +0,0 @@
|
||||
.timbreStyle {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.lineBreak {
|
||||
width: 0%;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 1920px) {
|
||||
.lineBreak {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 1440px) {
|
||||
.lineBreak {
|
||||
width: 0%;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 990px) {
|
||||
.lineBreak {
|
||||
width: 0%;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 920px) {
|
||||
.lineBreak {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.buttonContainer {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 25%;
|
||||
}
|
||||
|
||||
.buttonContainer > button:hover {
|
||||
background: white;
|
||||
color: slateblue;
|
||||
border: 2px solid slateblue;
|
||||
}
|
||||
.buttonContainer > button:focus {
|
||||
background: slateblue;
|
||||
color: white;
|
||||
border: 2px solid slateblue;
|
||||
}
|
||||
|
||||
.tabs {
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.tabList {
|
||||
border-bottom: 1px solid black;
|
||||
display: none;
|
||||
flex-direction: row;
|
||||
list-style-type: none;
|
||||
justify-content: center;
|
||||
top: 0;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
width: 85vw;
|
||||
background: white;
|
||||
}
|
||||
.tab {
|
||||
height: 1.25em;
|
||||
width: 4em;
|
||||
background: white;
|
||||
color: slategrey;
|
||||
font-size: 0.75em;
|
||||
margin: 0.75em 1em;
|
||||
padding: 0.25em 1em;
|
||||
border: 2px solid slategrey;
|
||||
border-radius: 3px;
|
||||
outline: none;
|
||||
-webkit-touch-callout: none; /* iOS Safari */
|
||||
-webkit-user-select: none; /* Safari */
|
||||
-khtml-user-select: none; /* Konqueror HTML */
|
||||
-moz-user-select: none; /* Old versions of Firefox */
|
||||
-ms-user-select: none; /* Internet Explorer/Edge */
|
||||
user-select: none;
|
||||
transition: all 0.2s ease-in-out;
|
||||
}
|
||||
|
||||
.tab:hover {
|
||||
background: white;
|
||||
color: slateblue;
|
||||
border: 2px solid slateblue;
|
||||
}
|
||||
.selected,
|
||||
.selected:hover {
|
||||
background: slateblue;
|
||||
color: white;
|
||||
border: 2px solid slateblue;
|
||||
transition: 0.2s ease-in-out;
|
||||
}
|
||||
@keyframes slideeffect {
|
||||
0% {
|
||||
opacity: 0.5;
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
.tabPanel {
|
||||
padding: 1em 0;
|
||||
height: 100%;
|
||||
animation: slideeffect 0.6s ease-in-out;
|
||||
opacity: 1;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
.tabPanel::-webkit-scrollbar {
|
||||
width: 0.3em;
|
||||
}
|
||||
|
||||
.tabPanel::-webkit-scrollbar-track,
|
||||
.tabPanel::-webkit-scrollbar-thumb {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.tabPanel:hover::-webkit-scrollbar-thumb {
|
||||
background-color: lightgray;
|
||||
border-radius: 6px;
|
||||
}
|
||||
@@ -10,105 +10,104 @@ import { VocoderFilter, FCMod } from './parameters/Filter';
|
||||
import { VocoderAmp } from './parameters/Amp';
|
||||
import Levels from './parameters/Levels';
|
||||
import Pans from './parameters/Pans';
|
||||
import styles from './Timbre.module.css';
|
||||
|
||||
export default function Vocoder(props) {
|
||||
const ids = useSelector((state) => selectById(state, props.id));
|
||||
return (
|
||||
<div className={styles.timbreStyle}>
|
||||
<VCO
|
||||
name="VCO"
|
||||
id={ids.vco}
|
||||
waveforms={[
|
||||
{ value: 'Saw' },
|
||||
{ value: 'Square' },
|
||||
{ value: 'Triangle' },
|
||||
{ value: 'Sine' },
|
||||
{ value: 'Vox Wave' },
|
||||
{ value: 'DWGS' },
|
||||
{ value: 'Noise' },
|
||||
{ value: 'Audio In' },
|
||||
]}
|
||||
dwgsOrModTypeName="DWGS"
|
||||
dwgsOrModType={[
|
||||
{ value: 'SynSine1' },
|
||||
{ value: 'SynSine2' },
|
||||
{ value: 'SynSine3' },
|
||||
{ value: 'SynSine4' },
|
||||
{ value: 'SynSine5' },
|
||||
{ value: 'SynSine6' },
|
||||
{ value: 'SynSine7' },
|
||||
{ value: 'SynBass1' },
|
||||
{ value: 'SynBass2' },
|
||||
{ value: 'SynBass3' },
|
||||
{ value: 'SynBass4' },
|
||||
{ value: 'SynBass5' },
|
||||
{ value: 'SynBass6' },
|
||||
{ value: 'SynBass7' },
|
||||
{ value: 'SynWave1' },
|
||||
{ value: 'SynWave2' },
|
||||
{ value: 'SynWave3' },
|
||||
{ value: 'SynWave4' },
|
||||
{ value: 'SynWave5' },
|
||||
{ value: 'SynWave6' },
|
||||
{ value: 'SynWave7' },
|
||||
{ value: 'SynWave8' },
|
||||
{ value: 'SynWave9' },
|
||||
{ value: '5thWave1' },
|
||||
{ value: '5thWave2' },
|
||||
{ value: '5thWave3' },
|
||||
{ value: 'Digi1' },
|
||||
{ value: 'Digi2' },
|
||||
{ value: 'Digi3' },
|
||||
{ value: 'Digi4' },
|
||||
{ value: 'Digi5' },
|
||||
{ value: 'Digi6' },
|
||||
{ value: 'Digi7' },
|
||||
{ value: 'Digi8' },
|
||||
{ value: 'Endless' },
|
||||
{ value: 'E.Piano1' },
|
||||
{ value: 'E.Piano2' },
|
||||
{ value: 'E.Piano3' },
|
||||
{ value: 'E.Piano4' },
|
||||
{ value: 'Organ1' },
|
||||
{ value: 'Organ2' },
|
||||
{ value: 'Organ3' },
|
||||
{ value: 'Organ4' },
|
||||
{ value: 'Organ5' },
|
||||
{ value: 'Organ6' },
|
||||
{ value: 'Organ7' },
|
||||
{ value: 'Clav1' },
|
||||
{ value: 'Clav2' },
|
||||
{ value: 'Guitar1' },
|
||||
{ value: 'Guitar2' },
|
||||
{ value: 'Guitar3' },
|
||||
{ value: 'Bass1' },
|
||||
{ value: 'Bass2' },
|
||||
{ value: 'Bass3' },
|
||||
{ value: 'Bass4' },
|
||||
{ value: 'Bass5' },
|
||||
{ value: 'Bell1' },
|
||||
{ value: 'Bell2' },
|
||||
{ value: 'Bell3' },
|
||||
{ value: 'Bell4' },
|
||||
{ value: 'Voice1' },
|
||||
{ value: 'Voice2' },
|
||||
{ value: 'Voice3' },
|
||||
{ value: 'Voice4' },
|
||||
]}
|
||||
/>
|
||||
<AudioIn name="Audio In" id={ids.audioIn} />
|
||||
<Mixer name="Mixer" id={ids.mixer} />
|
||||
<Pitch name="Pitch" id={ids.pitch} />
|
||||
<VocoderFilter name="Filter" id={ids.filter} />
|
||||
<FCMod name="FC Mod" id={ids.fcMod} />
|
||||
<VocoderAmp name="Amp" id={ids.amp} />
|
||||
<EG name="EG" id={ids.eg} />
|
||||
<div className={styles.lineBreak} />
|
||||
<LFO name="LFO 1" id={ids.lfo1} />
|
||||
<LFO name="LFO 2" id={ids.lfo2} />
|
||||
<Levels name="Levels" id={ids.levels} />
|
||||
<Pans name="Pans" id={ids.pans} />
|
||||
</div>
|
||||
);
|
||||
const ids = useSelector((state) => selectById(state, props.id));
|
||||
return (
|
||||
<div>
|
||||
<VCO
|
||||
name='VCO'
|
||||
id={ids.vco}
|
||||
waveforms={[
|
||||
{ value: 'Saw' },
|
||||
{ value: 'Square' },
|
||||
{ value: 'Triangle' },
|
||||
{ value: 'Sine' },
|
||||
{ value: 'Vox Wave' },
|
||||
{ value: 'DWGS' },
|
||||
{ value: 'Noise' },
|
||||
{ value: 'Audio In' },
|
||||
]}
|
||||
dwgsOrModTypeName='DWGS'
|
||||
dwgsOrModType={[
|
||||
{ value: 'SynSine1' },
|
||||
{ value: 'SynSine2' },
|
||||
{ value: 'SynSine3' },
|
||||
{ value: 'SynSine4' },
|
||||
{ value: 'SynSine5' },
|
||||
{ value: 'SynSine6' },
|
||||
{ value: 'SynSine7' },
|
||||
{ value: 'SynBass1' },
|
||||
{ value: 'SynBass2' },
|
||||
{ value: 'SynBass3' },
|
||||
{ value: 'SynBass4' },
|
||||
{ value: 'SynBass5' },
|
||||
{ value: 'SynBass6' },
|
||||
{ value: 'SynBass7' },
|
||||
{ value: 'SynWave1' },
|
||||
{ value: 'SynWave2' },
|
||||
{ value: 'SynWave3' },
|
||||
{ value: 'SynWave4' },
|
||||
{ value: 'SynWave5' },
|
||||
{ value: 'SynWave6' },
|
||||
{ value: 'SynWave7' },
|
||||
{ value: 'SynWave8' },
|
||||
{ value: 'SynWave9' },
|
||||
{ value: '5thWave1' },
|
||||
{ value: '5thWave2' },
|
||||
{ value: '5thWave3' },
|
||||
{ value: 'Digi1' },
|
||||
{ value: 'Digi2' },
|
||||
{ value: 'Digi3' },
|
||||
{ value: 'Digi4' },
|
||||
{ value: 'Digi5' },
|
||||
{ value: 'Digi6' },
|
||||
{ value: 'Digi7' },
|
||||
{ value: 'Digi8' },
|
||||
{ value: 'Endless' },
|
||||
{ value: 'E.Piano1' },
|
||||
{ value: 'E.Piano2' },
|
||||
{ value: 'E.Piano3' },
|
||||
{ value: 'E.Piano4' },
|
||||
{ value: 'Organ1' },
|
||||
{ value: 'Organ2' },
|
||||
{ value: 'Organ3' },
|
||||
{ value: 'Organ4' },
|
||||
{ value: 'Organ5' },
|
||||
{ value: 'Organ6' },
|
||||
{ value: 'Organ7' },
|
||||
{ value: 'Clav1' },
|
||||
{ value: 'Clav2' },
|
||||
{ value: 'Guitar1' },
|
||||
{ value: 'Guitar2' },
|
||||
{ value: 'Guitar3' },
|
||||
{ value: 'Bass1' },
|
||||
{ value: 'Bass2' },
|
||||
{ value: 'Bass3' },
|
||||
{ value: 'Bass4' },
|
||||
{ value: 'Bass5' },
|
||||
{ value: 'Bell1' },
|
||||
{ value: 'Bell2' },
|
||||
{ value: 'Bell3' },
|
||||
{ value: 'Bell4' },
|
||||
{ value: 'Voice1' },
|
||||
{ value: 'Voice2' },
|
||||
{ value: 'Voice3' },
|
||||
{ value: 'Voice4' },
|
||||
]}
|
||||
/>
|
||||
<AudioIn name='Audio In' id={ids.audioIn} />
|
||||
<Mixer name='Mixer' id={ids.mixer} />
|
||||
<Pitch name='Pitch' id={ids.pitch} />
|
||||
<VocoderFilter name='Filter' id={ids.filter} />
|
||||
<FCMod name='FC Mod' id={ids.fcMod} />
|
||||
<VocoderAmp name='Amp' id={ids.amp} />
|
||||
<EG name='EG' id={ids.eg} />
|
||||
<div />
|
||||
<LFO name='LFO 1' id={ids.lfo1} />
|
||||
<LFO name='LFO 2' id={ids.lfo2} />
|
||||
<Levels name='Levels' id={ids.levels} />
|
||||
<Pans name='Pans' id={ids.pans} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2,134 +2,133 @@ import React from 'react';
|
||||
import { useSelector, useDispatch } from 'react-redux';
|
||||
import { selectById, parameterUpdated } from './parameterSlice.js';
|
||||
import { Slider, Checkbox } from '../../helpers/Helpers';
|
||||
import styles from './Parameters.module.css';
|
||||
|
||||
export default function Amp(props) {
|
||||
const parameters = useSelector((state) => selectById(state, props.id));
|
||||
const dispatch = useDispatch();
|
||||
const parameters = useSelector((state) => selectById(state, props.id));
|
||||
const dispatch = useDispatch();
|
||||
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
<span className={styles.header}>{`${props.name}`}</span>
|
||||
Amp Level
|
||||
<Slider
|
||||
parameter={parameters.ampLevel}
|
||||
min={0}
|
||||
max={127}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { ampLevel: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
PanPot
|
||||
<Slider
|
||||
parameter={parameters.panpot}
|
||||
min={-63}
|
||||
max={63}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { panpot: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
Amp Keyboard Tracking
|
||||
<Slider
|
||||
parameter={parameters.ampTrack}
|
||||
min={-63}
|
||||
max={63}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { ampTrack: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
<Checkbox
|
||||
name="Distortion"
|
||||
parameter={parameters.distortion}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { distortion: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
return (
|
||||
<div>
|
||||
<span>{`${props.name}`}</span>
|
||||
Amp Level
|
||||
<Slider
|
||||
parameter={parameters.ampLevel}
|
||||
min={0}
|
||||
max={127}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { ampLevel: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
PanPot
|
||||
<Slider
|
||||
parameter={parameters.panpot}
|
||||
min={-63}
|
||||
max={63}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { panpot: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
Amp Keyboard Tracking
|
||||
<Slider
|
||||
parameter={parameters.ampTrack}
|
||||
min={-63}
|
||||
max={63}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { ampTrack: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
<Checkbox
|
||||
name='Distortion'
|
||||
parameter={parameters.distortion}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { distortion: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export const VocoderAmp = (props) => {
|
||||
const parameters = useSelector((state) => selectById(state, props.id));
|
||||
const dispatch = useDispatch();
|
||||
const parameters = useSelector((state) => selectById(state, props.id));
|
||||
const dispatch = useDispatch();
|
||||
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
<span className={styles.header}>{`${props.name}`}</span>
|
||||
Amp Level
|
||||
<Slider
|
||||
parameter={parameters.ampLevel}
|
||||
min={0}
|
||||
max={127}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { ampLevel: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
Direct Level
|
||||
<Slider
|
||||
parameter={parameters.directLevel}
|
||||
min={0}
|
||||
max={127}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { directLevel: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
Amp Keyboard Tracking
|
||||
<Slider
|
||||
parameter={parameters.ampTrack}
|
||||
min={-63}
|
||||
max={63}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { ampTrack: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
<Checkbox
|
||||
name="Distortion"
|
||||
parameter={parameters.distortion}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { distortion: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
return (
|
||||
<div>
|
||||
<span>{`${props.name}`}</span>
|
||||
Amp Level
|
||||
<Slider
|
||||
parameter={parameters.ampLevel}
|
||||
min={0}
|
||||
max={127}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { ampLevel: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
Direct Level
|
||||
<Slider
|
||||
parameter={parameters.directLevel}
|
||||
min={0}
|
||||
max={127}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { directLevel: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
Amp Keyboard Tracking
|
||||
<Slider
|
||||
parameter={parameters.ampTrack}
|
||||
min={-63}
|
||||
max={63}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { ampTrack: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
<Checkbox
|
||||
name='Distortion'
|
||||
parameter={parameters.distortion}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { distortion: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -2,16 +2,15 @@ import React from 'react';
|
||||
import { useSelector, useDispatch } from 'react-redux';
|
||||
import { selectById, parameterUpdated } from './parameterSlice.js';
|
||||
import { Slider, SelectList, Checkbox } from '../../helpers/Helpers';
|
||||
import styles from './Parameters.module.css';
|
||||
|
||||
const ArpeggA = (props) => {
|
||||
const parameters = useSelector((state) => selectById(state, props.id));
|
||||
const dispatch = useDispatch();
|
||||
|
||||
return (
|
||||
<div className={styles.horizontalContainer}>
|
||||
<span className={styles.header}>Arpeggio A.</span>
|
||||
<div className={styles.container}>
|
||||
<div>
|
||||
<span>Arpeggio A.</span>
|
||||
<div>
|
||||
Tempo
|
||||
<Slider
|
||||
min={20}
|
||||
@@ -61,8 +60,8 @@ const ArpeggA = (props) => {
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<div className={styles.divider} />
|
||||
<div className={styles.container}>
|
||||
<div />
|
||||
<div>
|
||||
Type
|
||||
<SelectList
|
||||
value={parameters.type}
|
||||
@@ -107,11 +106,11 @@ const ArpeggB = (props) => {
|
||||
const dispatch = useDispatch();
|
||||
|
||||
return (
|
||||
<div className={styles.horizontalContainer}>
|
||||
<span className={styles.header}>Arpeggio B.</span>
|
||||
<div className={styles.container}>
|
||||
<div>
|
||||
<span>Arpeggio B.</span>
|
||||
<div>
|
||||
<Checkbox
|
||||
name="Latch"
|
||||
name='Latch'
|
||||
parameter={parameters.latch}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
@@ -137,7 +136,7 @@ const ArpeggB = (props) => {
|
||||
}
|
||||
/>
|
||||
<Checkbox
|
||||
name="Key Sync"
|
||||
name='Key Sync'
|
||||
parameter={parameters.keySync}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
@@ -149,8 +148,8 @@ const ArpeggB = (props) => {
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<div className={styles.divider} />
|
||||
<div className={styles.container}>
|
||||
<div />
|
||||
<div>
|
||||
Last Step
|
||||
<SelectList
|
||||
labelFunction={(v) => `Step ${v.value}`}
|
||||
|
||||
@@ -2,83 +2,82 @@ import React from 'react';
|
||||
import { useSelector, useDispatch } from 'react-redux';
|
||||
import { selectById, parameterUpdated } from './parameterSlice.js';
|
||||
import { Slider, Checkbox } from '../../helpers/Helpers';
|
||||
import styles from './Parameters.module.css';
|
||||
|
||||
export default function EG(props) {
|
||||
const parameters = useSelector((state) => selectById(state, props.id));
|
||||
const dispatch = useDispatch();
|
||||
const parameters = useSelector((state) => selectById(state, props.id));
|
||||
const dispatch = useDispatch();
|
||||
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
<span className={styles.header}>{`${props.name}`}</span>
|
||||
Attack
|
||||
<Slider
|
||||
parameter={parameters.attack}
|
||||
min={0}
|
||||
max={127}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { attack: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
Decay
|
||||
<Slider
|
||||
parameter={parameters.decay}
|
||||
min={0}
|
||||
max={127}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { decay: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
Sustain
|
||||
<Slider
|
||||
parameter={parameters.sustain}
|
||||
min={0}
|
||||
max={127}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { sustain: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
Release
|
||||
<Slider
|
||||
parameter={parameters.release}
|
||||
min={0}
|
||||
max={127}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { release: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
<Checkbox
|
||||
name="EG Reset"
|
||||
parameter={parameters.egReset}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { egReset: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
return (
|
||||
<div>
|
||||
<span>{`${props.name}`}</span>
|
||||
Attack
|
||||
<Slider
|
||||
parameter={parameters.attack}
|
||||
min={0}
|
||||
max={127}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { attack: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
Decay
|
||||
<Slider
|
||||
parameter={parameters.decay}
|
||||
min={0}
|
||||
max={127}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { decay: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
Sustain
|
||||
<Slider
|
||||
parameter={parameters.sustain}
|
||||
min={0}
|
||||
max={127}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { sustain: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
Release
|
||||
<Slider
|
||||
parameter={parameters.release}
|
||||
min={0}
|
||||
max={127}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { release: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
<Checkbox
|
||||
name='EG Reset'
|
||||
parameter={parameters.egReset}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { egReset: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2,186 +2,185 @@ import React from 'react';
|
||||
import { useSelector, useDispatch } from 'react-redux';
|
||||
import { selectById, parameterUpdated } from './parameterSlice.js';
|
||||
import { Slider, SelectList } from '../../helpers/Helpers';
|
||||
import styles from './Parameters.module.css';
|
||||
|
||||
export default function Filter(props) {
|
||||
const parameters = useSelector((state) => selectById(state, props.id));
|
||||
const dispatch = useDispatch();
|
||||
const parameters = useSelector((state) => selectById(state, props.id));
|
||||
const dispatch = useDispatch();
|
||||
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
<span className={styles.header}>{`${props.name}`}</span>
|
||||
Filter Type
|
||||
<SelectList
|
||||
value={parameters.filterType}
|
||||
list={[
|
||||
{ value: '-24db Low Pass' },
|
||||
{ value: '-12db Low Pass' },
|
||||
{ value: 'Band Pass' },
|
||||
{ value: 'High Pass' },
|
||||
]}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { filterType: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
Cutoff
|
||||
<Slider
|
||||
parameter={parameters.cutoff}
|
||||
min={0}
|
||||
max={127}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { cutoff: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
Resonance
|
||||
<Slider
|
||||
parameter={parameters.resonance}
|
||||
min={0}
|
||||
max={127}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { resonance: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
EG Intensity
|
||||
<Slider
|
||||
parameter={parameters.egIntensity}
|
||||
min={-63}
|
||||
max={63}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { egIntensity: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
Keyboard Tracking
|
||||
<Slider
|
||||
parameter={parameters.keyboardTrack}
|
||||
min={-63}
|
||||
max={63}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { keyboardTrack: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
return (
|
||||
<div>
|
||||
<span>{`${props.name}`}</span>
|
||||
Filter Type
|
||||
<SelectList
|
||||
value={parameters.filterType}
|
||||
list={[
|
||||
{ value: '-24db Low Pass' },
|
||||
{ value: '-12db Low Pass' },
|
||||
{ value: 'Band Pass' },
|
||||
{ value: 'High Pass' },
|
||||
]}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { filterType: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
Cutoff
|
||||
<Slider
|
||||
parameter={parameters.cutoff}
|
||||
min={0}
|
||||
max={127}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { cutoff: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
Resonance
|
||||
<Slider
|
||||
parameter={parameters.resonance}
|
||||
min={0}
|
||||
max={127}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { resonance: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
EG Intensity
|
||||
<Slider
|
||||
parameter={parameters.egIntensity}
|
||||
min={-63}
|
||||
max={63}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { egIntensity: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
Keyboard Tracking
|
||||
<Slider
|
||||
parameter={parameters.keyboardTrack}
|
||||
min={-63}
|
||||
max={63}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { keyboardTrack: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export const VocoderFilter = (props) => {
|
||||
const parameters = useSelector((state) => selectById(state, props.id));
|
||||
const dispatch = useDispatch();
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
<span className={styles.header}>{`${props.name}`}</span>
|
||||
Cutoff
|
||||
<Slider
|
||||
parameter={parameters.cutoff}
|
||||
min={0}
|
||||
max={127}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { cutoff: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
Resonance
|
||||
<Slider
|
||||
parameter={parameters.resonance}
|
||||
min={0}
|
||||
max={127}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { resonance: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
EF Sense
|
||||
<Slider
|
||||
parameter={parameters.efSense}
|
||||
min={0}
|
||||
max={127}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { efSense: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
const parameters = useSelector((state) => selectById(state, props.id));
|
||||
const dispatch = useDispatch();
|
||||
return (
|
||||
<div>
|
||||
<span>{`${props.name}`}</span>
|
||||
Cutoff
|
||||
<Slider
|
||||
parameter={parameters.cutoff}
|
||||
min={0}
|
||||
max={127}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { cutoff: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
Resonance
|
||||
<Slider
|
||||
parameter={parameters.resonance}
|
||||
min={0}
|
||||
max={127}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { resonance: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
EF Sense
|
||||
<Slider
|
||||
parameter={parameters.efSense}
|
||||
min={0}
|
||||
max={127}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { efSense: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const FCMod = (props) => {
|
||||
const parameters = useSelector((state) => selectById(state, props.id));
|
||||
const dispatch = useDispatch();
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
<span className={styles.header}>{`${props.name}`}</span>
|
||||
Source
|
||||
<SelectList
|
||||
value={parameters.source}
|
||||
list={[
|
||||
{ value: 'Amp EG' },
|
||||
{ value: 'LFO 1' },
|
||||
{ value: 'LFO 2' },
|
||||
{ value: 'Velocity' },
|
||||
{ value: 'Keyboard Track' },
|
||||
{ value: 'Pitch Bend' },
|
||||
{ value: 'Mod Wheel' },
|
||||
]}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { source: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
Intensity
|
||||
<Slider
|
||||
parameter={parameters.intensity}
|
||||
min={0}
|
||||
max={127}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { intensity: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
const parameters = useSelector((state) => selectById(state, props.id));
|
||||
const dispatch = useDispatch();
|
||||
return (
|
||||
<div>
|
||||
<span>{`${props.name}`}</span>
|
||||
Source
|
||||
<SelectList
|
||||
value={parameters.source}
|
||||
list={[
|
||||
{ value: 'Amp EG' },
|
||||
{ value: 'LFO 1' },
|
||||
{ value: 'LFO 2' },
|
||||
{ value: 'Velocity' },
|
||||
{ value: 'Keyboard Track' },
|
||||
{ value: 'Pitch Bend' },
|
||||
{ value: 'Mod Wheel' },
|
||||
]}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { source: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
Intensity
|
||||
<Slider
|
||||
parameter={parameters.intensity}
|
||||
min={0}
|
||||
max={127}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { intensity: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -2,15 +2,14 @@ import React from 'react';
|
||||
import { useSelector, useDispatch } from 'react-redux';
|
||||
import { selectById, parameterUpdated } from './parameterSlice.js';
|
||||
import { Slider, SelectList, Checkbox } from '../../helpers/Helpers';
|
||||
import styles from './Parameters.module.css';
|
||||
|
||||
export default function LFO(props) {
|
||||
const parameters = useSelector((state) => selectById(state, props.id));
|
||||
const dispatch = useDispatch();
|
||||
|
||||
return (
|
||||
<div className={styles.lfo}>
|
||||
<span className={styles.header}>{`${props.name}`}</span>
|
||||
<div>
|
||||
<span>{`${props.name}`}</span>
|
||||
LFO Waveform
|
||||
<SelectList
|
||||
value={parameters.waveform}
|
||||
|
||||
@@ -1,133 +1,132 @@
|
||||
import React from 'react';
|
||||
import { useSelector, useDispatch } from 'react-redux';
|
||||
import { selectById, parameterUpdated } from './parameterSlice.js';
|
||||
import { Slider} from '../../helpers/Helpers';
|
||||
import styles from './Parameters.module.css';
|
||||
import { Slider } from '../../helpers/Helpers';
|
||||
|
||||
export default function Levels(props) {
|
||||
const parameters = useSelector((state) => selectById(state, props.id));
|
||||
const dispatch = useDispatch();
|
||||
const parameters = useSelector((state) => selectById(state, props.id));
|
||||
const dispatch = useDispatch();
|
||||
|
||||
return (
|
||||
<div className={styles.horizontalContainer}>
|
||||
<span className={styles.header}>{`${props.name}`}</span>
|
||||
<div className={styles.container}>
|
||||
Level 1
|
||||
<Slider
|
||||
min={0}
|
||||
max={127}
|
||||
parameter={parameters.level1}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { level1: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
Level 2
|
||||
<Slider
|
||||
min={0}
|
||||
max={127}
|
||||
parameter={parameters.level2}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { level2: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
Level 3
|
||||
<Slider
|
||||
min={0}
|
||||
max={127}
|
||||
parameter={parameters.level3}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { level3: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
Level 4
|
||||
<Slider
|
||||
min={0}
|
||||
max={127}
|
||||
parameter={parameters.level4}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { level4: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<div className={styles.divider}/>
|
||||
<div className={styles.container}>
|
||||
Level 5
|
||||
<Slider
|
||||
min={0}
|
||||
max={127}
|
||||
parameter={parameters.level5}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { level5: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
Level 6
|
||||
<Slider
|
||||
min={0}
|
||||
max={127}
|
||||
parameter={parameters.level6}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { level6: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
Level 7
|
||||
<Slider
|
||||
min={0}
|
||||
max={127}
|
||||
parameter={parameters.level7}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { level7: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
Level 8
|
||||
<Slider
|
||||
min={0}
|
||||
max={127}
|
||||
parameter={parameters.level8}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { level8: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
return (
|
||||
<div>
|
||||
<span>{`${props.name}`}</span>
|
||||
<div>
|
||||
Level 1
|
||||
<Slider
|
||||
min={0}
|
||||
max={127}
|
||||
parameter={parameters.level1}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { level1: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
Level 2
|
||||
<Slider
|
||||
min={0}
|
||||
max={127}
|
||||
parameter={parameters.level2}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { level2: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
Level 3
|
||||
<Slider
|
||||
min={0}
|
||||
max={127}
|
||||
parameter={parameters.level3}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { level3: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
Level 4
|
||||
<Slider
|
||||
min={0}
|
||||
max={127}
|
||||
parameter={parameters.level4}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { level4: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<div />
|
||||
<div>
|
||||
Level 5
|
||||
<Slider
|
||||
min={0}
|
||||
max={127}
|
||||
parameter={parameters.level5}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { level5: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
Level 6
|
||||
<Slider
|
||||
min={0}
|
||||
max={127}
|
||||
parameter={parameters.level6}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { level6: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
Level 7
|
||||
<Slider
|
||||
min={0}
|
||||
max={127}
|
||||
parameter={parameters.level7}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { level7: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
Level 8
|
||||
<Slider
|
||||
min={0}
|
||||
max={127}
|
||||
parameter={parameters.level8}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { level8: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2,58 +2,56 @@ import React from 'react';
|
||||
import { useSelector, useDispatch } from 'react-redux';
|
||||
import { selectById, parameterUpdated } from './parameterSlice.js';
|
||||
import { Slider } from '../../helpers/Helpers';
|
||||
import styles from './Parameters.module.css';
|
||||
|
||||
export default function Mixer(props) {
|
||||
const parameters = useSelector((state) => selectById(state, props.id));
|
||||
const dispatch = useDispatch();
|
||||
const parameters = useSelector((state) => selectById(state, props.id));
|
||||
const dispatch = useDispatch();
|
||||
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
<span className={styles.header}>{`${props.name}`}</span>
|
||||
Volume 1
|
||||
<Slider
|
||||
min={0}
|
||||
max={127}
|
||||
parameter={parameters.vol1}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { vol1: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
Volume 2
|
||||
<Slider
|
||||
min={0}
|
||||
max={127}
|
||||
parameter={parameters.vol2}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { vol2: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
Volume 3
|
||||
<Slider
|
||||
className={styles.slider}
|
||||
min={0}
|
||||
max={127}
|
||||
parameter={parameters.vol3}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { vol3: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
return (
|
||||
<div>
|
||||
<span>{`${props.name}`}</span>
|
||||
Volume 1
|
||||
<Slider
|
||||
min={0}
|
||||
max={127}
|
||||
parameter={parameters.vol1}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { vol1: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
Volume 2
|
||||
<Slider
|
||||
min={0}
|
||||
max={127}
|
||||
parameter={parameters.vol2}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { vol2: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
Volume 3
|
||||
<Slider
|
||||
min={0}
|
||||
max={127}
|
||||
parameter={parameters.vol3}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { vol3: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2,15 +2,14 @@ import React from 'react';
|
||||
import { useSelector, useDispatch } from 'react-redux';
|
||||
import { selectById, parameterUpdated } from './parameterSlice.js';
|
||||
import { Slider, SelectList, Checkbox } from '../../helpers/Helpers';
|
||||
import styles from './Parameters.module.css';
|
||||
|
||||
const ModFX = (props) => {
|
||||
const parameters = useSelector((state) => selectById(state, props.id));
|
||||
const dispatch = useDispatch();
|
||||
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
<span className={styles.header}>Mod FX</span>
|
||||
<div>
|
||||
<span>Mod FX</span>
|
||||
Mod Type
|
||||
<SelectList
|
||||
value={parameters.type}
|
||||
@@ -65,8 +64,8 @@ const Delay = (props) => {
|
||||
const dispatch = useDispatch();
|
||||
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
<span className={styles.header}>Delay</span>
|
||||
<div>
|
||||
<span>Delay</span>
|
||||
Delay Type
|
||||
<SelectList
|
||||
value={parameters.type}
|
||||
@@ -85,7 +84,7 @@ const Delay = (props) => {
|
||||
}
|
||||
/>
|
||||
<Checkbox
|
||||
name="Tempo Sync"
|
||||
name='Tempo Sync'
|
||||
parameter={parameters.tempoSync}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
@@ -169,8 +168,8 @@ const EQ = (props) => {
|
||||
const dispatch = useDispatch();
|
||||
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
<span className={styles.header}>EQ</span>
|
||||
<div>
|
||||
<span>EQ</span>
|
||||
Low EQ Frequency
|
||||
<SelectList
|
||||
labelFunction={(e) => `${e.value}kHz`}
|
||||
|
||||
@@ -1,133 +1,132 @@
|
||||
import React from 'react';
|
||||
import { useSelector, useDispatch } from 'react-redux';
|
||||
import { selectById, parameterUpdated } from './parameterSlice.js';
|
||||
import { Slider} from '../../helpers/Helpers';
|
||||
import styles from './Parameters.module.css';
|
||||
import { Slider } from '../../helpers/Helpers';
|
||||
|
||||
export default function Pans(props) {
|
||||
const parameters = useSelector((state) => selectById(state, props.id));
|
||||
const dispatch = useDispatch();
|
||||
const parameters = useSelector((state) => selectById(state, props.id));
|
||||
const dispatch = useDispatch();
|
||||
|
||||
return (
|
||||
<div className={styles.horizontalContainer}>
|
||||
<span className={styles.header}>{`${props.name}`}</span>
|
||||
<div className={styles.container}>
|
||||
Pan 1
|
||||
<Slider
|
||||
min={0}
|
||||
max={127}
|
||||
parameter={parameters.pan1}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { pan1: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
Pan 2
|
||||
<Slider
|
||||
min={0}
|
||||
max={127}
|
||||
parameter={parameters.pan2}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { pan2: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
Pan 3
|
||||
<Slider
|
||||
min={0}
|
||||
max={127}
|
||||
parameter={parameters.pan3}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { pan3: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
Pan 4
|
||||
<Slider
|
||||
min={0}
|
||||
max={127}
|
||||
parameter={parameters.pan4}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { pan4: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<div className={styles.divider}/>
|
||||
<div className={styles.container}>
|
||||
Pan 5
|
||||
<Slider
|
||||
min={0}
|
||||
max={127}
|
||||
parameter={parameters.pan5}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { pan5: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
Pan 6
|
||||
<Slider
|
||||
min={0}
|
||||
max={127}
|
||||
parameter={parameters.pan6}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { pan6: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
Pan 7
|
||||
<Slider
|
||||
min={0}
|
||||
max={127}
|
||||
parameter={parameters.pan7}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { pan7: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
Pan 8
|
||||
<Slider
|
||||
min={0}
|
||||
max={127}
|
||||
parameter={parameters.pan8}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { pan8: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<div>
|
||||
<span>{`${props.name}`}</span>
|
||||
<div>
|
||||
Pan 1
|
||||
<Slider
|
||||
min={0}
|
||||
max={127}
|
||||
parameter={parameters.pan1}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { pan1: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
Pan 2
|
||||
<Slider
|
||||
min={0}
|
||||
max={127}
|
||||
parameter={parameters.pan2}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { pan2: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
Pan 3
|
||||
<Slider
|
||||
min={0}
|
||||
max={127}
|
||||
parameter={parameters.pan3}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { pan3: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
Pan 4
|
||||
<Slider
|
||||
min={0}
|
||||
max={127}
|
||||
parameter={parameters.pan4}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { pan4: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<div />
|
||||
<div>
|
||||
Pan 5
|
||||
<Slider
|
||||
min={0}
|
||||
max={127}
|
||||
parameter={parameters.pan5}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { pan5: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
Pan 6
|
||||
<Slider
|
||||
min={0}
|
||||
max={127}
|
||||
parameter={parameters.pan6}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { pan6: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
Pan 7
|
||||
<Slider
|
||||
min={0}
|
||||
max={127}
|
||||
parameter={parameters.pan7}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { pan7: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
Pan 8
|
||||
<Slider
|
||||
min={0}
|
||||
max={127}
|
||||
parameter={parameters.pan8}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { pan8: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,98 +0,0 @@
|
||||
.container,
|
||||
.lfo,
|
||||
.horizontalContainer,
|
||||
.patchesContainer {
|
||||
border: solid 1pt slategrey;
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
.container,
|
||||
.lfo {
|
||||
position: relative;
|
||||
font-size: small;
|
||||
display: inline-flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
padding: 16pt;
|
||||
margin: 10pt;
|
||||
min-width: 15%;
|
||||
height: 214px;
|
||||
line-height: 1.5em;
|
||||
}
|
||||
|
||||
.lfo {
|
||||
height: 250px;
|
||||
}
|
||||
|
||||
.lfo > *,
|
||||
.container > * {
|
||||
margin: 3pt 0;
|
||||
}
|
||||
|
||||
.header {
|
||||
font-size: 1.5em;
|
||||
line-height: 1.25em;
|
||||
text-align: center;
|
||||
background-color: white;
|
||||
padding: 0 0.25em 0.075em;
|
||||
border-left: 1px solid slategrey;
|
||||
border-right: 1px solid slategrey;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.lfo > .header,
|
||||
.container > .header {
|
||||
position: absolute;
|
||||
top: -7.5%;
|
||||
left: 12%;
|
||||
}
|
||||
.horizontalContainer > .header,
|
||||
.patchesContainer > .header {
|
||||
position: absolute;
|
||||
top: -5.25%;
|
||||
left: 6%;
|
||||
}
|
||||
|
||||
.horizontalContainer {
|
||||
position: relative;
|
||||
font-size: small;
|
||||
display: inline-flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 16pt 8pt 16pt 8pt;
|
||||
margin: 10pt;
|
||||
width: 448px;
|
||||
height: 214px;
|
||||
}
|
||||
|
||||
.patchesContainer {
|
||||
position: relative;
|
||||
font-size: small;
|
||||
display: inline-flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 16pt 8pt 16pt 8pt;
|
||||
margin: 10pt;
|
||||
width: 680px;
|
||||
height: 250px;
|
||||
}
|
||||
|
||||
.horizontalContainer > .container,
|
||||
.patchesContainer > .container {
|
||||
padding: 0 16pt;
|
||||
width: 100%;
|
||||
margin: 10pt 0;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.divider {
|
||||
height: 214px;
|
||||
width: 2px;
|
||||
background-color: slategrey;
|
||||
margin: 0 8pt;
|
||||
}
|
||||
|
||||
.patchesContainer > .divider {
|
||||
width: 4px;
|
||||
}
|
||||
@@ -2,128 +2,127 @@ import React from 'react';
|
||||
import { useSelector, useDispatch } from 'react-redux';
|
||||
import { selectById, parameterUpdated } from './parameterSlice.js';
|
||||
import { Slider, SelectList } from '../../helpers/Helpers';
|
||||
import styles from './Parameters.module.css';
|
||||
|
||||
const Patch = (props) => {
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
Source
|
||||
<SelectList
|
||||
value={props.patch.source}
|
||||
list={[
|
||||
{ value: 'Filter EG' },
|
||||
{ value: 'Amp Eg' },
|
||||
{ value: 'LFO 1' },
|
||||
{ value: 'LFO 2' },
|
||||
{ value: 'Velocity' },
|
||||
{ value: 'Keyboard Track' },
|
||||
{ value: 'Pitch Bend' },
|
||||
{ value: 'Mod Wheel' },
|
||||
]}
|
||||
onChange={(value) =>
|
||||
props.onChange({
|
||||
source: value,
|
||||
destination: props.patch.destination,
|
||||
modIntensity: props.patch.modIntensity,
|
||||
})
|
||||
}
|
||||
/>
|
||||
Destination
|
||||
<SelectList
|
||||
value={props.patch.destination}
|
||||
list={[
|
||||
{ value: 'Pitch' },
|
||||
{ value: 'OSC 2 Tune' },
|
||||
{ value: 'OSC 1 Control 1' },
|
||||
{ value: 'Noise Level' },
|
||||
{ value: 'Cutoff' },
|
||||
{ value: 'Amp' },
|
||||
{ value: 'Pan' },
|
||||
{ value: 'LFO 2 Frequency' },
|
||||
]}
|
||||
onChange={(value) =>
|
||||
props.onChange({
|
||||
source: props.patch.source,
|
||||
destination: value,
|
||||
modIntensity: props.patch.modIntensity,
|
||||
})
|
||||
}
|
||||
/>
|
||||
Mod Intensity
|
||||
<Slider
|
||||
min={0}
|
||||
max={127}
|
||||
parameter={props.patch.modIntensity}
|
||||
onChange={(value) =>
|
||||
props.onChange({
|
||||
source: props.patch.source,
|
||||
destination: props.patch.destination,
|
||||
modIntensity: value,
|
||||
})
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
return (
|
||||
<div>
|
||||
Source
|
||||
<SelectList
|
||||
value={props.patch.source}
|
||||
list={[
|
||||
{ value: 'Filter EG' },
|
||||
{ value: 'Amp Eg' },
|
||||
{ value: 'LFO 1' },
|
||||
{ value: 'LFO 2' },
|
||||
{ value: 'Velocity' },
|
||||
{ value: 'Keyboard Track' },
|
||||
{ value: 'Pitch Bend' },
|
||||
{ value: 'Mod Wheel' },
|
||||
]}
|
||||
onChange={(value) =>
|
||||
props.onChange({
|
||||
source: value,
|
||||
destination: props.patch.destination,
|
||||
modIntensity: props.patch.modIntensity,
|
||||
})
|
||||
}
|
||||
/>
|
||||
Destination
|
||||
<SelectList
|
||||
value={props.patch.destination}
|
||||
list={[
|
||||
{ value: 'Pitch' },
|
||||
{ value: 'OSC 2 Tune' },
|
||||
{ value: 'OSC 1 Control 1' },
|
||||
{ value: 'Noise Level' },
|
||||
{ value: 'Cutoff' },
|
||||
{ value: 'Amp' },
|
||||
{ value: 'Pan' },
|
||||
{ value: 'LFO 2 Frequency' },
|
||||
]}
|
||||
onChange={(value) =>
|
||||
props.onChange({
|
||||
source: props.patch.source,
|
||||
destination: value,
|
||||
modIntensity: props.patch.modIntensity,
|
||||
})
|
||||
}
|
||||
/>
|
||||
Mod Intensity
|
||||
<Slider
|
||||
min={0}
|
||||
max={127}
|
||||
parameter={props.patch.modIntensity}
|
||||
onChange={(value) =>
|
||||
props.onChange({
|
||||
source: props.patch.source,
|
||||
destination: props.patch.destination,
|
||||
modIntensity: value,
|
||||
})
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default function Patches(props) {
|
||||
const parameters = useSelector((state) => selectById(state, props.id));
|
||||
const dispatch = useDispatch();
|
||||
const parameters = useSelector((state) => selectById(state, props.id));
|
||||
const dispatch = useDispatch();
|
||||
|
||||
return (
|
||||
<div id="patches" className={styles.patchesContainer}>
|
||||
<span className={styles.header}>{`${props.name}`}</span>
|
||||
<Patch
|
||||
patch={parameters.patch1}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: {
|
||||
patch1: value,
|
||||
},
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
<div className={styles.divider} />
|
||||
<Patch
|
||||
patch={parameters.patch2}
|
||||
onChange={(value, parameter) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: {
|
||||
patch2: value,
|
||||
},
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
<div className={styles.divider} />
|
||||
<Patch
|
||||
patch={parameters.patch3}
|
||||
onChange={(value, parameter) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { patch3: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
<div className={styles.divider} />
|
||||
<Patch
|
||||
patch={parameters.patch4}
|
||||
onChange={(value, parameter) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { patch4: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
return (
|
||||
<div id='patches'>
|
||||
<span>{`${props.name}`}</span>
|
||||
<Patch
|
||||
patch={parameters.patch1}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: {
|
||||
patch1: value,
|
||||
},
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
<div />
|
||||
<Patch
|
||||
patch={parameters.patch2}
|
||||
onChange={(value, parameter) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: {
|
||||
patch2: value,
|
||||
},
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
<div />
|
||||
<Patch
|
||||
patch={parameters.patch3}
|
||||
onChange={(value, parameter) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { patch3: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
<div />
|
||||
<Patch
|
||||
patch={parameters.patch4}
|
||||
onChange={(value, parameter) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { patch4: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2,134 +2,129 @@ import React from 'react';
|
||||
import { useSelector, useDispatch } from 'react-redux';
|
||||
import { selectById, parameterUpdated } from './parameterSlice.js';
|
||||
import { Slider, SelectList } from '../../helpers/Helpers';
|
||||
import styles from './Parameters.module.css';
|
||||
|
||||
export default function Pitch(props) {
|
||||
const parameters = useSelector((state) => selectById(state, props.id));
|
||||
const dispatch = useDispatch();
|
||||
const parameters = useSelector((state) => selectById(state, props.id));
|
||||
const dispatch = useDispatch();
|
||||
|
||||
return (
|
||||
<div className={styles.horizontalContainer}>
|
||||
<span className={styles.header}>{`${props.name}`}</span>
|
||||
<div className={styles.container}>
|
||||
Voice Assign
|
||||
<SelectList
|
||||
value={parameters.voiceAssign}
|
||||
list={[
|
||||
{ value: 'Mono' },
|
||||
{ value: 'Poly' },
|
||||
{ value: 'Unison' },
|
||||
]}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { voiceAssign: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
Trigger Mode
|
||||
<SelectList
|
||||
value={parameters.triggerMode}
|
||||
list={[{ value: 'Single' }, { value: 'Multiple' }]}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { triggerMode: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
Transpose
|
||||
<Slider
|
||||
parameter={parameters.transpose}
|
||||
min={-24}
|
||||
max={24}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { transpose: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<div className={styles.divider} />
|
||||
<div className={styles.container}>
|
||||
Tune
|
||||
<Slider
|
||||
parameter={parameters.tune}
|
||||
min={-50}
|
||||
max={50}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { tune: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
Unisone Detune
|
||||
<Slider
|
||||
parameter={parameters.unisonDetune}
|
||||
min={0}
|
||||
max={99}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { unisonDetune: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
Portamento
|
||||
<Slider
|
||||
parameter={parameters.portamento}
|
||||
min={0}
|
||||
max={127}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { portamento: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
Bend Range
|
||||
<Slider
|
||||
parameter={parameters.bendRange}
|
||||
min={-12}
|
||||
max={12}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { bendRange: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
Vibrato Intensity
|
||||
<Slider
|
||||
parameter={parameters.vibratoIntensity}
|
||||
min={-63}
|
||||
max={63}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { vibratoIntensity: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
return (
|
||||
<div>
|
||||
<span>{`${props.name}`}</span>
|
||||
<div>
|
||||
Voice Assign
|
||||
<SelectList
|
||||
value={parameters.voiceAssign}
|
||||
list={[{ value: 'Mono' }, { value: 'Poly' }, { value: 'Unison' }]}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { voiceAssign: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
Trigger Mode
|
||||
<SelectList
|
||||
value={parameters.triggerMode}
|
||||
list={[{ value: 'Single' }, { value: 'Multiple' }]}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { triggerMode: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
Transpose
|
||||
<Slider
|
||||
parameter={parameters.transpose}
|
||||
min={-24}
|
||||
max={24}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { transpose: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<div />
|
||||
<div>
|
||||
Tune
|
||||
<Slider
|
||||
parameter={parameters.tune}
|
||||
min={-50}
|
||||
max={50}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { tune: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
Unisone Detune
|
||||
<Slider
|
||||
parameter={parameters.unisonDetune}
|
||||
min={0}
|
||||
max={99}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { unisonDetune: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
Portamento
|
||||
<Slider
|
||||
parameter={parameters.portamento}
|
||||
min={0}
|
||||
max={127}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { portamento: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
Bend Range
|
||||
<Slider
|
||||
parameter={parameters.bendRange}
|
||||
min={-12}
|
||||
max={12}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { bendRange: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
Vibrato Intensity
|
||||
<Slider
|
||||
parameter={parameters.vibratoIntensity}
|
||||
min={-63}
|
||||
max={63}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { vibratoIntensity: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2,134 +2,133 @@ import React from 'react';
|
||||
import { useSelector, useDispatch } from 'react-redux';
|
||||
import { selectById, parameterUpdated } from './parameterSlice.js';
|
||||
import { Slider, SelectList, Checkbox } from '../../helpers/Helpers';
|
||||
import styles from './Parameters.module.css';
|
||||
|
||||
export default function VCO(props) {
|
||||
const parameters = useSelector((state) => selectById(state, props.id));
|
||||
const parameters = useSelector((state) => selectById(state, props.id));
|
||||
|
||||
const dispatch = useDispatch();
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
<span className={styles.header}>{`${props.name}`}</span>
|
||||
Waveform
|
||||
<SelectList
|
||||
value={parameters.waveform}
|
||||
list={props.waveforms}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { waveform: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
{`${props.dwgsOrModTypeName}`}
|
||||
<SelectList
|
||||
value={parameters.dwgsOrModType}
|
||||
list={props.dwgsOrModType}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { dwgsOrModType: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
Waveform Mod
|
||||
<Slider
|
||||
min={0}
|
||||
max={127}
|
||||
parameter={parameters.waveMod}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { waveMod: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
LFO Mod
|
||||
<Slider
|
||||
min={0}
|
||||
max={127}
|
||||
parameter={parameters.lfoMod}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { lfoMod: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
const dispatch = useDispatch();
|
||||
return (
|
||||
<div>
|
||||
<span>{`${props.name}`}</span>
|
||||
Waveform
|
||||
<SelectList
|
||||
value={parameters.waveform}
|
||||
list={props.waveforms}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { waveform: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
{`${props.dwgsOrModTypeName}`}
|
||||
<SelectList
|
||||
value={parameters.dwgsOrModType}
|
||||
list={props.dwgsOrModType}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { dwgsOrModType: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
Waveform Mod
|
||||
<Slider
|
||||
min={0}
|
||||
max={127}
|
||||
parameter={parameters.waveMod}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { waveMod: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
LFO Mod
|
||||
<Slider
|
||||
min={0}
|
||||
max={127}
|
||||
parameter={parameters.lfoMod}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { lfoMod: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export const AudioIn = (props) => {
|
||||
const parameters = useSelector((state) => selectById(state, props.id));
|
||||
const dispatch = useDispatch();
|
||||
const parameters = useSelector((state) => selectById(state, props.id));
|
||||
const dispatch = useDispatch();
|
||||
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
<span className={styles.header}>{`${props.name}`}</span>
|
||||
Gate
|
||||
<Slider
|
||||
min={0}
|
||||
max={127}
|
||||
parameter={parameters.gate}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { gate: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
Threshold
|
||||
<Slider
|
||||
min={0}
|
||||
max={127}
|
||||
parameter={parameters.threshold}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { threshold: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
HPF Level
|
||||
<Slider
|
||||
min={0}
|
||||
max={127}
|
||||
parameter={parameters.hpfLevel}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { hpfLevel: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
<Checkbox
|
||||
name="HPF Gate"
|
||||
parameter={parameters.hpfGate}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { hpfGate: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
return (
|
||||
<div>
|
||||
<span>{`${props.name}`}</span>
|
||||
Gate
|
||||
<Slider
|
||||
min={0}
|
||||
max={127}
|
||||
parameter={parameters.gate}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { gate: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
Threshold
|
||||
<Slider
|
||||
min={0}
|
||||
max={127}
|
||||
parameter={parameters.threshold}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { threshold: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
HPF Level
|
||||
<Slider
|
||||
min={0}
|
||||
max={127}
|
||||
parameter={parameters.hpfLevel}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { hpfLevel: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
<Checkbox
|
||||
name='HPF Gate'
|
||||
parameter={parameters.hpfGate}
|
||||
onChange={(value) =>
|
||||
dispatch(
|
||||
parameterUpdated({
|
||||
id: props.id,
|
||||
changes: { hpfGate: value },
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -5,24 +5,18 @@ import Effects from './Effects';
|
||||
import Arpeggio from './Arpeggio';
|
||||
import { Tab, Tabs, TabList, TabPanel } from 'react-tabs';
|
||||
import { useSelector } from 'react-redux';
|
||||
import styles from './Timbre.module.css';
|
||||
|
||||
export default function TimbreSwitcher() {
|
||||
const index = useSelector((state) => state.parameters.tabIndex);
|
||||
return (
|
||||
<div className={styles.tabs}>
|
||||
<Tabs
|
||||
className={styles.tabs}
|
||||
selectedIndex={index}
|
||||
onSelect={() => {}}
|
||||
selectedTabClassName={styles.selected}
|
||||
selectedTabPanelClassName={styles.tabPanel}>
|
||||
<TabList className={styles.tabList}>
|
||||
<Tab className={styles.tab}>Timbre 1</Tab>
|
||||
<Tab className={styles.tab}>Timbre 2</Tab>
|
||||
<Tab className={styles.tab}>Vocoder</Tab>
|
||||
<Tab className={styles.tab}>Effects</Tab>
|
||||
<Tab className={styles.tab}>Arpeggio</Tab>
|
||||
<div>
|
||||
<Tabs selectedIndex={index} onSelect={() => {}}>
|
||||
<TabList>
|
||||
<Tab>Timbre 1</Tab>
|
||||
<Tab>Timbre 2</Tab>
|
||||
<Tab>Vocoder</Tab>
|
||||
<Tab>Effects</Tab>
|
||||
<Tab>Arpeggio</Tab>
|
||||
</TabList>
|
||||
|
||||
<TabPanel>
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
const Select = (props) => {
|
||||
return (
|
||||
<select
|
||||
className={props.className}
|
||||
onChange={(e) => props.onChange(e.target.value)}
|
||||
value={props.value}>
|
||||
{props.list.map((element) => (
|
||||
<option value={element.value}>{element.value}</option>
|
||||
))}
|
||||
</select>
|
||||
);
|
||||
};
|
||||
|
||||
export { Select };
|
||||
@@ -13,3 +13,7 @@ code {
|
||||
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
|
||||
monospace;
|
||||
}
|
||||
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
module.exports = {
|
||||
purge: ['./src/**/*.{js,jsx,ts,tsx}', './public/index.html'],
|
||||
darkMode: false, // or 'media' or 'class'
|
||||
theme: {
|
||||
extend: {},
|
||||
},
|
||||
variants: {
|
||||
extend: {},
|
||||
},
|
||||
plugins: [require('@tailwindcss/forms')],
|
||||
};
|
||||
Reference in New Issue
Block a user