diff --git a/frontend/apps/artcraft/app/src/pages/PageScene/comps/EngineCanvases.tsx b/frontend/apps/artcraft/app/src/pages/PageScene/comps/EngineCanvases.tsx index 6de4ee4a42..64ec4755ca 100644 --- a/frontend/apps/artcraft/app/src/pages/PageScene/comps/EngineCanvases.tsx +++ b/frontend/apps/artcraft/app/src/pages/PageScene/comps/EngineCanvases.tsx @@ -17,6 +17,8 @@ export const EditorCanvas = () => { id="video-scene" width="1280px" height="720px" + tabIndex={0} + style={{ outline: "none" }} /> ); }; diff --git a/frontend/apps/artcraft/app/src/pages/PageScene/hooks/useEditorCanvas.ts b/frontend/apps/artcraft/app/src/pages/PageScene/hooks/useEditorCanvas.ts new file mode 100644 index 0000000000..4ff6c796ad --- /dev/null +++ b/frontend/apps/artcraft/app/src/pages/PageScene/hooks/useEditorCanvas.ts @@ -0,0 +1,26 @@ +import { useEffect, useState } from "react"; +import { + camViewCanvasSignal, + editorCanvasSignal, +} from "~/pages/PageScene/contexts/EngineContext"; + +// React-shaped accessors for the canvas DOM nodes that the engine +// renders into. The underlying storage is a signal (set by +// EngineCanvases on mount); these hooks convert that to React state so +// dependent useEffects re-run when the canvas mounts/unmounts. + +export function useEditorCanvas(): HTMLCanvasElement | null { + const [canvas, setCanvas] = useState( + editorCanvasSignal.value, + ); + useEffect(() => editorCanvasSignal.subscribe(setCanvas), []); + return canvas; +} + +export function useCamViewCanvas(): HTMLCanvasElement | null { + const [canvas, setCanvas] = useState( + camViewCanvasSignal.value, + ); + useEffect(() => camViewCanvasSignal.subscribe(setCanvas), []); + return canvas; +}