Move header into Mainframe and controls to header

This commit is contained in:
Nilay Majorwar 2022-02-03 00:44:26 +05:30
parent 0befc7369a
commit 2db1e77a83
10 changed files with 99 additions and 75 deletions

View File

@ -2,7 +2,6 @@ import React from "react";
import { NextPage } from "next";
import Head from "next/head";
import { Mainframe } from "../../ui/Mainframe";
import { Header } from "../../ui/header";
import LangProvider from "../../languages/befunge93";
const LANG_ID = "befunge93";
const LANG_NAME = "Befunge-93";
@ -13,12 +12,11 @@ const IDE: NextPage = () => {
<Head>
<title>{LANG_NAME} | Esolang Park</title>
</Head>
<div style={{ height: "100%", display: "flex", flexDirection: "column" }}>
<Header langId={LANG_ID} langName={LANG_NAME} />
<div style={{ flexGrow: 1 }}>
<Mainframe langName={LANG_ID} provider={LangProvider} />
</div>
</div>
<Mainframe
langId={LANG_ID}
langName={LANG_NAME}
provider={LangProvider}
/>
</>
);
};

View File

@ -2,7 +2,6 @@ import React from "react";
import { NextPage } from "next";
import Head from "next/head";
import { Mainframe } from "../../ui/Mainframe";
import { Header } from "../../ui/header";
import LangProvider from "../../languages/brainfuck";
const LANG_ID = "brainfuck";
const LANG_NAME = "Brainfuck";
@ -13,12 +12,11 @@ const IDE: NextPage = () => {
<Head>
<title>{LANG_NAME} | Esolang Park</title>
</Head>
<div style={{ height: "100%", display: "flex", flexDirection: "column" }}>
<Header langId={LANG_ID} langName={LANG_NAME} />
<div style={{ flexGrow: 1 }}>
<Mainframe langName={LANG_ID} provider={LangProvider} />
</div>
</div>
<Mainframe
langId={LANG_ID}
langName={LANG_NAME}
provider={LangProvider}
/>
</>
);
};

View File

@ -2,7 +2,6 @@ import React from "react";
import { NextPage } from "next";
import Head from "next/head";
import { Mainframe } from "../../ui/Mainframe";
import { Header } from "../../ui/header";
import LangProvider from "../../languages/chef";
const LANG_ID = "chef";
const LANG_NAME = "Chef";
@ -13,12 +12,11 @@ const IDE: NextPage = () => {
<Head>
<title>{LANG_NAME} | Esolang Park</title>
</Head>
<div style={{ height: "100%", display: "flex", flexDirection: "column" }}>
<Header langId={LANG_ID} langName={LANG_NAME} />
<div style={{ flexGrow: 1 }}>
<Mainframe langName={LANG_ID} provider={LangProvider} />
</div>
</div>
<Mainframe
langId={LANG_ID}
langName={LANG_NAME}
provider={LangProvider}
/>
</>
);
};

View File

@ -2,7 +2,6 @@ import React from "react";
import { NextPage } from "next";
import Head from "next/head";
import { Mainframe } from "../../ui/Mainframe";
import { Header } from "../../ui/header";
import LangProvider from "../../languages/deadfish";
const LANG_ID = "deadfish";
const LANG_NAME = "Deadfish";
@ -13,12 +12,11 @@ const IDE: NextPage = () => {
<Head>
<title>{LANG_NAME} | Esolang Park</title>
</Head>
<div style={{ height: "100%", display: "flex", flexDirection: "column" }}>
<Header langId={LANG_ID} langName={LANG_NAME} />
<div style={{ flexGrow: 1 }}>
<Mainframe langName={LANG_ID} provider={LangProvider} />
</div>
</div>
<Mainframe
langId={LANG_ID}
langName={LANG_NAME}
provider={LangProvider}
/>
</>
);
};

View File

