Next.js 16, React 19, Monaco editor, Anthropic SDK, multi-provider AI, Wandbox Python execution, iframe HTML preview, SQLite auth + session persistence. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
74 lines
2.2 KiB
TypeScript
74 lines
2.2 KiB
TypeScript
'use client';
|
|
|
|
import type { Dispatch } from 'react';
|
|
import type { AppState, AppAction } from '@/types';
|
|
import { useCodeExecution } from '@/hooks/useCodeExecution';
|
|
import CodeEditor from './CodeEditor';
|
|
import EditorToolbar from './EditorToolbar';
|
|
import OutputPanel from './OutputPanel';
|
|
import HtmlPreview from './HtmlPreview';
|
|
|
|
interface Props {
|
|
state: AppState;
|
|
dispatch: Dispatch<AppAction>;
|
|
providerLabel: string;
|
|
onSubmit: () => void;
|
|
onReset: () => void;
|
|
onOpenSettings: () => void;
|
|
savedIndicator: boolean;
|
|
authUser: { id: string; email: string } | null;
|
|
onShowAuth: () => void;
|
|
onLogout: () => void;
|
|
}
|
|
|
|
export default function EditorPane({ state, dispatch, providerLabel, onSubmit, onReset, onOpenSettings, savedIndicator, authUser, onShowAuth, onLogout }: Props) {
|
|
const { execute } = useCodeExecution(dispatch);
|
|
const language = state.topic!.language;
|
|
|
|
function handleRun() {
|
|
execute(language, state.code);
|
|
}
|
|
|
|
return (
|
|
<div className="flex flex-col h-full bg-[#1e1e1e]">
|
|
<EditorToolbar
|
|
language={language}
|
|
providerLabel={providerLabel}
|
|
isExecuting={state.phase === 'executing'}
|
|
isStreaming={state.isStreaming}
|
|
onRun={handleRun}
|
|
onSubmit={onSubmit}
|
|
onReset={onReset}
|
|
onOpenSettings={onOpenSettings}
|
|
savedIndicator={savedIndicator}
|
|
authUser={authUser}
|
|
onShowAuth={onShowAuth}
|
|
onLogout={onLogout}
|
|
responseMode={state.responseMode}
|
|
onToggleHintMode={() =>
|
|
dispatch({ type: 'SET_RESPONSE_MODE', payload: { hintMode: !state.responseMode.hintMode } })
|
|
}
|
|
onToggleStrict={() =>
|
|
dispatch({ type: 'SET_RESPONSE_MODE', payload: { strict: !state.responseMode.strict } })
|
|
}
|
|
/>
|
|
|
|
<div className="flex-1 min-h-0">
|
|
<CodeEditor
|
|
language={language}
|
|
value={state.code}
|
|
onChange={(val) => dispatch({ type: 'CODE_CHANGE', payload: val })}
|
|
height="100%"
|
|
/>
|
|
</div>
|
|
|
|
{language === 'html' && <HtmlPreview code={state.code} />}
|
|
|
|
<OutputPanel
|
|
result={state.executionResult}
|
|
isLoading={state.phase === 'executing'}
|
|
/>
|
|
</div>
|
|
);
|
|
}
|