diff --git a/packages/react/src/components/CodeMirror6.jsx b/packages/react/src/components/CodeMirror6.jsx index 1dbc1066..eb02004a 100644 --- a/packages/react/src/components/CodeMirror6.jsx +++ b/packages/react/src/components/CodeMirror6.jsx @@ -49,11 +49,12 @@ const highlightField = StateField.define({ try { for (let e of tr.effects) { if (e.is(setHighlights)) { + const { haps } = e.value; const marks = - e.value + haps .map((hap) => (hap.context.locations || []).map(({ start, end }) => { - const color = hap.context.color || '#FFCA28'; + const color = hap.context.color || e.value.color || '#FFCA28'; let from = tr.newDoc.line(start.line).from + start.column; let to = tr.newDoc.line(end.line).from + end.column; const l = tr.newDoc.length; diff --git a/packages/react/src/components/MiniRepl.jsx b/packages/react/src/components/MiniRepl.jsx index 4649969a..508353e4 100644 --- a/packages/react/src/components/MiniRepl.jsx +++ b/packages/react/src/components/MiniRepl.jsx @@ -10,6 +10,7 @@ import { Icon } from './Icon'; import styles from './MiniRepl.module.css'; import './style.css'; import { logger } from '@strudel.cycles/core'; +import useEvent from '../hooks/useEvent.mjs'; const getTime = () => getAudioContext().currentTime; @@ -21,6 +22,7 @@ export function MiniRepl({ punchcard, canvasHeight = 200, theme, + highlightColor, }) { drawTime = drawTime || (punchcard ? [0, 4] : undefined); const evalOnMount = !!drawTime; @@ -69,6 +71,7 @@ export function MiniRepl({ pattern, active: started && !activeCode?.includes('strudel disable-highlighting'), getTime: () => scheduler.now(), + color: highlightColor, }); // set active pattern on ctrl+enter @@ -148,13 +151,3 @@ export function MiniRepl({ function useLogger(onTrigger) { useEvent(logger.key, onTrigger); } - -// TODO: dedupe -function useEvent(name, onTrigger, useCapture = false) { - useEffect(() => { - document.addEventListener(name, onTrigger, useCapture); - return () => { - document.removeEventListener(name, onTrigger, useCapture); - }; - }, [onTrigger]); -} diff --git a/packages/react/src/hooks/useEvent.mjs b/packages/react/src/hooks/useEvent.mjs new file mode 100644 index 00000000..f349c6e7 --- /dev/null +++ b/packages/react/src/hooks/useEvent.mjs @@ -0,0 +1,12 @@ +import { useEffect } from 'react'; + +function useEvent(name, onTrigger, useCapture = false) { + useEffect(() => { + document.addEventListener(name, onTrigger, useCapture); + return () => { + document.removeEventListener(name, onTrigger, useCapture); + }; + }, [onTrigger]); +} + +export default useEvent; diff --git a/packages/react/src/hooks/useHighlighting.mjs b/packages/react/src/hooks/useHighlighting.mjs index 1b7a2ced..84262583 100644 --- a/packages/react/src/hooks/useHighlighting.mjs +++ b/packages/react/src/hooks/useHighlighting.mjs @@ -1,7 +1,7 @@ import { useEffect, useRef } from 'react'; import { setHighlights } from '../components/CodeMirror6'; -function useHighlighting({ view, pattern, active, getTime }) { +function useHighlighting({ view, pattern, active, getTime, color }) { const highlights = useRef([]); const lastEnd = useRef(0); useEffect(() => { @@ -19,9 +19,9 @@ function useHighlighting({ view, pattern, active, getTime }) { highlights.current = highlights.current.filter((hap) => hap.whole.end > audioTime); // keep only highlights that are still active const haps = pattern.queryArc(...span).filter((hap) => hap.hasOnset()); highlights.current = highlights.current.concat(haps); // add potential new onsets - view.dispatch({ effects: setHighlights.of(highlights.current) }); // highlight all still active + new active haps + view.dispatch({ effects: setHighlights.of({ haps: highlights.current, color }) }); // highlight all still active + new active haps } catch (err) { - view.dispatch({ effects: setHighlights.of([]) }); + view.dispatch({ effects: setHighlights.of({ haps: [] }) }); } frame = requestAnimationFrame(updateHighlights); }); @@ -30,10 +30,10 @@ function useHighlighting({ view, pattern, active, getTime }) { }; } else { highlights.current = []; - view.dispatch({ effects: setHighlights.of([]) }); + view.dispatch({ effects: setHighlights.of({ haps: [] }) }); } } - }, [pattern, active, view]); + }, [pattern, active, view, color]); } export default useHighlighting; diff --git a/packages/react/src/index.js b/packages/react/src/index.js index 40b9fa8d..f9eca1cd 100644 --- a/packages/react/src/index.js +++ b/packages/react/src/index.js @@ -1,10 +1,11 @@ // import 'tailwindcss/tailwind.css'; -export { default as CodeMirror, flash } from './components/CodeMirror6'; -export * from './components/MiniRepl'; -export { default as useHighlighting } from './hooks/useHighlighting'; +export { default as CodeMirror, flash } from './components/CodeMirror6'; // !SSR +export * from './components/MiniRepl'; // !SSR +export { default as useHighlighting } from './hooks/useHighlighting'; // !SSR +export { default as useStrudel } from './hooks/useStrudel'; // !SSR export { default as usePostMessage } from './hooks/usePostMessage'; -export { default as useStrudel } from './hooks/useStrudel'; export { default as useKeydown } from './hooks/useKeydown'; +export { default as useEvent } from './hooks/useEvent'; export { default as strudelTheme } from './themes/strudel-theme'; export { default as cx } from './cx'; diff --git a/website/src/docs/MiniRepl.jsx b/website/src/docs/MiniRepl.jsx index 33aa4523..f3e83d99 100644 --- a/website/src/docs/MiniRepl.jsx +++ b/website/src/docs/MiniRepl.jsx @@ -2,7 +2,7 @@ import { evalScope, controls } from '@strudel.cycles/core'; import { initAudioOnFirstClick } from '@strudel.cycles/webaudio'; import { useEffect, useState } from 'react'; import { prebake } from '../repl/prebake'; -import { themes } from '../repl/themes.mjs'; +import { themes, settings } from '../repl/themes.mjs'; import './MiniRepl.css'; const theme = localStorage.getItem('strudel-theme') || 'strudelTheme'; @@ -36,6 +36,7 @@ export function MiniRepl({ tune, drawTime, punchcard, canvasHeight = 100 }) { .then(([res]) => setRepl(() => res.MiniRepl)) .catch((err) => console.error(err)); }, []); + // const { settings } = useTheme(); return Repl ? (