/* eslint-disable @typescript-eslint/ban-ts-comment */ import styled from "styles" import { useStateDesigner } from "@state-designer/react" import React, { useEffect, useRef } from "react" import { motion } from "framer-motion" import state, { useSelector } from "state" import { CodeFile } from "types" import CodeDocs from "./code-docs" import CodeEditor from "./code-editor" import { getShapesFromCode } from "lib/code/generate" import { X, Code, Info, PlayCircle, ChevronUp, ChevronDown, } from "react-feather" const getErrorLineAndColumn = (e: any) => { if ("line" in e) { return { line: Number(e.line), column: e.column } } const result = e.stack.match(/:([0-9]+):([0-9]+)/) if (result) { return { line: Number(result[1]) - 1, column: result[2] } } } export default function CodePanel() { const rContainer = useRef(null) const isReadOnly = useSelector((s) => s.data.isReadOnly) const fileId = useSelector((s) => s.data.currentCodeFileId) const file = useSelector( (s) => s.data.document.code[s.data.currentCodeFileId] ) const isOpen = true const fontSize = useSelector((s) => s.data.settings.fontSize) const local = useStateDesigner({ data: { code: file.code, error: null as { message: string; line: number; column: number } | null, }, on: { MOUNTED: "setCode", CHANGED_FILE: "loadFile", }, initial: "editingCode", states: { editingCode: { on: { RAN_CODE: "runCode", SAVED_CODE: ["runCode", "saveCode"], CHANGED_CODE: { secretlyDo: "setCode" }, CLEARED_ERROR: { if: "hasError", do: "clearError" }, TOGGLED_DOCS: { to: "viewingDocs" }, }, }, viewingDocs: { on: { TOGGLED_DOCS: { to: "editingCode" }, }, }, }, conditions: { hasError(data) { return !!data.error }, }, actions: { loadFile(data, payload: { file: CodeFile }) { data.code = payload.file.code }, setCode(data, payload: { code: string }) { data.code = payload.code }, runCode(data) { let error = null try { const shapes = getShapesFromCode(data.code) state.send("GENERATED_SHAPES_FROM_CODE", { shapes }) } catch (e) { console.error(e) error = { message: e.message, ...getErrorLineAndColumn(e) } } data.error = error }, saveCode(data) { const { code } = data state.send("SAVED_CODE", { code }) }, clearError(data) { data.error = null }, }, }) useEffect(() => { local.send("CHANGED_FILE", { file }) }, [file]) useEffect(() => { local.send("MOUNTED", { code: state.data.document.code[fileId].code }) return () => { state.send("CHANGED_CODE", { fileId, code: local.data.code }) } }, []) const { error } = local.data return ( {isOpen ? (
state.send("CLOSED_CODE_PANEL")}>

Code

state.send("INCREASED_CODE_FONT_SIZE")} > state.send("DECREASED_CODE_FONT_SIZE")} > local.send("TOGGLED_DOCS")}> local.send("SAVED_CODE")} >
local.send("CHANGED_CODE", { code })} onSave={() => local.send("SAVED_CODE")} onKey={() => local.send("CLEARED_ERROR")} /> {error && (error.line ? `(${Number(error.line) - 2}:${error.column}) ${error.message}` : error.message)}
) : ( state.send("OPENED_CODE_PANEL")}> )}
) } const PanelContainer = styled(motion.div, { position: "absolute", top: "48px", right: "8px", bottom: "48px", backgroundColor: "$panel", borderRadius: "4px", overflow: "hidden", border: "1px solid $border", pointerEvents: "all", userSelect: "none", zIndex: 200, button: { border: "none", }, variants: { isCollapsed: { true: {}, false: {}, }, }, }) const IconButton = styled("button", { height: "40px", width: "40px", backgroundColor: "$panel", borderRadius: "4px", border: "1px solid $border", padding: "0", margin: "0", display: "flex", alignItems: "center", justifyContent: "center", outline: "none", pointerEvents: "all", cursor: "pointer", "&:hover:not(:disabled)": { backgroundColor: "$panel", }, "&:disabled": { opacity: "0.5", }, svg: { height: "20px", width: "20px", strokeWidth: "2px", stroke: "$text", }, }) const Content = styled("div", { display: "grid", gridTemplateColumns: "1fr", gridTemplateRows: "auto 1fr 28px", height: "100%", width: 560, minWidth: "100%", maxWidth: 560, overflow: "hidden", userSelect: "none", pointerEvents: "all", }) const Header = styled("div", { pointerEvents: "all", display: "grid", gridTemplateColumns: "auto 1fr", alignItems: "center", justifyContent: "center", borderBottom: "1px solid $border", "& button": { gridColumn: "1", gridRow: "1", }, "& h3": { gridColumn: "1 / span 3", gridRow: "1", textAlign: "center", margin: "0", padding: "0", fontSize: "16px", }, }) const ButtonsGroup = styled("div", { gridRow: "1", gridColumn: "3", display: "flex", }) const EditorContainer = styled("div", { position: "relative", pointerEvents: "all", overflowY: "scroll", }) const ErrorContainer = styled("div", { overflowX: "scroll", color: "$text", font: "$debug", padding: "0 12px", display: "flex", alignItems: "center", }) const FontSizeButtons = styled("div", { paddingRight: 4, "& > button": { height: "50%", width: "100%", "&:nth-of-type(1)": { paddingTop: 4, }, "&:nth-of-type(2)": { paddingBottom: 4, }, "& svg": { height: 12, }, }, })