import { css } from "@emotion/css"; import { PicoCart, PicoPlayerHandle, makePicoConsole } from "./renderCart"; import { ForwardedRef, forwardRef, useCallback, useEffect, useImperativeHandle, useRef, useState } from "react"; type Pico8ConsoleImperatives = { getPicoConsoleHandle(): PicoPlayerHandle | null; } export const Pico8Console = forwardRef((props: { carts: PicoCart[] }, forwardedRef: ForwardedRef) => { const {carts} = props; const [playing, setPlaying] = useState(false); const playingRef = useRef(false); const ref = useRef(null); const listeners = useRef void) }>>({}); const [handle, setHandle] = useState(null); const attachConsole = useCallback(async () => { const picoConsole = await makePicoConsole({ carts, }); const codoTextarea: HTMLTextAreaElement = (picoConsole.rawModule as any).codo_textarea; picoConsole.canvas.addEventListener('click', () => { codoTextarea.focus(); codoTextarea.select(); }) if (ref.current) { ref.current.appendChild(picoConsole.canvas); ref.current.appendChild(codoTextarea); } setHandle(picoConsole); listeners.current.keydown = function (event) { console.log("keydown", event.key); if (!playingRef.current) { return; } console.log(picoConsole.state); if (picoConsole.state.hasFocus) { console.log("hasFocus"); // block only cursors, M R P, tab if (["ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight", "M", "R", "P", "m", "r", "p", "Tab"].includes(event.key)) { console.log("preventDefault"); event.preventDefault(); } } }; document.addEventListener('keydown', listeners.current.keydown, {passive: false} ); }, [carts]); useImperativeHandle(forwardedRef, () => ({ getPicoConsoleHandle() { return handle; } }), [handle]); useEffect(() => { if (playing && playingRef.current) { attachConsole(); return () => { playingRef.current = false; if (ref.current) { ref.current.innerHTML = ""; } if (listeners.current.keydown) { document.removeEventListener("keydown", listeners.current.keydown); listeners.current.keydown = null; } } } }, [playing, attachConsole]); if (!playing) { return (
{playingRef.current = true; setPlaying(true)}} > Play!
) } return (
canvas { width: 100%; height: 100%; } `}>
); });