105 lines
3.1 KiB
TypeScript
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>
|
|
);
|
|
}
|