@ -3,7 +3,6 @@ import React from "react";
import { NextPage } from "next";
import Head from "next/head";
import { Mainframe } from "../../ui/Mainframe";
import { Header } from "../../ui/header";
import LangProvider from "../../languages/rockstar";
const LANG_ID = "$LANG_ID";
const LANG_NAME = "Rockstar";
@ -14,12 +13,11 @@ const IDE: NextPage = () => {
<Head>
<title>{LANG_NAME} | Esolang Park</title>
</Head>
<div style={{ height: "100%", display: "flex", flexDirection: "column" }}>
<Header langId={LANG_ID} langName={LANG_NAME} />
<div style={{ flexGrow: 1 }}>
<Mainframe langName={LANG_ID} provider={LangProvider} />
</div>
</div>
<Mainframe
langId={LANG_ID}
langName={LANG_NAME}
provider={LangProvider}
/>
</>
);
};

View File

@ -3,7 +3,6 @@ import React from "react";
import { NextPage } from "next";
import Head from "next/head";
import { Mainframe } from "../../ui/Mainframe";
import { Header } from "../../ui/header";
import LangProvider from "../../languages/$LANG_ID";
const LANG_ID = "$LANG_ID";
const LANG_NAME = "$LANG_NAME";
@ -14,12 +13,11 @@ const IDE: NextPage = () => {
<Head>
<title>{LANG_NAME} | Esolang Park</title>
</Head>
<div style={{ height: "100%", display: "flex", flexDirection: "column" }}>
<Header langId={LANG_ID} langName={LANG_NAME} />
<div style={{ flexGrow: 1 }}>
<Mainframe langName={LANG_ID} provider={LangProvider} />
</div>
</div>
<Mainframe
langId={LANG_ID}
langName={LANG_NAME}
provider={LangProvider}
/>
</>
);
};

View File

@ -1,5 +1,6 @@
import React from "react";
import { Mosaic, MosaicNode, MosaicWindow } from "react-mosaic-component";
import { Header } from "./header";
import { useDarkMode } from "./providers/dark-mode-provider";
// IDs of windows in the mosaic layout
@ -13,6 +14,8 @@ const WindowTitles = {
};
type Props = {
langId: string;
langName: string;
renderEditor: () => React.ReactNode;
renderRenderer: () => React.ReactNode;
renderInput: () => React.ReactNode;
@ -46,20 +49,27 @@ export const MainLayout = (props: Props) => {
};
return (
<Mosaic<keyof typeof MOSAIC_MAP>
className={mosaicClass}
initialValue={INITIAL_LAYOUT}
renderTile={(windowId, path) => (
<MosaicWindow<number>
path={path}
title={WindowTitles[windowId]}
toolbarControls={
windowId === "editor" ? props.renderExecControls() : <span />
}
>
{MOSAIC_MAP[windowId]()}
</MosaicWindow>
)}
/>
<div style={{ height: "100%", display: "flex", flexDirection: "column" }}>
<Header
langId={props.langId}
langName={props.langName}
renderExecControls={props.renderExecControls}
/>
<div style={{ flexGrow: 1 }}>
<Mosaic<keyof typeof MOSAIC_MAP>
className={mosaicClass}
initialValue={INITIAL_LAYOUT}
renderTile={(windowId, path) => (
<MosaicWindow<number>
path={path}
title={WindowTitles[windowId]}
toolbarControls={<span />}
>
{MOSAIC_MAP[windowId]()}
</MosaicWindow>
)}
/>
</div>
</div>
);
};

View File

