diff options
| author | Keith Lyons <[email protected]> | 2025-07-17 20:45:42 -0400 |
|---|---|---|
| committer | GitHub <[email protected]> | 2025-07-18 00:45:42 +0000 |
| commit | 8ade3e7ee26c1dedd105a20fa769c68e4103b75d (patch) | |
| tree | 38a93971170bf301713ee490db1a34cad1be5d1d /packages/cli/src/ui/hooks/useFocus.ts | |
| parent | 584a50a3422fc543a0f861cd946fa0403acc12f0 (diff) | |
feat(ui): hide cursor when terminal is unfocused (#4012)
Diffstat (limited to 'packages/cli/src/ui/hooks/useFocus.ts')
| -rw-r--r-- | packages/cli/src/ui/hooks/useFocus.ts | 48 |
1 files changed, 48 insertions, 0 deletions
diff --git a/packages/cli/src/ui/hooks/useFocus.ts b/packages/cli/src/ui/hooks/useFocus.ts new file mode 100644 index 00000000..6c9a6daa --- /dev/null +++ b/packages/cli/src/ui/hooks/useFocus.ts @@ -0,0 +1,48 @@ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import { useStdin, useStdout } from 'ink'; +import { useEffect, useState } from 'react'; + +// ANSI escape codes to enable/disable terminal focus reporting +const ENABLE_FOCUS_REPORTING = '\x1b[?1004h'; +const DISABLE_FOCUS_REPORTING = '\x1b[?1004l'; + +// ANSI escape codes for focus events +const FOCUS_IN = '\x1b[I'; +const FOCUS_OUT = '\x1b[O'; + +export const useFocus = () => { + const { stdin } = useStdin(); + const { stdout } = useStdout(); + const [isFocused, setIsFocused] = useState(true); + + useEffect(() => { + const handleData = (data: Buffer) => { + const sequence = data.toString(); + const lastFocusIn = sequence.lastIndexOf(FOCUS_IN); + const lastFocusOut = sequence.lastIndexOf(FOCUS_OUT); + + if (lastFocusIn > lastFocusOut) { + setIsFocused(true); + } else if (lastFocusOut > lastFocusIn) { + setIsFocused(false); + } + }; + + // Enable focus reporting + stdout?.write(ENABLE_FOCUS_REPORTING); + stdin?.on('data', handleData); + + return () => { + // Disable focus reporting on cleanup + stdout?.write(DISABLE_FOCUS_REPORTING); + stdin?.removeListener('data', handleData); + }; + }, [stdin, stdout]); + + return isFocused; +}; |
