minirepl optimizations:

- can now evaluate on init
- support disable-highlighting
- support keyboard shortcuts
- support flash
This commit is contained in:
Felix Roos 2022-07-28 23:55:05 +02:00
parent a42ebd7aaf
commit ce4d2c17a7
3 changed files with 64 additions and 16 deletions

File diff suppressed because one or more lines are too long

View file

@ -1,4 +1,4 @@
import React, { useState, useEffect, useCallback, useMemo, useRef } from 'react'; import React, { useState, useEffect, useCallback, useMemo, useRef, useLayoutEffect } from 'react';
import { CodeMirror as CodeMirror$1 } from 'react-codemirror6'; import { CodeMirror as CodeMirror$1 } from 'react-codemirror6';
import { EditorView, Decoration } from '@codemirror/view'; import { EditorView, Decoration } from '@codemirror/view';
import { StateEffect, StateField } from '@codemirror/state'; import { StateEffect, StateField } from '@codemirror/state';
@ -563,12 +563,16 @@ function Icon({ type }) {
}[type]); }[type]);
} }
function MiniRepl({ tune, defaultSynth, hideOutsideView = false }) { function MiniRepl({ tune, defaultSynth, hideOutsideView = false, theme, init, onEvent, enableKeyboard }) {
const { code, setCode, pattern, activateCode, error, cycle, dirty, togglePlay } = useRepl({ const { code, setCode, pattern, activeCode, activateCode, evaluateOnly, error, cycle, dirty, togglePlay, stop } = useRepl({
tune, tune,
defaultSynth, defaultSynth,
autolink: false autolink: false,
onEvent
}); });
useEffect(() => {
init && evaluateOnly();
}, [tune, init]);
const [view, setView] = useState(); const [view, setView] = useState();
const [ref, isVisible] = useInView({ const [ref, isVisible] = useInView({
threshold: 0.01 threshold: 0.01
@ -580,7 +584,25 @@ function MiniRepl({ tune, defaultSynth, hideOutsideView = false }) {
} }
return isVisible || wasVisible.current; return isVisible || wasVisible.current;
}, [isVisible, hideOutsideView]); }, [isVisible, hideOutsideView]);
useHighlighting({ view, pattern, active: cycle.started }); useHighlighting({ view, pattern, active: cycle.started && !activeCode?.includes("strudel disable-highlighting") });
useLayoutEffect(() => {
if (enableKeyboard) {
const handleKeyPress = async (e) => {
if (e.ctrlKey || e.altKey) {
if (e.code === "Enter") {
e.preventDefault();
flash(view);
await activateCode();
} else if (e.code === "Period") {
cycle.stop();
e.preventDefault();
}
}
};
window.addEventListener("keydown", handleKeyPress, true);
return () => window.removeEventListener("keydown", handleKeyPress, true);
}
}, [enableKeyboard, pattern, code, activateCode, cycle, view]);
return /* @__PURE__ */ React.createElement("div", { return /* @__PURE__ */ React.createElement("div", {
className: styles.container, className: styles.container,
ref ref

View file

@ -1,20 +1,25 @@
import React, { useState, useMemo, useRef } from 'react'; import React, { useState, useMemo, useRef, useEffect, useLayoutEffect } from 'react';
import { useInView } from 'react-hook-inview'; import { useInView } from 'react-hook-inview';
import useRepl from '../hooks/useRepl.mjs'; import useRepl from '../hooks/useRepl.mjs';
import cx from '../cx'; import cx from '../cx';
import useHighlighting from '../hooks/useHighlighting.mjs'; import useHighlighting from '../hooks/useHighlighting.mjs';
import CodeMirror6 from './CodeMirror6'; import CodeMirror6, { flash } from './CodeMirror6';
import 'tailwindcss/tailwind.css'; import 'tailwindcss/tailwind.css';
import './style.css'; import './style.css';
import styles from './MiniRepl.module.css'; import styles from './MiniRepl.module.css';
import { Icon } from './Icon'; import { Icon } from './Icon';
export function MiniRepl({ tune, defaultSynth, hideOutsideView = false }) { export function MiniRepl({ tune, defaultSynth, hideOutsideView = false, theme, init, onEvent, enableKeyboard }) {
const { code, setCode, pattern, activateCode, error, cycle, dirty, togglePlay } = useRepl({ const { code, setCode, pattern, activeCode, activateCode, evaluateOnly, error, cycle, dirty, togglePlay, stop } =
tune, useRepl({
defaultSynth, tune,
autolink: false, defaultSynth,
}); autolink: false,
onEvent,
});
useEffect(() => {
init && evaluateOnly();
}, [tune, init]);
const [view, setView] = useState(); const [view, setView] = useState();
const [ref, isVisible] = useInView({ const [ref, isVisible] = useInView({
threshold: 0.01, threshold: 0.01,
@ -26,7 +31,28 @@ export function MiniRepl({ tune, defaultSynth, hideOutsideView = false }) {
} }
return isVisible || wasVisible.current; return isVisible || wasVisible.current;
}, [isVisible, hideOutsideView]); }, [isVisible, hideOutsideView]);
useHighlighting({ view, pattern, active: cycle.started }); useHighlighting({ view, pattern, active: cycle.started && !activeCode?.includes('strudel disable-highlighting') });
// set active pattern on ctrl+enter
useLayoutEffect(() => {
if (enableKeyboard) {
const handleKeyPress = async (e) => {
if (e.ctrlKey || e.altKey) {
if (e.code === 'Enter') {
e.preventDefault();
flash(view);
await activateCode();
} else if (e.code === 'Period') {
cycle.stop();
e.preventDefault();
}
}
};
window.addEventListener('keydown', handleKeyPress, true);
return () => window.removeEventListener('keydown', handleKeyPress, true);
}
}, [enableKeyboard, pattern, code, activateCode, cycle, view]);
return ( return (
<div className={styles.container} ref={ref}> <div className={styles.container} ref={ref}>
<div className={styles.header}> <div className={styles.header}>