Files
bitfielder/src/components/EditorPanel.tsx

60 lines
1.7 KiB
TypeScript

import { useState, useEffect } from 'react';
import { useStore } from '@nanostores/react';
import { $shader, setShaderCode } from '../stores/shader';
interface EditorPanelProps {
minimal?: boolean;
}
export function EditorPanel({ minimal = false }: EditorPanelProps) {
const shader = useStore($shader);
// const ui = useStore(uiState); // Unused for now
const [localCode, setLocalCode] = useState(shader.code);
// Check if code has changed from the compiled version
const hasChanges = localCode !== shader.code;
const handleCodeChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
// Only update local state, don't compile until eval
setLocalCode(e.target.value);
};
// Sync local code when shader code changes externally (e.g., from library)
useEffect(() => {
setLocalCode(shader.code);
}, [shader.code]);
const handleEval = () => {
// Compile and render the shader
setShaderCode(localCode);
};
const handleKeyDown = (e: React.KeyboardEvent) => {
if ((e.ctrlKey || e.metaKey) && e.key === 'Enter') {
e.preventDefault();
handleEval();
}
};
return (
<div id="editor-panel" className={minimal ? 'minimal' : ''}>
<textarea
id="editor"
className={minimal ? 'minimal' : ''}
value={localCode}
onChange={handleCodeChange}
onKeyDown={handleKeyDown}
placeholder="Enter shader code... (x, y, t, i, bpm, mouseX, mouseY, mousePressed, touchCount, accelX, audioLevel, bassLevel...)"
spellCheck={false}
/>
<button
id="eval-btn"
className={minimal ? 'minimal' : ''}
onClick={handleEval}
>
{hasChanges ? 'Eval *' : 'Eval'}
</button>
</div>
);
}