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 ref = useRef(null); const [handle, setHandle] = useState(null); const attachConsole = useCallback(async () => { const picoConsole = await makePicoConsole({ carts, }); picoConsole.canvas.tabIndex=0; if (ref.current) { ref.current.appendChild(picoConsole.canvas); picoConsole.canvas.focus(); } setHandle(picoConsole); picoConsole.canvas.addEventListener('keydown',(event) => { if (["ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight"].includes(event.key)) { event.preventDefault(); } }, {passive: false}); picoConsole.canvas.addEventListener('click', () => { picoConsole.canvas.focus(); }) }, [carts]); useImperativeHandle(forwardedRef, () => ({ getPicoConsoleHandle() { return handle; } }), [handle]); useEffect(() => { if (playing) { attachConsole(); return () => { if (ref.current) { ref.current.innerHTML = ""; } } } }, [playing, attachConsole]); if (!playing) { return (
{setPlaying(true)}} > Play!
) } return (
canvas { width: 100%; height: 100%; } `}>
); });