import { type ReactNode, useEffect, useRef, useState, useCallback, useId, } from "react"; import { KittyContext, type KittyContextProps } from "../context/KittyContext"; import { useApp } from "../context/AppContext"; export const CHAR_WIDTH = 12; export const CHAR_HEIGHT = 26; const PADDING_RIGHT = CHAR_WIDTH / 2; export const Kitty = (props: { children?: ReactNode; rows?: number; cols?: number; className?: string; }) => { const container = useRef(null); const [width, setWidth] = useState<`${number}px` | "auto">( props.cols ? `${props.cols * CHAR_WIDTH}px` : "auto", ); const [height, setHeight] = useState<`${number}px` | "auto">( props.rows ? `${props.rows * CHAR_HEIGHT}px` : "auto", ); const [context, setContext] = useState( undefined, ); const id = useId(); const { activeKitty, setActiveKitty } = useApp(); const handleMouseEnter = useCallback(() => { setActiveKitty(id); }, [id, setActiveKitty]); const snapToCharacter = useCallback(() => { if (!container.current) return; const cols = Math.round( (container.current.clientWidth - PADDING_RIGHT) / CHAR_WIDTH, ); const rows = Math.round(container.current.clientHeight / CHAR_HEIGHT); const width = cols * CHAR_WIDTH; const height = rows * CHAR_HEIGHT; setWidth(`${width}px`); setHeight(`${height}px`); setContext((ctx) => ({ ...(ctx ?? { active: false }), rows, cols })); }, []); useEffect(() => { if (!container.current) return; snapToCharacter(); window.addEventListener("resize", snapToCharacter); return () => { window.removeEventListener("resize", snapToCharacter); }; }, [snapToCharacter]); return (
{props.children}
); };