Added Layout to the editor page
This commit is contained in:
parent
c82b287c8a
commit
c5e00165dd
|
@ -0,0 +1,32 @@
|
|||
import React from "react";
|
||||
import { EventEmitter } from "../utils/EventEmitter";
|
||||
import Split from "react-split";
|
||||
|
||||
const Layouts = (props) => {
|
||||
const { splitType, children } = props;
|
||||
return (
|
||||
<>
|
||||
<Split
|
||||
className="split"
|
||||
minSize={0}
|
||||
snapOffset={0}
|
||||
expandToMin={false}
|
||||
gutterSize={10}
|
||||
gutterAlign="center"
|
||||
dragInterval={1}
|
||||
direction={splitType}
|
||||
style={{
|
||||
flexGrow: 1,
|
||||
...(splitType === "horizontal"
|
||||
? { display: "flex", flexDirection: "row", alignItems: "stretch" }
|
||||
: {}),
|
||||
}}
|
||||
onDragEnd={() => EventEmitter.dispatch("resize")}
|
||||
>
|
||||
{children}
|
||||
</Split>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default Layouts;
|
|
@ -19,6 +19,9 @@ function RijuTerminal() {
|
|||
term.loadAddon(fitAddon);
|
||||
|
||||
window.addEventListener("resize", () => fitAddon.fit());
|
||||
EventEmitter.subscribe("resize", () => {
|
||||
fitAddon.fit();
|
||||
});
|
||||
EventEmitter.subscribe("terminal", (payload) => {
|
||||
if (!payload) return;
|
||||
const { type, data } = payload;
|
||||
|
@ -40,7 +43,14 @@ function RijuTerminal() {
|
|||
}, []);
|
||||
|
||||
return (
|
||||
<Box id="riju-term" sx={{ height: `calc(100% - 8px)`, mt: 1, ml: 2 }} />
|
||||
<Box
|
||||
id="riju-term"
|
||||
sx={{
|
||||
height: "100%",
|
||||
width: "100%",
|
||||
backgroundColor: "#292D3E",
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,13 +1,30 @@
|
|||
import MonacoEditor, { useMonaco } from "@monaco-editor/react";
|
||||
import { Circle, Code as Format, Home, PlayArrow } from "@mui/icons-material";
|
||||
import {
|
||||
Circle,
|
||||
Code as Format,
|
||||
Home,
|
||||
HorizontalSplit,
|
||||
PlayArrow,
|
||||
VerticalSplit,
|
||||
} from "@mui/icons-material";
|
||||
import { LoadingButton } from "@mui/lab";
|
||||
import { Box, Button, Chip, Divider, Typography } from "@mui/material";
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
Chip,
|
||||
Divider,
|
||||
Stack,
|
||||
ToggleButton,
|
||||
ToggleButtonGroup,
|
||||
Typography,
|
||||
} from "@mui/material";
|
||||
import ansi from "ansicolor";
|
||||
import dynamic from "next/dynamic";
|
||||
import Head from "next/head";
|
||||
import { useRouter } from "next/router";
|
||||
import React, { useEffect, useRef, useState } from "react";
|
||||
import { createMessageConnection } from "vscode-jsonrpc";
|
||||
import Layouts from "../../components/Layouts";
|
||||
import langs from "../../static/langs.json";
|
||||
import { EventEmitter } from "../../utils/EventEmitter";
|
||||
ansi.rgb = {
|
||||
|
@ -27,12 +44,14 @@ const CodeRunner = (props) => {
|
|||
const router = useRouter();
|
||||
const { langConfig } = props;
|
||||
const editorRef = useRef(null);
|
||||
const paneRef = useRef(null);
|
||||
const [config, setConfig] = useState(langConfig);
|
||||
const [mounted, setMounted] = useState(false);
|
||||
const [isRunning, setRunning] = useState(false);
|
||||
const [isFormatting, setFormatting] = useState(false);
|
||||
const [isLspStarted, setLspStarted] = useState(false);
|
||||
const [isLspRequested, setIsLspRequested] = useState(false);
|
||||
const [splitType, setSplitType] = useState("horizontal");
|
||||
const monaco = useMonaco();
|
||||
const [status, setStatus] = useState("connecting");
|
||||
|
||||
|
@ -233,8 +252,6 @@ const CodeRunner = (props) => {
|
|||
case "lsp":
|
||||
setLspStarted(false);
|
||||
setIsLspRequested(false);
|
||||
// lspButton.classList.add("is-light");
|
||||
// lspButtonState.innerText = "CRASHED";
|
||||
break;
|
||||
case "terminal":
|
||||
sendToTerminal(
|
||||
|
@ -307,13 +324,42 @@ const CodeRunner = (props) => {
|
|||
showValue();
|
||||
},
|
||||
});
|
||||
// editor.getModel().onDidChangeContent(() => recordActivity());
|
||||
// window.addEventListener("resize", () => editor.layout());
|
||||
editor.getModel().setValue(config.template + "\n");
|
||||
monaco.editor.setModelLanguage(
|
||||
editor.getModel(),
|
||||
config.monacoLang || "plaintext"
|
||||
);
|
||||
// Below code is just for adding an empty line in editor
|
||||
monaco.languages.registerCodeLensProvider(
|
||||
config.monacoLang || "plaintext",
|
||||
{
|
||||
provideCodeLenses: function (model, token) {
|
||||
return {
|
||||
lenses: [
|
||||
{
|
||||
range: {
|
||||
startLineNumber: 1,
|
||||
startColumn: 1,
|
||||
endLineNumber: 2,
|
||||
endColumn: 1,
|
||||
},
|
||||
id: "Format",
|
||||
command: {
|
||||
// id: commandId,
|
||||
// title: "Format",
|
||||
title: "",
|
||||
},
|
||||
},
|
||||
],
|
||||
dispose: () => {},
|
||||
};
|
||||
},
|
||||
resolveCodeLens: function (model, codeLens, token) {
|
||||
return codeLens;
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
setMounted(true);
|
||||
}
|
||||
|
||||
|
@ -338,6 +384,17 @@ const CodeRunner = (props) => {
|
|||
}
|
||||
};
|
||||
|
||||
const handleLayout = (event, value) => {
|
||||
const e = document.querySelector(".split .gutter");
|
||||
e.classList.replace(`gutter-${splitType}`, `gutter-${value}`);
|
||||
const es = document.querySelectorAll(".split .panel");
|
||||
for (const e of es) {
|
||||
e.removeAttribute("style");
|
||||
e.removeAttribute("style");
|
||||
}
|
||||
setSplitType(value);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
|
@ -352,25 +409,20 @@ const CodeRunner = (props) => {
|
|||
content="minimum-scale=1, initial-scale=1, width=device-width"
|
||||
/>
|
||||
</Head>
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
height: "100vh",
|
||||
bgcolor: "#fff",
|
||||
}}
|
||||
component="main"
|
||||
<Stack
|
||||
direction="column"
|
||||
sx={{ height: "100vh", bgcolor: "white" }}
|
||||
alignItems="stretch"
|
||||
>
|
||||
<Box
|
||||
<Stack
|
||||
direction="row"
|
||||
alignItems="stretch"
|
||||
sx={{
|
||||
display: "flex",
|
||||
flexDirection: "row",
|
||||
alignItems: "stretch",
|
||||
boxShadow: `0 2px 4px rgb(0 0 0 / 2%)`,
|
||||
width: "60%",
|
||||
boxShadow: `0 2px 4px rgb(0 0 0 / 10%)`,
|
||||
zIndex: (t) => t.zIndex.appBar,
|
||||
}}
|
||||
>
|
||||
<Box sx={{ flexGrow: 1, display: "flex", alignItems: "center" }}>
|
||||
<Stack direction="row" sx={{ flexGrow: 1 }} alignItems="stretch">
|
||||
<Button
|
||||
variant="contained"
|
||||
sx={{ borderRadius: 0, minWidth: 0 }}
|
||||
|
@ -383,7 +435,10 @@ const CodeRunner = (props) => {
|
|||
>
|
||||
<Home fontSize={"small"} />
|
||||
</Button>
|
||||
<Typography sx={{ fontSize: 14, px: 2, fontWeight: 600 }}>
|
||||
<Typography
|
||||
sx={{ fontSize: 14, px: 2, fontWeight: 600, alignSelf: "center" }}
|
||||
textAlign="center"
|
||||
>
|
||||
{config.name}
|
||||
</Typography>
|
||||
<Chip
|
||||
|
@ -397,7 +452,7 @@ const CodeRunner = (props) => {
|
|||
}}
|
||||
label={status}
|
||||
/>
|
||||
</Box>
|
||||
</Stack>
|
||||
<LoadingButton
|
||||
onClick={handleLspClick}
|
||||
size="small"
|
||||
|
@ -423,6 +478,31 @@ const CodeRunner = (props) => {
|
|||
>
|
||||
<Typography sx={{ fontSize: 12 }}>Autocomplete</Typography>
|
||||
</LoadingButton>
|
||||
<ToggleButtonGroup
|
||||
size="small"
|
||||
value={splitType}
|
||||
color="primary"
|
||||
exclusive
|
||||
onChange={handleLayout}
|
||||
aria-label="split type"
|
||||
sx={{ mr: 1 }}
|
||||
>
|
||||
<ToggleButton
|
||||
value="vertical"
|
||||
aria-label="vertical split"
|
||||
sx={{ borderRadius: 0 }}
|
||||
>
|
||||
<VerticalSplit fontSize="small" />
|
||||
</ToggleButton>
|
||||
<ToggleButton
|
||||
value="horizontal"
|
||||
aria-label="horizontal split"
|
||||
sx={{ borderRadius: 0 }}
|
||||
>
|
||||
<HorizontalSplit fontSize="small" />
|
||||
</ToggleButton>
|
||||
</ToggleButtonGroup>
|
||||
|
||||
<LoadingButton
|
||||
onClick={sendFormat}
|
||||
loading={isFormatting}
|
||||
|
@ -451,26 +531,17 @@ const CodeRunner = (props) => {
|
|||
>
|
||||
<Typography sx={{ fontSize: 12, color: "#fff" }}>Run</Typography>
|
||||
</LoadingButton>
|
||||
</Box>
|
||||
<Divider />
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
flexDirection: "row",
|
||||
flexGrow: 1,
|
||||
alignItems: "stretch",
|
||||
}}
|
||||
>
|
||||
<Box sx={{ backgroundColor: "white", width: "60%" }}>
|
||||
<Box
|
||||
component={MonacoEditor}
|
||||
</Stack>
|
||||
<Layouts splitType={splitType}>
|
||||
<Box className="panel editor">
|
||||
<MonacoEditor
|
||||
wrapperClassName={"rijuEditor"}
|
||||
onChange={handleChange}
|
||||
height="90vh"
|
||||
// height="100vh"
|
||||
defaultLanguage="javascript"
|
||||
defaultValue="// some comment"
|
||||
options={{
|
||||
minimap: { enabled: false },
|
||||
minimap: { enabled: splitType == "horizontal" ? false : true },
|
||||
scrollbar: { verticalScrollbarSize: 0 },
|
||||
fontLigatures: true,
|
||||
fontFamily: "Fira Code",
|
||||
|
@ -478,17 +549,11 @@ const CodeRunner = (props) => {
|
|||
onMount={editorDidMount}
|
||||
/>
|
||||
</Box>
|
||||
<Box
|
||||
sx={{
|
||||
overflow: "hidden",
|
||||
backgroundColor: "#292D3E",
|
||||
width: "40%",
|
||||
}}
|
||||
>
|
||||
<Box className="panel" sx={{ bgcolor: "#292D3E", p: 2 }}>
|
||||
<RijuTerminal />
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
</Layouts>
|
||||
</Stack>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -1,121 +0,0 @@
|
|||
.container {
|
||||
min-height: 100vh;
|
||||
padding: 0 0.5rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
.main {
|
||||
padding: 5rem 0;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.footer {
|
||||
width: 100%;
|
||||
height: 100px;
|
||||
border-top: 1px solid #eaeaea;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.footer a {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.title a {
|
||||
color: #0070f3;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.title a:hover,
|
||||
.title a:focus,
|
||||
.title a:active {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.title {
|
||||
margin: 0;
|
||||
line-height: 1.15;
|
||||
font-size: 4rem;
|
||||
}
|
||||
|
||||
.title,
|
||||
.description {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.description {
|
||||
line-height: 1.5;
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
.code {
|
||||
background: #fafafa;
|
||||
border-radius: 5px;
|
||||
padding: 0.75rem;
|
||||
font-size: 1.1rem;
|
||||
font-family: Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono,
|
||||
Bitstream Vera Sans Mono, Courier New, monospace;
|
||||
}
|
||||
|
||||
.grid {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-wrap: wrap;
|
||||
max-width: 800px;
|
||||
margin-top: 3rem;
|
||||
}
|
||||
|
||||
.card {
|
||||
margin: 1rem;
|
||||
padding: 1.5rem;
|
||||
text-align: left;
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
border: 1px solid #eaeaea;
|
||||
border-radius: 10px;
|
||||
transition: color 0.15s ease, border-color 0.15s ease;
|
||||
width: 45%;
|
||||
}
|
||||
|
||||
.card:hover,
|
||||
.card:focus,
|
||||
.card:active {
|
||||
color: #0070f3;
|
||||
border-color: #0070f3;
|
||||
}
|
||||
|
||||
.card h2 {
|
||||
margin: 0 0 1rem 0;
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
.card p {
|
||||
margin: 0;
|
||||
font-size: 1.25rem;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.logo {
|
||||
height: 1em;
|
||||
margin-left: 0.5rem;
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
.grid {
|
||||
width: 100%;
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
|
@ -20,6 +20,43 @@ a {
|
|||
}
|
||||
|
||||
.rijuEdutor {
|
||||
overflow: hidden;
|
||||
height: calc(100% - 8px);
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* Split pane */
|
||||
|
||||
.split {
|
||||
overflow: auto;
|
||||
}
|
||||
.split .panel {
|
||||
overflow: auto;
|
||||
}
|
||||
.split .editor {
|
||||
overflow: hidden;
|
||||
}
|
||||
.split .gutter {
|
||||
background-color: #eee;
|
||||
opacity: 1;
|
||||
z-index: 1;
|
||||
background-repeat: no-repeat;
|
||||
background-position: 50%;
|
||||
}
|
||||
|
||||
/* .split .gutter:hover {
|
||||
opacity: 1;
|
||||
-webkit-transition: all 2s ease;
|
||||
transition: all 2s ease;
|
||||
} */
|
||||
|
||||
.split .gutter.gutter-vertical {
|
||||
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAFAQMAAABo7865AAAABlBMVEVHcEzMzMzyAv2sAAAAAXRSTlMAQObYZgAAABBJREFUeF5jOAMEEAIEEFwAn3kMwcB6I2AAAAAASUVORK5CYII=");
|
||||
cursor: row-resize;
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
.split .gutter.gutter-horizontal {
|
||||
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAeCAYAAADkftS9AAAAIklEQVQoU2M4c+bMfxAGAgYYmwGrIIiDjrELjpo5aiZeMwF+yNnOs5KSvgAAAABJRU5ErkJggg==");
|
||||
cursor: col-resize;
|
||||
height: 100% !important;
|
||||
}
|
||||
|
|
|
@ -51,6 +51,7 @@
|
|||
"prettier": "^2.3.1",
|
||||
"react": "17.0.2",
|
||||
"react-dom": "17.0.2",
|
||||
"react-split": "^2.0.13",
|
||||
"regenerator-runtime": "^0.13.7",
|
||||
"setimmediate": "^1.0.5",
|
||||
"strip-ansi": "^6.0.0",
|
||||
|
|
15
yarn.lock
15
yarn.lock
|
@ -4787,7 +4787,7 @@ promise-inflight@^1.0.1:
|
|||
resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3"
|
||||
integrity sha1-mEcocL8igTL8vdhoEputEsPAKeM=
|
||||
|
||||
prop-types@15.7.2, prop-types@^15.6.2, prop-types@^15.7.2:
|
||||
prop-types@15.7.2, prop-types@^15.5.7, prop-types@^15.6.2, prop-types@^15.7.2:
|
||||
version "15.7.2"
|
||||
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5"
|
||||
integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==
|
||||
|
@ -4952,6 +4952,14 @@ react-refresh@0.8.3:
|
|||
resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.8.3.tgz#721d4657672d400c5e3c75d063c4a85fb2d5d68f"
|
||||
integrity sha512-X8jZHc7nCMjaCqoU+V2I0cOhNW+QMBwSUkeXnTi8IPe6zaRWfn60ZzvFDZqWPfmSJfjub7dDW1SP0jaHWLu/hg==
|
||||
|
||||
react-split@^2.0.13:
|
||||
version "2.0.13"
|
||||
resolved "https://registry.yarnpkg.com/react-split/-/react-split-2.0.13.tgz#8d55fcb17edfd6cd2fb0203ab8324c02ec39a81a"
|
||||
integrity sha512-suq/UH4epMu2aF4NBh+imlpUvntsIvU3li9EBBLdxqNtYEg+nY7TGl8Ij65mD1qYyhs3dQhA1Pv3rLXd1s5/lQ==
|
||||
dependencies:
|
||||
prop-types "^15.5.7"
|
||||
split.js "^1.6.0"
|
||||
|
||||
react-transition-group@^4.4.2:
|
||||
version "4.4.2"
|
||||
resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-4.4.2.tgz#8b59a56f09ced7b55cbd53c36768b922890d5470"
|
||||
|
@ -5432,6 +5440,11 @@ split-string@^3.0.1, split-string@^3.0.2:
|
|||
dependencies:
|
||||
extend-shallow "^3.0.0"
|
||||
|
||||
split.js@^1.6.0:
|
||||
version "1.6.4"
|
||||
resolved "https://registry.yarnpkg.com/split.js/-/split.js-1.6.4.tgz#13d47cba53382adef230a53294ce5dacb2a2f2e1"
|
||||
integrity sha512-kYmQZprRJrF1IOjg/E+gdBEsKFv5kbgUE6RJVJZvrIzTOK/IHzKSqIeiJnWs7IP5D9TnpTQ2CbanuDuIWcyDUQ==
|
||||
|
||||
ssri@^6.0.1:
|
||||
version "6.0.2"
|
||||
resolved "https://registry.yarnpkg.com/ssri/-/ssri-6.0.2.tgz#157939134f20464e7301ddba3e90ffa8f7728ac5"
|
||||
|
|
Loading…
Reference in New Issue