├── README.md
├── index.html
├── package-lock.json
├── package.json
├── public
└── vite.svg
├── src
├── App.jsx
├── api.js
├── components
│ ├── CodeEditor.jsx
│ ├── LanguageSelector.jsx
│ └── Output.jsx
├── constants.js
├── main.jsx
└── theme.js
└── vite.config.js
/README.md:
--------------------------------------------------------------------------------
1 | # React + Vite
2 |
3 | An in-browser code editor that allows you to write and execute your code in the browser.
4 |
5 | ## Run Locally
6 |
7 | ```bash
8 | # install dependencies
9 |
10 | npm install
11 |
12 | # start the dev server
13 |
14 | npm run dev
15 | ```
16 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Vite + React
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-code-editor",
3 | "private": true,
4 | "version": "0.0.0",
5 | "type": "module",
6 | "scripts": {
7 | "dev": "vite",
8 | "build": "vite build",
9 | "lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0",
10 | "preview": "vite preview"
11 | },
12 | "dependencies": {
13 | "@chakra-ui/react": "^2.8.2",
14 | "@emotion/react": "^11.11.3",
15 | "@emotion/styled": "^11.11.0",
16 | "@monaco-editor/react": "^4.6.0",
17 | "axios": "^1.6.7",
18 | "framer-motion": "^11.0.3",
19 | "react": "^18.2.0",
20 | "react-dom": "^18.2.0"
21 | },
22 | "devDependencies": {
23 | "@types/react": "^18.2.43",
24 | "@types/react-dom": "^18.2.17",
25 | "@vitejs/plugin-react": "^4.2.1",
26 | "eslint": "^8.55.0",
27 | "eslint-plugin-react": "^7.33.2",
28 | "eslint-plugin-react-hooks": "^4.6.0",
29 | "eslint-plugin-react-refresh": "^0.4.5",
30 | "vite": "^5.0.8"
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/public/vite.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/App.jsx:
--------------------------------------------------------------------------------
1 | import { Box } from "@chakra-ui/react";
2 | import CodeEditor from "./components/CodeEditor";
3 |
4 | function App() {
5 | return (
6 |
7 |
8 |
9 | );
10 | }
11 |
12 | export default App;
13 |
--------------------------------------------------------------------------------
/src/api.js:
--------------------------------------------------------------------------------
1 | import axios from "axios";
2 | import { LANGUAGE_VERSIONS } from "./constants";
3 |
4 | const API = axios.create({
5 | baseURL: "https://emkc.org/api/v2/piston",
6 | });
7 |
8 | export const executeCode = async (language, sourceCode) => {
9 | const response = await API.post("/execute", {
10 | language: language,
11 | version: LANGUAGE_VERSIONS[language],
12 | files: [
13 | {
14 | content: sourceCode,
15 | },
16 | ],
17 | });
18 | return response.data;
19 | };
20 |
--------------------------------------------------------------------------------
/src/components/CodeEditor.jsx:
--------------------------------------------------------------------------------
1 | import { useRef, useState } from "react";
2 | import { Box, HStack } from "@chakra-ui/react";
3 | import { Editor } from "@monaco-editor/react";
4 | import LanguageSelector from "./LanguageSelector";
5 | import { CODE_SNIPPETS } from "../constants";
6 | import Output from "./Output";
7 |
8 | const CodeEditor = () => {
9 | const editorRef = useRef();
10 | const [value, setValue] = useState("");
11 | const [language, setLanguage] = useState("javascript");
12 |
13 | const onMount = (editor) => {
14 | editorRef.current = editor;
15 | editor.focus();
16 | };
17 |
18 | const onSelect = (language) => {
19 | setLanguage(language);
20 | setValue(CODE_SNIPPETS[language]);
21 | };
22 |
23 | return (
24 |
25 |
26 |
27 |
28 | setValue(value)}
41 | />
42 |
43 |
44 |
45 |
46 | );
47 | };
48 | export default CodeEditor;
49 |
--------------------------------------------------------------------------------
/src/components/LanguageSelector.jsx:
--------------------------------------------------------------------------------
1 | import {
2 | Box,
3 | Button,
4 | Menu,
5 | MenuButton,
6 | MenuItem,
7 | MenuList,
8 | Text,
9 | } from "@chakra-ui/react";
10 | import { LANGUAGE_VERSIONS } from "../constants";
11 |
12 | const languages = Object.entries(LANGUAGE_VERSIONS);
13 | const ACTIVE_COLOR = "blue.400";
14 |
15 | const LanguageSelector = ({ language, onSelect }) => {
16 | return (
17 |
18 |
19 | Language:
20 |
21 |
44 |
45 | );
46 | };
47 | export default LanguageSelector;
48 |
--------------------------------------------------------------------------------
/src/components/Output.jsx:
--------------------------------------------------------------------------------
1 | import { useState } from "react";
2 | import { Box, Button, Text, useToast } from "@chakra-ui/react";
3 | import { executeCode } from "../api";
4 |
5 | const Output = ({ editorRef, language }) => {
6 | const toast = useToast();
7 | const [output, setOutput] = useState(null);
8 | const [isLoading, setIsLoading] = useState(false);
9 | const [isError, setIsError] = useState(false);
10 |
11 | const runCode = async () => {
12 | const sourceCode = editorRef.current.getValue();
13 | if (!sourceCode) return;
14 | try {
15 | setIsLoading(true);
16 | const { run: result } = await executeCode(language, sourceCode);
17 | setOutput(result.output.split("\n"));
18 | result.stderr ? setIsError(true) : setIsError(false);
19 | } catch (error) {
20 | console.log(error);
21 | toast({
22 | title: "An error occurred.",
23 | description: error.message || "Unable to run code",
24 | status: "error",
25 | duration: 6000,
26 | });
27 | } finally {
28 | setIsLoading(false);
29 | }
30 | };
31 |
32 | return (
33 |
34 |
35 | Output
36 |
37 |
46 |
54 | {output
55 | ? output.map((line, i) => {line})
56 | : 'Click "Run Code" to see the output here'}
57 |
58 |
59 | );
60 | };
61 | export default Output;
62 |
--------------------------------------------------------------------------------
/src/constants.js:
--------------------------------------------------------------------------------
1 | export const LANGUAGE_VERSIONS = {
2 | javascript: "18.15.0",
3 | typescript: "5.0.3",
4 | python: "3.10.0",
5 | java: "15.0.2",
6 | csharp: "6.12.0",
7 | php: "8.2.3",
8 | };
9 |
10 | export const CODE_SNIPPETS = {
11 | javascript: `\nfunction greet(name) {\n\tconsole.log("Hello, " + name + "!");\n}\n\ngreet("Alex");\n`,
12 | typescript: `\ntype Params = {\n\tname: string;\n}\n\nfunction greet(data: Params) {\n\tconsole.log("Hello, " + data.name + "!");\n}\n\ngreet({ name: "Alex" });\n`,
13 | python: `\ndef greet(name):\n\tprint("Hello, " + name + "!")\n\ngreet("Alex")\n`,
14 | java: `\npublic class HelloWorld {\n\tpublic static void main(String[] args) {\n\t\tSystem.out.println("Hello World");\n\t}\n}\n`,
15 | csharp:
16 | 'using System;\n\nnamespace HelloWorld\n{\n\tclass Hello { \n\t\tstatic void Main(string[] args) {\n\t\t\tConsole.WriteLine("Hello World in C#");\n\t\t}\n\t}\n}\n',
17 | php: "
9 |
10 |
11 |
12 |
13 | );
14 |
--------------------------------------------------------------------------------
/src/theme.js:
--------------------------------------------------------------------------------
1 | import { extendTheme } from "@chakra-ui/react";
2 |
3 | const theme = extendTheme({
4 | config: {
5 | initialColorMode: "dark",
6 | useSystemColorMode: false,
7 | },
8 | });
9 | export default theme;
10 |
--------------------------------------------------------------------------------
/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite'
2 | import react from '@vitejs/plugin-react'
3 |
4 | // https://vitejs.dev/config/
5 | export default defineConfig({
6 | plugins: [react()],
7 | })
8 |
--------------------------------------------------------------------------------