All files / web/src/lib/character useChatInputFocus.ts

0% Statements 0/40
0% Branches 0/1
0% Functions 0/1
0% Lines 0/40

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41                                                                                 
import { useRef, useEffect, useCallback } from 'react'

/**
 * Keeps a chat input focused across send → stream → idle cycles.
 *
 * When `disabled={isStreaming}` kicks in, the browser blurs the input.
 * This hook snapshots whether the input had focus before the send,
 * then restores focus once streaming finishes.
 *
 * Also provides `preventFocusLoss` — put it on `onMouseDown` of buttons
 * (like the send button) that should not steal focus from the input.
 */
export function useChatInputFocus(
  inputRef: React.RefObject<HTMLInputElement | null>,
  isStreaming: boolean
) {
  const hadFocusRef = useRef(false)

  /** Call right before sending to snapshot the focus state. */
  const markFocusBeforeSend = useCallback(() => {
    if (inputRef.current && document.activeElement === inputRef.current) {
      hadFocusRef.current = true
    }
  }, [inputRef])

  /** Put on `onMouseDown` of the send button to prevent it from stealing focus. */
  const preventFocusLoss = useCallback((e: React.MouseEvent) => {
    e.preventDefault()
  }, [])

  // Restore focus when streaming ends
  useEffect(() => {
    if (!isStreaming && hadFocusRef.current) {
      hadFocusRef.current = false
      requestAnimationFrame(() => inputRef.current?.focus())
    }
  }, [isStreaming, inputRef])

  return { markFocusBeforeSend, preventFocusLoss }
}