60 lines
1.7 KiB
TypeScript
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>
|
|
);
|
|
}
|