@ -10,6 +10,7 @@ import { RendererRef, RendererWrapper } from "./renderer-wrapper";
import { WorkerRuntimeError } from "../languages/worker-errors";
type Props<RS> = {
langId: string;
langName: string;
provider: LanguageProvider<RS>;
};
@ -22,10 +23,10 @@ type Props<RS> = {
* small execution intervals if rendered on every execution. All state management
* is delegated to imperatively controlled child components.
*/
export const Mainframe = <RS extends {}>({ langName, provider }: Props<RS>) => {
export const Mainframe = <RS extends {}>(props: Props<RS>) => {
// Language provider and engine
const providerRef = React.useRef(provider);
const execController = useExecController(langName);
const providerRef = React.useRef(props.provider);
const execController = useExecController(props.langId);
// Refs for controlling UI components
const codeEditorRef = React.useRef<CodeEditorRef>(null);
@ -146,10 +147,12 @@ export const Mainframe = <RS extends {}>({ langName, provider }: Props<RS>) => {
return (
<MainLayout
langId={props.langId}
langName={props.langName}
renderEditor={() => (
<CodeEditor
ref={codeEditorRef}
languageId={langName}
languageId={props.langName}
defaultValue={providerRef.current.sampleProgram}
tokensProvider={providerRef.current.editorTokensProvider}
onValidateCode={execController.validateCode}

View File

@ -15,10 +15,11 @@ const styles = {
},
inputWrapper: {
/**
* As of Dec'21, NumericInput doesn't have `small` prop yet,
* so we instead use `transform` to hack up a smaller input.
* As of Feb'22, NumericInput doesn't have `small` prop yet,
* so we instead use `transform` to hack up a slightly smaller input.
*/
transform: "scale(0.8)",
transform: "scale(0.9)",
marginLeft: 10,
},
input: {
width: 125,
@ -44,6 +45,7 @@ const IntervalInput = (props: {
clampValueOnBlur
style={styles.input}
disabled={props.disabled}
title="Adjust the execution interval"
onValueChange={(v) => props.onChange(v)}
rightElement={<Tag minimal>ms</Tag>}
allowNumericCharactersOnly
@ -55,9 +57,11 @@ const IntervalInput = (props: {
/** Button for starting code execution */
const RunButton = ({ onClick }: { onClick: () => void }) => (
<Button
small
outlined
intent="success"
onClick={onClick}
rightIcon={<Icon icon="play" intent="success" />}
title="Run your code"
>
Run code
</Button>
@ -78,21 +82,24 @@ const DebugControls = (props: {
return (
<ButtonGroup>
<Button
small
title={paused ? "Pause" : "Resume"}
outlined
intent="primary"
title={paused ? "Resume" : "Pause"}
disabled={pauseDisabled}
onClick={paused ? props.onResume : props.onPause}
icon={<Icon icon={paused ? "play" : "pause"} intent="primary" />}
/>
<Button
small
outlined
intent="warning"
title="Step"
onClick={props.onStep}
disabled={stepDisabled}
icon={<Icon icon="step-forward" intent="warning" />}
/>
<Button
small
outlined
intent="danger"
title="Stop"
onClick={props.onStop}
icon={<Icon icon="stop" intent="danger" />}

View File

@ -1,8 +1,8 @@
import { Button, Card, Icon } from "@blueprintjs/core";
import Image from "next/image";
import logoImg from "./assets/logo.png";
import { GitHubIcon } from "./custom-icons";
import { useDarkMode } from "./providers/dark-mode-provider";
import { Button, Card, Icon, Tag } from "@blueprintjs/core";
/** Link to the project's GitHub repository */
const REPO_LINK = "https://github.com/nilaymaj/esolang-park";
@ -11,22 +11,38 @@ const REPO_LINK = "https://github.com/nilaymaj/esolang-park";
const NOTES_LINK = (id: string) =>
`https://github.com/nilaymaj/esolang-park/blob/main/languages/${id}/README.md`;
export const Header = (props: { langId: string; langName: string }) => {
type Props = {
langId: string;
langName: string;
renderExecControls: () => React.ReactNode;
};
export const Header = (props: Props) => {
const DarkMode = useDarkMode();
const brandSection = (
<div style={{ flex: 1, textAlign: "left" }}>
<div
style={{
flex: 1,
textAlign: "left",
display: "flex",
alignItems: "center",
}}
>
<Button minimal large>
<div style={{ display: "flex", alignItems: "center" }}>
<Image src={logoImg} alt="logo" width={20} height={20} />
<span style={{ marginLeft: 10 }}>Esolang Park</span>
</div>
</Button>
<Tag large minimal style={{ marginLeft: 10 }}>
{props.langName}
</Tag>
</div>
);
const langSection = (
<div style={{ flex: 0, textAlign: "center" }}>{props.langName}</div>
const controlsSection = (
<div style={{ textAlign: "center" }}>{props.renderExecControls()}</div>
);
const infoSection = (
@ -60,7 +76,7 @@ export const Header = (props: { langId: string; langName: string }) => {
}}
>
{brandSection}
{langSection}
{controlsSection}
{infoSection}
</Card>
</div>