mirror of
https://github.com/eliasstepanik/strudel-docker.git
synced 2026-01-11 05:38:34 +00:00
migrate repl + move imports out of minirepl
This commit is contained in:
parent
0bcc01ed0e
commit
ed35f967b0
@ -1 +1,3 @@
|
||||
import './midi.mjs';
|
||||
|
||||
export * from './midi.mjs';
|
||||
|
||||
6
packages/react/dist/index.cjs.js
vendored
6
packages/react/dist/index.cjs.js
vendored
File diff suppressed because one or more lines are too long
153
packages/react/dist/index.es.js
vendored
153
packages/react/dist/index.es.js
vendored
@ -1,14 +1,15 @@
|
||||
import React$1, { useState, useEffect, useCallback, useMemo, useRef } from 'react';
|
||||
import React, { useState, useEffect, useCallback, useMemo, useRef } from 'react';
|
||||
import { CodeMirror as CodeMirror$1 } from 'react-codemirror6';
|
||||
import { EditorView, Decoration } from '@codemirror/view';
|
||||
import { StateEffect, StateField } from '@codemirror/state';
|
||||
import { javascript } from '@codemirror/lang-javascript';
|
||||
import { HighlightStyle, tags } from '@codemirror/highlight';
|
||||
import { useInView } from 'react-hook-inview';
|
||||
import { evaluate, evalScope } from '@strudel.cycles/eval';
|
||||
import { evaluate } from '@strudel.cycles/eval';
|
||||
import { getPlayableNoteValue } from '@strudel.cycles/core/util.mjs';
|
||||
import { Tone } from '@strudel.cycles/tone';
|
||||
import { TimeSpan, State } from '@strudel.cycles/core';
|
||||
import { WebMidi, enableWebMidi } from '@strudel.cycles/midi';
|
||||
|
||||
/*
|
||||
Credits for color palette:
|
||||
@ -173,7 +174,7 @@ const highlightField = StateField.define({
|
||||
provide: (f) => EditorView.decorations.from(f)
|
||||
});
|
||||
function CodeMirror({ value, onChange, onViewChanged, onCursor, options, editorDidMount }) {
|
||||
return /* @__PURE__ */ React$1.createElement(React$1.Fragment, null, /* @__PURE__ */ React$1.createElement(CodeMirror$1, {
|
||||
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(CodeMirror$1, {
|
||||
onViewChange: onViewChanged,
|
||||
style: {
|
||||
display: "flex",
|
||||
@ -189,82 +190,6 @@ function CodeMirror({ value, onChange, onViewChanged, onCursor, options, editorD
|
||||
]
|
||||
}));
|
||||
}
|
||||
let parenMark;
|
||||
const markParens = (editor, data) => {
|
||||
const v = editor.getDoc().getValue();
|
||||
const marked = getCurrentParenArea(v, data);
|
||||
parenMark?.clear();
|
||||
parenMark = editor.getDoc().markText(...marked, { css: "background-color: #00007720" });
|
||||
};
|
||||
function offsetToPosition(offset, code) {
|
||||
const lines = code.split("\n");
|
||||
let line = 0;
|
||||
let ch = 0;
|
||||
for (let i = 0; i < offset; i++) {
|
||||
if (ch === lines[line].length) {
|
||||
line++;
|
||||
ch = 0;
|
||||
} else {
|
||||
ch++;
|
||||
}
|
||||
}
|
||||
return { line, ch };
|
||||
}
|
||||
function positionToOffset(position, code) {
|
||||
const lines = code.split("\n");
|
||||
if (position.line > lines.length) {
|
||||
return 0;
|
||||
}
|
||||
let offset = 0;
|
||||
for (let i = 0; i < position.line; i++) {
|
||||
offset += lines[i].length + 1;
|
||||
}
|
||||
offset += position.ch;
|
||||
return offset;
|
||||
}
|
||||
function getCurrentParenArea(code, caretPosition) {
|
||||
const caret = positionToOffset(caretPosition, code);
|
||||
let open, i, begin, end;
|
||||
i = caret;
|
||||
open = 0;
|
||||
while (i > 0) {
|
||||
if (code[i - 1] === "(") {
|
||||
open--;
|
||||
} else if (code[i - 1] === ")") {
|
||||
open++;
|
||||
}
|
||||
if (open === -1) {
|
||||
break;
|
||||
}
|
||||
i--;
|
||||
}
|
||||
begin = i;
|
||||
i = caret;
|
||||
open = 0;
|
||||
while (i < code.length) {
|
||||
if (code[i] === "(") {
|
||||
open--;
|
||||
} else if (code[i] === ")") {
|
||||
open++;
|
||||
}
|
||||
if (open === 1) {
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
end = i;
|
||||
return [begin, end].map((o) => offsetToPosition(o, code));
|
||||
}
|
||||
|
||||
var CodeMirror6 = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({
|
||||
__proto__: null,
|
||||
setHighlights: setHighlights,
|
||||
'default': CodeMirror,
|
||||
markParens: markParens,
|
||||
offsetToPosition: offsetToPosition,
|
||||
positionToOffset: positionToOffset,
|
||||
getCurrentParenArea: getCurrentParenArea
|
||||
}, Symbol.toStringTag, { value: 'Module' }));
|
||||
|
||||
/*
|
||||
useCycle.mjs - <short description TODO>
|
||||
@ -607,14 +532,7 @@ function Icon({ type }) {
|
||||
}[type]);
|
||||
}
|
||||
|
||||
evalScope(Tone, import('@strudel.cycles/core'), import('@strudel.cycles/tone'), import('@strudel.cycles/tonal'), import('@strudel.cycles/mini'), import('@strudel.cycles/midi'), import('@strudel.cycles/xen'), import('@strudel.cycles/webaudio'));
|
||||
const defaultSynth = new Tone.PolySynth().chain(new Tone.Gain(0.5), Tone.Destination).set({
|
||||
oscillator: { type: "triangle" },
|
||||
envelope: {
|
||||
release: 0.01
|
||||
}
|
||||
});
|
||||
function MiniRepl({ tune }) {
|
||||
function MiniRepl({ tune, defaultSynth }) {
|
||||
const { code, setCode, pattern, activateCode, error, cycle, dirty, togglePlay } = useRepl({
|
||||
tune,
|
||||
defaultSynth,
|
||||
@ -632,32 +550,71 @@ function MiniRepl({ tune }) {
|
||||
return isVisible || wasVisible.current;
|
||||
}, [isVisible]);
|
||||
useHighlighting({ view, pattern, active: cycle.started });
|
||||
return /* @__PURE__ */ React$1.createElement("div", {
|
||||
return /* @__PURE__ */ React.createElement("div", {
|
||||
className: styles.container,
|
||||
ref
|
||||
}, /* @__PURE__ */ React$1.createElement("div", {
|
||||
}, /* @__PURE__ */ React.createElement("div", {
|
||||
className: styles.header
|
||||
}, /* @__PURE__ */ React$1.createElement("div", {
|
||||
}, /* @__PURE__ */ React.createElement("div", {
|
||||
className: styles.buttons
|
||||
}, /* @__PURE__ */ React$1.createElement("button", {
|
||||
}, /* @__PURE__ */ React.createElement("button", {
|
||||
className: cx(styles.button, cycle.started ? "sc-animate-pulse" : ""),
|
||||
onClick: () => togglePlay()
|
||||
}, /* @__PURE__ */ React$1.createElement(Icon, {
|
||||
}, /* @__PURE__ */ React.createElement(Icon, {
|
||||
type: cycle.started ? "pause" : "play"
|
||||
})), /* @__PURE__ */ React$1.createElement("button", {
|
||||
})), /* @__PURE__ */ React.createElement("button", {
|
||||
className: cx(dirty ? styles.button : styles.buttonDisabled),
|
||||
onClick: () => activateCode()
|
||||
}, /* @__PURE__ */ React$1.createElement(Icon, {
|
||||
}, /* @__PURE__ */ React.createElement(Icon, {
|
||||
type: "refresh"
|
||||
}))), error && /* @__PURE__ */ React$1.createElement("div", {
|
||||
}))), error && /* @__PURE__ */ React.createElement("div", {
|
||||
className: styles.error
|
||||
}, error.message)), /* @__PURE__ */ React$1.createElement("div", {
|
||||
}, error.message)), /* @__PURE__ */ React.createElement("div", {
|
||||
className: styles.body
|
||||
}, show && /* @__PURE__ */ React$1.createElement(CodeMirror, {
|
||||
}, show && /* @__PURE__ */ React.createElement(CodeMirror, {
|
||||
value: code,
|
||||
onChange: setCode,
|
||||
onViewChanged: setView
|
||||
})));
|
||||
}
|
||||
|
||||
export { CodeMirror6 as CodeMirror, MiniRepl };
|
||||
/*
|
||||
useWebMidi.js - <short description TODO>
|
||||
Copyright (C) 2022 Strudel contributors - see <https://github.com/tidalcycles/strudel/blob/main/repl/src/useWebMidi.js>
|
||||
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
function useWebMidi(props) {
|
||||
const { ready, connected, disconnected } = props;
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [outputs, setOutputs] = useState(WebMidi?.outputs || []);
|
||||
useEffect(() => {
|
||||
enableWebMidi()
|
||||
.then(() => {
|
||||
// Reacting when a new device becomes available
|
||||
WebMidi.addListener('connected', (e) => {
|
||||
setOutputs([...WebMidi.outputs]);
|
||||
connected?.(WebMidi, e);
|
||||
});
|
||||
// Reacting when a device becomes unavailable
|
||||
WebMidi.addListener('disconnected', (e) => {
|
||||
setOutputs([...WebMidi.outputs]);
|
||||
disconnected?.(WebMidi, e);
|
||||
});
|
||||
ready?.(WebMidi);
|
||||
setLoading(false);
|
||||
})
|
||||
.catch((err) => {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
//throw new Error("Web Midi could not be enabled...");
|
||||
console.warn('Web Midi could not be enabled..');
|
||||
return;
|
||||
}
|
||||
});
|
||||
}, [ready, connected, disconnected, outputs]);
|
||||
const outputByName = (name) => WebMidi.getOutputByName(name);
|
||||
return { loading, outputs, outputByName };
|
||||
}
|
||||
|
||||
export { CodeMirror, MiniRepl, cx, useCycle, useHighlighting, usePostMessage, useRepl, useWebMidi };
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import React, { useState, useMemo, useRef } from 'react';
|
||||
import { useInView } from 'react-hook-inview';
|
||||
|
||||
import useRepl from '../hooks/useRepl.mjs';
|
||||
import cx from '../cx';
|
||||
import useHighlighting from '../hooks/useHighlighting.mjs';
|
||||
@ -9,27 +8,7 @@ import 'tailwindcss/tailwind.css';
|
||||
import styles from './MiniRepl.module.css';
|
||||
import { Icon } from './Icon';
|
||||
|
||||
import { Tone } from '@strudel.cycles/tone';
|
||||
import { evalScope } from '@strudel.cycles/eval';
|
||||
evalScope(
|
||||
Tone,
|
||||
import('@strudel.cycles/core'),
|
||||
import('@strudel.cycles/tone'),
|
||||
import('@strudel.cycles/tonal'),
|
||||
import('@strudel.cycles/mini'),
|
||||
import('@strudel.cycles/midi'),
|
||||
import('@strudel.cycles/xen'),
|
||||
import('@strudel.cycles/webaudio'),
|
||||
);
|
||||
|
||||
const defaultSynth = new Tone.PolySynth().chain(new Tone.Gain(0.5), Tone.Destination).set({
|
||||
oscillator: { type: 'triangle' },
|
||||
envelope: {
|
||||
release: 0.01,
|
||||
},
|
||||
});
|
||||
|
||||
export function MiniRepl({ tune }) {
|
||||
export function MiniRepl({ tune, defaultSynth }) {
|
||||
const { code, setCode, pattern, activateCode, error, cycle, dirty, togglePlay } = useRepl({
|
||||
tune,
|
||||
defaultSynth,
|
||||
|
||||
@ -1,4 +1,10 @@
|
||||
// import 'tailwindcss/tailwind.css';
|
||||
|
||||
export * as CodeMirror from './components/CodeMirror6';
|
||||
export { default as CodeMirror } from './components/CodeMirror6';
|
||||
export * from './components/MiniRepl';
|
||||
export { default as useCycle } from './hooks/useCycle';
|
||||
export { default as useHighlighting } from './hooks/useHighlighting';
|
||||
export { default as usePostMessage } from './hooks/usePostMessage';
|
||||
export { default as useRepl } from './hooks/useRepl';
|
||||
export { default as cx } from './cx';
|
||||
export { useWebMidi } from './hooks/useWebMidi';
|
||||
|
||||
@ -47,7 +47,7 @@ Pattern.prototype.draw = function (callback, cycleSpan, lookaheadCycles = 1) {
|
||||
return this;
|
||||
};
|
||||
|
||||
export const cleanup = () => {
|
||||
export const cleanupDraw = () => {
|
||||
const ctx = getDrawContext();
|
||||
ctx.clearRect(0, 0, window.innerWidth, window.innerHeight);
|
||||
if (window.strudelAnimation) {
|
||||
|
||||
@ -47,7 +47,7 @@ export const backgroundImage = function (src, animateOptions = {}) {
|
||||
);
|
||||
};
|
||||
|
||||
export const cleanup = () => {
|
||||
export const cleanupUi = () => {
|
||||
const container = document.getElementById('code');
|
||||
if (container) {
|
||||
container.style = '';
|
||||
|
||||
@ -4,59 +4,24 @@ Copyright (C) 2022 Strudel contributors - see <https://github.com/tidalcycles/st
|
||||
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import CodeMirror6, { setHighlights } from '@strudel.cycles/react/src/components/CodeMirror6';
|
||||
import React, { useCallback, useLayoutEffect, useRef, useState } from 'react';
|
||||
import cx from '@strudel.cycles/react/src/cx';
|
||||
import logo from './logo.svg';
|
||||
// import playStatic from './static.mjs';
|
||||
import { getDefaultSynth } from '@strudel.cycles/tone';
|
||||
import * as tunes from './tunes.mjs';
|
||||
import useRepl from '@strudel.cycles/react/src/hooks/useRepl.mjs';
|
||||
import { useWebMidi } from '@strudel.cycles/react/src/hooks/useWebMidi.mjs';
|
||||
import useHighlighting from '@strudel.cycles/react/src/hooks/useHighlighting';
|
||||
import './App.css';
|
||||
// eval stuff start
|
||||
import { evaluate, extend } from '@strudel.cycles/eval';
|
||||
import * as strudel from '@strudel.cycles/core';
|
||||
import gist from '@strudel.cycles/core/gist.js';
|
||||
import { mini } from '@strudel.cycles/mini/mini.mjs';
|
||||
import { Tone } from '@strudel.cycles/tone';
|
||||
import * as toneHelpers from '@strudel.cycles/tone/tone.mjs';
|
||||
import * as voicingHelpers from '@strudel.cycles/tonal/voicings.mjs';
|
||||
import * as uiHelpers from '@strudel.cycles/tone/ui.mjs';
|
||||
import * as drawHelpers from '@strudel.cycles/tone/draw.mjs';
|
||||
import euclid from '@strudel.cycles/core/euclid.mjs';
|
||||
import '@strudel.cycles/tone/tone.mjs';
|
||||
import '@strudel.cycles/midi/midi.mjs';
|
||||
import '@strudel.cycles/tonal/voicings.mjs';
|
||||
import '@strudel.cycles/tonal/tonal.mjs';
|
||||
import '@strudel.cycles/xen/xen.mjs';
|
||||
import '@strudel.cycles/xen/tune.mjs';
|
||||
import '@strudel.cycles/core/euclid.mjs';
|
||||
import '@strudel.cycles/core/speak.mjs';
|
||||
import '@strudel.cycles/tone/pianoroll.mjs';
|
||||
import '@strudel.cycles/tone/draw.mjs';
|
||||
import '@strudel.cycles/osc/osc.mjs';
|
||||
import '@strudel.cycles/webaudio/webaudio.mjs';
|
||||
import '@strudel.cycles/serial/serial.mjs';
|
||||
import controls from '@strudel.cycles/core/controls.mjs';
|
||||
|
||||
// TODO: refactor to evalScope
|
||||
extend(
|
||||
import { evalScope, evaluate } from '@strudel.cycles/eval';
|
||||
import { CodeMirror, cx, useHighlighting, useRepl, useWebMidi } from '@strudel.cycles/react';
|
||||
import { getDefaultSynth, cleanupDraw, cleanupUi, Tone } from '@strudel.cycles/tone';
|
||||
import React, { useCallback, useLayoutEffect, useRef, useState } from 'react';
|
||||
import './App.css';
|
||||
import logo from './logo.svg';
|
||||
import * as tunes from './tunes.mjs';
|
||||
evalScope(
|
||||
Tone,
|
||||
strudel,
|
||||
strudel.Pattern.prototype.bootstrap(),
|
||||
controls,
|
||||
toneHelpers,
|
||||
voicingHelpers,
|
||||
drawHelpers,
|
||||
uiHelpers,
|
||||
{
|
||||
gist,
|
||||
euclid,
|
||||
mini,
|
||||
Tone,
|
||||
},
|
||||
import('@strudel.cycles/core'),
|
||||
import('@strudel.cycles/tone'),
|
||||
import('@strudel.cycles/tonal'),
|
||||
import('@strudel.cycles/mini'),
|
||||
import('@strudel.cycles/midi'),
|
||||
import('@strudel.cycles/xen'),
|
||||
import('@strudel.cycles/webaudio'),
|
||||
);
|
||||
|
||||
const initialUrl = window.location.href;
|
||||
@ -195,8 +160,8 @@ function App() {
|
||||
const _code = getRandomTune();
|
||||
console.log('tune', _code); // uncomment this to debug when random code fails
|
||||
setCode(_code);
|
||||
drawHelpers.cleanup();
|
||||
uiHelpers.cleanup();
|
||||
cleanupDraw();
|
||||
cleanupUi();
|
||||
const parsed = await evaluate(_code);
|
||||
setPattern(parsed.pattern);
|
||||
setActiveCode(_code);
|
||||
@ -235,7 +200,7 @@ function App() {
|
||||
<section className="grow flex flex-col text-gray-100">
|
||||
<div className="grow relative flex overflow-auto" id="code">
|
||||
{/* onCursor={markParens} */}
|
||||
<CodeMirror6 value={code} onChange={setCode} onViewChanged={setView} />
|
||||
<CodeMirror value={code} onChange={setCode} onViewChanged={setView} />
|
||||
<span className="z-[20] py-1 px-2 absolute top-0 right-0 text-xs whitespace-pre text-right pointer-events-none">
|
||||
{!cycle.started ? `press ctrl+enter to play\n` : dirty ? `ctrl+enter to update\n` : 'no changes\n'}
|
||||
</span>
|
||||
|
||||
25
tutorial/MiniRepl.jsx
Normal file
25
tutorial/MiniRepl.jsx
Normal file
@ -0,0 +1,25 @@
|
||||
import { Tone } from '@strudel.cycles/tone';
|
||||
import { evalScope } from '@strudel.cycles/eval';
|
||||
import { MiniRepl as _MiniRepl } from '@strudel.cycles/react';
|
||||
|
||||
export const defaultSynth = new Tone.PolySynth().chain(new Tone.Gain(0.5), Tone.Destination).set({
|
||||
oscillator: { type: 'triangle' },
|
||||
envelope: {
|
||||
release: 0.01,
|
||||
},
|
||||
});
|
||||
|
||||
evalScope(
|
||||
Tone,
|
||||
import('@strudel.cycles/core'),
|
||||
import('@strudel.cycles/tone'),
|
||||
import('@strudel.cycles/tonal'),
|
||||
import('@strudel.cycles/mini'),
|
||||
import('@strudel.cycles/midi'),
|
||||
import('@strudel.cycles/xen'),
|
||||
import('@strudel.cycles/webaudio'),
|
||||
);
|
||||
|
||||
export function MiniRepl({ tune }) {
|
||||
return <_MiniRepl tune={tune} defaultSynth={defaultSynth} />;
|
||||
}
|
||||
@ -10,7 +10,6 @@ import Tutorial from './tutorial.mdx';
|
||||
import './style.css';
|
||||
import '@strudel.cycles/react/dist/style.css';
|
||||
|
||||
|
||||
ReactDOM.render(
|
||||
<React.StrictMode>
|
||||
<div className="min-h-screen">
|
||||
@ -32,5 +31,5 @@ ReactDOM.render(
|
||||
</main>
|
||||
</div>
|
||||
</React.StrictMode>,
|
||||
document.getElementById('root')
|
||||
document.getElementById('root'),
|
||||
);
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { MiniRepl } from '@strudel.cycles/react';
|
||||
import { MiniRepl } from './MiniRepl';
|
||||
|
||||
# What is Strudel?
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user