import React, { useLayoutEffect, useRef } from 'react'; import * as Tone from 'tone'; import CodeMirror from './CodeMirror'; import cx from './cx'; import { evaluate } from './evaluate'; import logo from './logo.svg'; import * as tunes from './tunes'; import useRepl from './useRepl'; // TODO: use https://www.npmjs.com/package/@monaco-editor/react const [_, codeParam] = window.location.href.split('#'); let decoded; try { decoded = atob(decodeURIComponent(codeParam || '')); } catch (err) { console.warn('failed to decode', err); } const defaultSynth = new Tone.PolySynth().chain(new Tone.Gain(0.5), Tone.Destination); defaultSynth.set({ oscillator: { type: 'triangle' }, envelope: { release: 0.01, }, }); function getRandomTune() { const allTunes = Object.values(tunes); const randomItem = (arr: any[]) => arr[Math.floor(Math.random() * arr.length)]; return randomItem(allTunes); } const randomTune = getRandomTune(); function App() { const { setCode, setPattern, error, code, cycle, dirty, log, togglePlay } = useRepl({ tune: decoded || randomTune, defaultSynth, }); const logBox = useRef(); // scroll log box to bottom when log changes useLayoutEffect(() => { logBox.current.scrollTop = logBox.current?.scrollHeight; }, [log]); return (
logo

Strudel REPL

setCode(value)} /> {!cycle.started ? `press ctrl+enter to play\n` : dirty ? `ctrl+enter to update\n` : 'no changes\n'}
{error && (
{error?.message || 'unknown error'}
)}