-
Notifications
You must be signed in to change notification settings - Fork 47
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
60a826b
commit 05117cd
Showing
2 changed files
with
132 additions
and
92 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
import * as React from 'react' | ||
import MonacoEditor, { Monaco } from '@monaco-editor/react' | ||
import { addKeyBinding, CustomKeyBinding } from '../utils' | ||
|
||
interface Props { | ||
initialCode: string | ||
languageLabel: string | ||
hideOutputEditor?: boolean | ||
isLoading?: boolean | ||
defaultLanguage?: string | ||
onRunCode(inputCode: string): Promise<string | void> | ||
children?: React.ReactNode | ||
} | ||
|
||
export default function Editor(props: Props) { | ||
const { | ||
initialCode, | ||
languageLabel, | ||
hideOutputEditor, | ||
isLoading = false, | ||
defaultLanguage, | ||
onRunCode, | ||
children, | ||
} = props | ||
|
||
const inputCodeRef = React.useRef(initialCode) | ||
const editorRef = React.useRef(null) | ||
|
||
const [monaco, setMonaco] = React.useState<Monaco>(null) | ||
const [output, setOutput] = React.useState('') | ||
|
||
async function runCode(code: string) { | ||
const output = await onRunCode(code) | ||
if (output) { | ||
setOutput(output) | ||
} | ||
} | ||
|
||
function handleEditorDidMount(editor: any, monaco: Monaco) { | ||
editorRef.current = editor | ||
setMonaco(monaco) | ||
} | ||
|
||
React.useEffect(() => { | ||
if (!monaco || isLoading) { | ||
return | ||
} | ||
const runCodeBinding: CustomKeyBinding = { | ||
label: 'run', | ||
keybinding: monaco.KeyMod.CtrlCmd | monaco.KeyCode.Enter, | ||
callback: () => runCode(inputCodeRef.current), | ||
editor: editorRef.current, | ||
} | ||
return addKeyBinding(runCodeBinding) | ||
}, [monaco, isLoading]) | ||
|
||
return ( | ||
<> | ||
<div> | ||
<div> | ||
<label className="block pb-4 text-sm font-medium text-gray-700 dark:text-gray-450"> | ||
{languageLabel} | ||
</label> | ||
|
||
<div className="mt-1 "> | ||
<div className="relative group"> | ||
<div className="absolute -inset-0.5 dark:bg-gradient-to-r from-indigo-300 to-purple-400 rounded-lg blur opacity-25 group-hover:opacity-100 transition duration-1000 group-hover:duration-200 animate-tilt" /> | ||
<MonacoEditor | ||
height="20rem" | ||
defaultLanguage={defaultLanguage} | ||
defaultValue={inputCodeRef.current} | ||
onChange={(value) => { | ||
inputCodeRef.current = value | ||
}} | ||
className="block w-1/2 text-white bg-gray-900 border-gray-300 rounded-lg shadow-sm p-0.5 border dark:border-purple-300 focus:ring-gray-500 focus:border-gray-500 sm:text-sm" | ||
theme="vs-dark" | ||
options={{ fontSize: 12 }} | ||
onMount={handleEditorDidMount} | ||
/> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
|
||
<div className="pt-8 "> | ||
<div className="grid items-start justify-left"> | ||
<div className="relative group"> | ||
<button | ||
className="relative flex items-center py-4 leading-none bg-black divide-x divide-gray-600 rounded-lg px-7 border-gray-300 disabled:bg-gray-700 disabled:cursor-not-allowed" | ||
onClick={() => runCode(inputCodeRef.current)} | ||
disabled={isLoading} | ||
> | ||
<span className="text-gray-100 transition duration-200 group-hover:text-gray-100"> | ||
{!isLoading ? 'Run Code →' : `Loading ${languageLabel}...`} | ||
</span> | ||
</button> | ||
</div> | ||
</div> | ||
</div> | ||
|
||
{children} | ||
|
||
{!hideOutputEditor && ( | ||
<div> | ||
<label className="block pt-8 text-sm font-medium text-gray-700 dark:text-gray-450"> | ||
Output | ||
</label> | ||
|
||
<div className="mt-1 dark:text-gray-450"> | ||
<MonacoEditor | ||
value={output?.toString()} | ||
height="20rem" | ||
defaultLanguage="python" | ||
className="block w-1/2 text-white bg-gray-900 border-gray-300 rounded-lg shadow-sm p-0.5 border dark:border-purple-300 focus:ring-gray-500 focus:border-gray-500 sm:text-sm" | ||
theme="vs-dark" | ||
options={{ readOnly: true }} | ||
/> | ||
</div> | ||
</div> | ||
)} | ||
</> | ||
) | ||
} |