aethex-studio/src/components/CodeEditor.tsx

105 lines
3.1 KiB
TypeScript

import Editor from '@monaco-editor/react';
import { usePersistentState } from '@/lib/usePersistentState';
import { useEffect, useMemo } from 'react';
import { LoadingSpinner } from './ui/loading-spinner';
import { toast } from 'sonner';
import { PlatformId } from '@/lib/platforms';
interface CodeEditorProps {
onCodeChange?: (code: string) => void;
platform?: PlatformId;
}
export function CodeEditor({ onCodeChange, platform = 'roblox' }: CodeEditorProps) {
const languageMap: Record<PlatformId, string> = useMemo(() => ({
roblox: 'lua',
uefn: 'plaintext', // Verse not yet supported by Monaco, use plaintext
spatial: 'typescript',
core: 'lua',
}), []);
const editorLanguage = languageMap[platform];
const [code, setCode] = usePersistentState('aethex-current-code', `-- Welcome to AeThex Studio!
-- Write your Roblox Lua code here
local Players = game:GetService("Players")
Players.PlayerAdded:Connect(function(player)
print(player.Name .. " joined the game!")
local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
leaderstats.Parent = player
local coins = Instance.new("IntValue")
coins.Name = "Coins"
coins.Value = 0
coins.Parent = leaderstats
end)
`);
useEffect(() => {
try {
if (onCodeChange && code) {
onCodeChange(code);
}
} catch (error) {
console.error('Failed to update code:', error);
}
}, [code, onCodeChange]);
const handleEditorChange = (value: string | undefined) => {
try {
setCode(value || '');
} catch (error) {
console.error('Failed to save code:', error);
toast.error('Failed to save changes. Please try again.');
}
};
const handleEditorMount = () => {
console.log('Monaco editor mounted successfully');
};
const handleEditorError = (error: Error) => {
console.error('Monaco editor error:', error);
toast.error('Editor failed to load. Please refresh the page.');
};
return (
<div className="h-full w-full bg-background border border-border shadow-md rounded-md flex flex-col">
<div className="flex-1 min-h-0">
<Editor
height="100%"
language={editorLanguage}
theme="vs-dark"
value={code}
onChange={handleEditorChange}
onMount={handleEditorMount}
loading={
<div className="h-full flex items-center justify-center">
<LoadingSpinner />
</div>
}
options={{
minimap: { enabled: typeof window !== 'undefined' && window.innerWidth >= 768 },
fontSize: 13,
lineNumbers: 'on',
automaticLayout: true,
scrollBeyondLastLine: false,
wordWrap: 'on',
fontFamily: 'JetBrains Mono, monospace',
fontLigatures: true,
cursorBlinking: 'smooth',
smoothScrolling: true,
padding: { top: 8, bottom: 8 },
scrollbar: {
verticalScrollbarSize: 6,
horizontalScrollbarSize: 6,
},
}}
/>
</div>
</div>
);
}