import { useState, useRef, useCallback, useMemo, useEffect } from 'react'; import { Icon } from './Icon'; import { silence, getPunchcardPainter, noteToMidi } from '@strudel/core'; import { transpiler } from '@strudel/transpiler'; import { getAudioContext, webaudioOutput } from '@strudel/webaudio'; import { StrudelMirror } from '@strudel/codemirror'; // import { prebake } from '@strudel/repl'; import { prebake } from '../repl/prebake.mjs'; import { loadModules } from '../repl/util.mjs'; import Claviature from '@components/Claviature'; import useClient from '@src/useClient.mjs'; let prebaked, modulesLoading; if (typeof window !== 'undefined') { prebaked = prebake(); modulesLoading = loadModules(); } export function MiniRepl({ tune: code, hideHeader = false, canvasHeight = 100, onTrigger, punchcard, punchcardLabels = true, claviature, claviatureLabels, }) { const id = useMemo(() => s4(), []); const canvasId = useMemo(() => `canvas-${id}`, [id]); const shouldDraw = !!punchcard || !!claviature; const shouldShowCanvas = !!punchcard; const drawTime = punchcard ? [0, 4] : [0, 0]; const [activeNotes, setActiveNotes] = useState([]); const init = useCallback(({ code, shouldDraw }) => { const drawContext = shouldDraw ? document.querySelector('#' + canvasId)?.getContext('2d') : null; let onDraw; if (shouldDraw) { onDraw = (haps, time, frame, painters) => { painters.length && drawContext?.clearRect(0, 0, drawContext.canvas.width * 2, drawContext.canvas.height * 2); painters?.forEach((painter) => { // ctx time haps drawTime paintOptions painter(drawContext, time, haps, drawTime, { clear: false }); }); }; } const editor = new StrudelMirror({ id, defaultOutput: webaudioOutput, getTime: () => getAudioContext().currentTime, transpiler, autodraw: !!shouldDraw, root: containerRef.current, initialCode: '// LOADING', pattern: silence, drawTime, onDraw, editPattern: (pat, id) => { if (onTrigger) { pat = pat.onTrigger(onTrigger, false); } if (claviature) { editor?.painters.push((ctx, time, haps, drawTime) => { const active = haps .map((hap) => hap.value.note) .filter(Boolean) .map((n) => (typeof n === 'string' ? noteToMidi(n) : n)); setActiveNotes(active); }); } if (punchcard) { editor?.painters.push(getPunchcardPainter({ labels: !!punchcardLabels })); } return pat; }, prebake: async () => Promise.all([modulesLoading, prebaked]), onUpdateState: (state) => { setReplState({ ...state }); }, }); // init settings editor.setCode(code); editorRef.current = editor; }, []); const [replState, setReplState] = useState({}); const { started, isDirty, error } = replState; const editorRef = useRef(); const containerRef = useRef(); const client = useClient(); if (!client) { return
{code};
}
return (