/** * @license * Copyright 2025 Vybestack LLC * SPDX-License-Identifier: Apache-2.0 */ import type { InputPromptStateResult } from './inputPromptHooks.js'; import { useMousePaste, useRuntimeState } from './inputPromptHooks.js'; import { PromptInputBox, useGhostTextLines, useSuggestionsNodes, } from './inputPromptRender.js'; import type { InputPromptProps } from './inputPromptTypes.js'; import type { TextBuffer } from './shared/text-buffer.js'; import type { DOMElement } from 'ink'; import type React from 'react'; import { useRef } from 'react'; import { useMouseClick } from '../hooks/useMouseClick.js'; export { calculatePromptWidths } from './inputPromptText.js'; export type { InputPromptProps } from './inputPromptTypes.js'; type InputPromptViewProps = { buffer: TextBuffer; placeholder: string; focus: boolean; inputWidth: number; suggestionsPosition: 'above' | 'below'; shellModeActive: boolean; state: InputPromptStateResult; suggestionsNode: React.ReactNode; innerBoxRef: React.RefObject; ghostText: { inlineGhost: string; additionalLines: string[] }; }; const InputPromptView: React.FC = ({ buffer, placeholder, focus, inputWidth, suggestionsPosition, shellModeActive, state, suggestionsNode, ghostText, innerBoxRef, }) => ( <> {suggestionsPosition === 'above' && suggestionsNode} {suggestionsPosition === 'below' && suggestionsNode} ); export const InputPrompt: React.FC = ({ placeholder = ' Type your message or @path/to/file', focus = true, inputWidth, suggestionsWidth, suggestionsPosition = 'below', ...runtimeProps }) => { const state = useRuntimeState({ ...runtimeProps, focus }); useMousePaste(focus, runtimeProps.isEmbeddedShellFocused, state); const innerBoxRef = useRef(null); // Clicking the prompt moves the caret to the clicked cell. This was lost when // InputPrompt was split into hooks; the buffer still exposes the operation. useMouseClick( innerBoxRef, (_event, relativeX, relativeY) => { const visualRow = runtimeProps.buffer.visualScrollRow + relativeY; runtimeProps.buffer.moveToVisualPosition(visualRow, relativeX); }, { isActive: focus === true && runtimeProps.isEmbeddedShellFocused !== true, }, ); const ghostText = useGhostTextLines( state.completion, runtimeProps.buffer, inputWidth, ); const suggestionsNode = useSuggestionsNodes( state.completion, runtimeProps.shellModeActive, state.reverseSearchActive, state.reverseSearchCompletion, state.shellPathCompletion, suggestionsWidth, runtimeProps.buffer.text, ); return ( ); };