Move header into Mainframe and controls to header
This commit is contained in:
		@@ -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}
 | 
			
		||||
      />
 | 
			
		||||
    </>
 | 
			
		||||
  );
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -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}
 | 
			
		||||
      />
 | 
			
		||||
    </>
 | 
			
		||||
  );
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -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}
 | 
			
		||||
      />
 | 
			
		||||
    </>
 | 
			
		||||
  );
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -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}
 | 
			
		||||
      />
 | 
			
		||||
    </>
 | 
			
		||||
  );
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -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}
 | 
			
		||||
      />
 | 
			
		||||
    </>
 | 
			
		||||
  );
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -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}
 | 
			
		||||
      />
 | 
			
		||||
    </>
 | 
			
		||||
  );
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -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>
 | 
			
		||||
  );
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -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}
 | 
			
		||||
 
 | 
			
		||||
@@ -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" />}
 | 
			
		||||
 
 | 
			
		||||
@@ -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>
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user