| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150 |
- import { c as _c } from "react/compiler-runtime";
- /**
- * Overlay tracking for Escape key coordination.
- *
- * This solves the problem of escape key handling when overlays (like Select with onCancel)
- * are open. The CancelRequestHandler needs to know when an overlay is active so it doesn't
- * cancel requests when the user just wants to dismiss the overlay.
- *
- * Usage:
- * 1. Call useRegisterOverlay() in any overlay component to automatically register it
- * 2. Call useIsOverlayActive() to check if any overlay is currently active
- *
- * The hook automatically registers on mount and unregisters on unmount,
- * so no manual cleanup or state management is needed.
- */
- import { useContext, useEffect, useLayoutEffect } from 'react';
- import instances from '../ink/instances.js';
- import { AppStoreContext, useAppState } from '../state/AppState.js';
- // Non-modal overlays that shouldn't disable TextInput focus
- const NON_MODAL_OVERLAYS = new Set(['autocomplete']);
- /**
- * Hook to register a component as an active overlay.
- * Automatically registers on mount and unregisters on unmount.
- *
- * @param id - Unique identifier for this overlay (e.g., 'select', 'multi-select')
- * @param enabled - Whether to register (default: true). Use this to conditionally register
- * based on component props, e.g., only register when onCancel is provided.
- *
- * @example
- * // Conditional registration based on whether cancel is supported
- * function useSelectInput({ state }) {
- * useRegisterOverlay('select', !!state.onCancel)
- * // ...
- * }
- */
- export function useRegisterOverlay(id, t0) {
- const $ = _c(8);
- const enabled = t0 === undefined ? true : t0;
- const store = useContext(AppStoreContext);
- const setAppState = store?.setState;
- let t1;
- let t2;
- if ($[0] !== enabled || $[1] !== id || $[2] !== setAppState) {
- t1 = () => {
- if (!enabled || !setAppState) {
- return;
- }
- setAppState(prev => {
- if (prev.activeOverlays.has(id)) {
- return prev;
- }
- const next = new Set(prev.activeOverlays);
- next.add(id);
- return {
- ...prev,
- activeOverlays: next
- };
- });
- return () => {
- setAppState(prev_0 => {
- if (!prev_0.activeOverlays.has(id)) {
- return prev_0;
- }
- const next_0 = new Set(prev_0.activeOverlays);
- next_0.delete(id);
- return {
- ...prev_0,
- activeOverlays: next_0
- };
- });
- };
- };
- t2 = [id, enabled, setAppState];
- $[0] = enabled;
- $[1] = id;
- $[2] = setAppState;
- $[3] = t1;
- $[4] = t2;
- } else {
- t1 = $[3];
- t2 = $[4];
- }
- useEffect(t1, t2);
- let t3;
- let t4;
- if ($[5] !== enabled) {
- t3 = () => {
- if (!enabled) {
- return;
- }
- return _temp;
- };
- t4 = [enabled];
- $[5] = enabled;
- $[6] = t3;
- $[7] = t4;
- } else {
- t3 = $[6];
- t4 = $[7];
- }
- useLayoutEffect(t3, t4);
- }
- /**
- * Hook to check if any overlay is currently active.
- * This is reactive - the component will re-render when the overlay state changes.
- *
- * @returns true if any overlay is currently active
- *
- * @example
- * function CancelRequestHandler() {
- * const isOverlayActive = useIsOverlayActive()
- * const isActive = !isOverlayActive && canCancelRunningTask
- * useKeybinding('chat:cancel', handleCancel, { isActive })
- * }
- */
- function _temp() {
- return instances.get(process.stdout)?.invalidatePrevFrame();
- }
- export function useIsOverlayActive() {
- return useAppState(_temp2);
- }
- /**
- * Hook to check if any modal overlay is currently active.
- * Modal overlays are overlays that should capture all input (like Select dialogs).
- * Non-modal overlays (like autocomplete) don't disable TextInput focus.
- *
- * @returns true if any modal overlay is currently active
- *
- * @example
- * // Use for TextInput focus - allows typing during autocomplete
- * focus: !isSearchingHistory && !isModalOverlayActive
- */
- function _temp2(s) {
- return s.activeOverlays.size > 0;
- }
- export function useIsModalOverlayActive() {
- return useAppState(_temp3);
- }
- function _temp3(s) {
- for (const id of s.activeOverlays) {
- if (!NON_MODAL_OVERLAYS.has(id)) {
- return true;
- }
- }
- return false;
- }
|