import { useCallback, useContext, useLayoutEffect, useRef } from 'react' import CursorDeclarationContext from '../components/CursorDeclarationContext.js' import type { DOMElement } from '../dom.js' /** * Declares where the terminal cursor should be parked after each frame. * * Terminal emulators render IME preedit text at the physical cursor * position, and screen readers / screen magnifiers track the native * cursor — so parking it at the text input's caret makes CJK input * appear inline and lets accessibility tools follow the input. * * Returns a ref callback to attach to the Box that contains the input. */ export function useDeclaredCursor({ line, column, active, }: { line: number column: number active: boolean }): (element: DOMElement | null) => void { const setCursorDeclaration = useContext(CursorDeclarationContext) const nodeRef = useRef(null) const setNode = useCallback((node: DOMElement | null) => { nodeRef.current = node }, []) useLayoutEffect(() => { const node = nodeRef.current if (active && node) { setCursorDeclaration({ relativeX: column, relativeY: line, node }) } else { setCursorDeclaration(null, node) } }) useLayoutEffect(() => { return () => { setCursorDeclaration(null, nodeRef.current) } }, [setCursorDeclaration]) return setNode }