import { useEffect, useRef } from 'react' import { GhostScene } from './GhostScene' import type { GhostMood, GhostVisualState } from './GhostScene' export type GhostCanvasProps = { visual: GhostVisualState | null mood: GhostMood /** Called each frame to get the speaking amplitude (0..1). */ getAmplitude?: () => number className?: string } /** React wrapper: owns the canvas element and the GhostScene lifecycle. */ export function GhostCanvas({ visual, mood, getAmplitude, className }: GhostCanvasProps) { const canvasRef = useRef(null) const sceneRef = useRef(null) const ampRef = useRef(getAmplitude) ampRef.current = getAmplitude useEffect(() => { const canvas = canvasRef.current if (!canvas) return const scene = new GhostScene(canvas) sceneRef.current = scene scene.start() const ampTimer = window.setInterval(() => { scene.setSpeakAmplitude(ampRef.current?.() ?? 0) }, 50) return () => { window.clearInterval(ampTimer) scene.dispose() sceneRef.current = null } }, []) useEffect(() => { sceneRef.current?.setVisual(visual) }, [visual]) useEffect(() => { sceneRef.current?.setMood(mood) }, [mood]) return (
) }