Download src/hooks/chat/use-chat-input-events.ts from SaylorTwift/openhands: direct link, hf CLI and curl.
- Browser
- Download file 3.5 kB
-
https://huggingface.co/SaylorTwift/openhands/resolve/main/src/hooks/chat/use-chat-input-events.ts
- Command line
-
hf download hf://SaylorTwift/openhands/src/hooks/chat/use-chat-input-events.ts
-
curl -L -o use-chat-input-events.ts https://huggingface.co/SaylorTwift/openhands/resolve/main/src/hooks/chat/use-chat-input-events.ts
3.5 kB
| import { useCallback } from "react"; | |
| import { isMobileUserAgent } from "#/utils/utils"; | |
| import { | |
| ensureCursorVisible, | |
| clearEmptyContent, | |
| getClipboardFiles, | |
| } from "#/components/features/chat/utils/chat-input.utils"; | |
| /** | |
| * Hook for handling chat input events | |
| */ | |
| export const useChatInputEvents = ( | |
| chatInputRef: React.RefObject<HTMLDivElement | null>, | |
| smartResize: () => void, | |
| increaseHeightForEmptyContent: () => void, | |
| checkIsContentEmpty: () => boolean, | |
| clearEmptyContentHandler: () => void, | |
| onFocus?: () => void, | |
| onBlur?: () => void, | |
| ) => { | |
| // Handle input events | |
| const handleInput = useCallback(() => { | |
| smartResize(); | |
| // Clear empty content to ensure placeholder shows | |
| if (chatInputRef.current) { | |
| clearEmptyContent(chatInputRef.current); | |
| } | |
| // Ensure cursor stays visible when content is scrollable | |
| ensureCursorVisible(chatInputRef.current); | |
| }, [smartResize, chatInputRef]); | |
| // Handle paste events to clean up formatting and handle files | |
| const handlePaste = useCallback( | |
| (e: React.ClipboardEvent) => { | |
| e.preventDefault(); | |
| const files = getClipboardFiles(e.clipboardData); | |
| const hasFiles = files.length > 0; | |
| if (hasFiles) { | |
| // Handle file paste - let the file handling system process the files | |
| // We'll trigger a custom event that the file handling system can listen to | |
| const customEvent = new CustomEvent("pasteFiles", { | |
| detail: { files }, | |
| }); | |
| document.dispatchEvent(customEvent); | |
| return; | |
| } | |
| // Handle text paste as before | |
| const text = e.clipboardData.getData("text/plain"); | |
| if (text) { | |
| // Insert plain text | |
| document.execCommand("insertText", false, text); | |
| // Trigger resize | |
| setTimeout(smartResize, 0); | |
| } | |
| }, | |
| [smartResize], | |
| ); | |
| // Handle key events | |
| const handleKeyDown = useCallback( | |
| (e: React.KeyboardEvent, disabled: boolean, handleSubmit: () => void) => { | |
| if (e.key !== "Enter") { | |
| return; | |
| } | |
| // Ignore Enter key during IME composition (e.g., Chinese, Japanese, Korean input) | |
| // When using IME, Enter is used to confirm the composition, not to submit | |
| if (e.nativeEvent.isComposing) { | |
| return; | |
| } | |
| if (checkIsContentEmpty()) { | |
| e.preventDefault(); | |
| increaseHeightForEmptyContent(); | |
| return; | |
| } | |
| // Submit on Enter for everything except phones/tablets (where Enter | |
| // inserts a newline and the user taps the send button). We gate on the | |
| // user agent rather than touch capability so a desktop OS with a | |
| // touchscreen (e.g. a Windows 2-in-1) still submits on Enter. | |
| if (!isMobileUserAgent() && !e.shiftKey && !disabled) { | |
| e.preventDefault(); | |
| handleSubmit(); | |
| } | |
| }, | |
| [checkIsContentEmpty, increaseHeightForEmptyContent], | |
| ); | |
| // Handle blur events to ensure placeholder shows when empty | |
| const handleBlur = useCallback(() => { | |
| // Clear empty content to ensure placeholder shows | |
| if (chatInputRef.current) { | |
| clearEmptyContent(chatInputRef.current); | |
| } | |
| // Call the original onBlur callback if provided | |
| if (onBlur) { | |
| onBlur(); | |
| } | |
| }, [chatInputRef, onBlur]); | |
| // Handle focus events | |
| const handleFocus = useCallback(() => { | |
| if (onFocus) { | |
| onFocus(); | |
| } | |
| }, [onFocus]); | |
| return { | |
| handleInput, | |
| handlePaste, | |
| handleKeyDown, | |
| handleBlur, | |
| handleFocus, | |
| }; | |
| }; | |