esolang/languages/bf/renderer.tsx
2025-01-16 15:47:35 -08:00

59 lines
1.4 KiB
TypeScript

import * as React from "react";
import { RendererProps } from "../types";
import { Box } from "../ui-utils";
import { BFRS, serializeTapeMap } from "./common";
/** Number of cells shown in a single row */
const ROWSIZE = 8;
// Parameters for cell sizing, balanced to span the full row width
// Constraint: `(width% + 2 * margin%) * ROWSIZE = 100%`
const CELL_WIDTH = "12%";
const CELL_MARGIN = "5px 0.25%";
const styles: { [k: string]: React.CSSProperties } = {
container: {
padding: 10,
height: "100%",
display: "flex",
flexWrap: "wrap",
alignContent: "flex-start",
overflowY: "auto",
},
cell: {
// Sizing
width: CELL_WIDTH,
margin: CELL_MARGIN,
height: "50px",
// Center-align values
display: "flex",
justifyContent: "center",
alignItems: "center",
},
};
/** Component for displaying a single tape cell */
const Cell = React.memo(
({ value, active }: { value: number; active: boolean }) => {
return (
<Box
intent={active ? "active" : "plain"}
style={{ ...styles.cell, fontWeight: active ? "bold" : undefined }}
>
{value}
</Box>
);
}
);
/** Renderer for Brainfuck */
export const Renderer = ({ state }: RendererProps<BFRS>) => {
return (
<div style={styles.container}>
{serializeTapeMap(state?.tape || {}, 2 * ROWSIZE).map((num, i) => (
<Cell value={num} key={i} active={(state?.pointer || 0) === i} />
))}
</div>
);
};