UNPKG

@1771technologies/lytenyte-pro

Version:

Blazingly fast headless React data grid with 100s of features.

38 lines (37 loc) 1.92 kB
import { useCallback } from "react"; import { replaceWordAtCursor } from "./replace-word-at-cursor.js"; export function useKeyboardNavigation({ onValueChange, onAccepted, textareaRef }) { const acceptCompletion = useCallback((item, word) => { const textarea = textareaRef.current; if (!textarea) return; // Extend the replacement range to consume any @"..." / @'...' prefix the user already typed. // The partial word may contain spaces (e.g. @"Age Gr → word is "Gr"), so scan backwards // through word chars and spaces to find the opening @" / @'. let adjustedWord = word; const text = textarea.value; let scan = word.start - 1; // skip back over any chars that could be part of a quoted identifier value (spaces included) while (scan > 0 && text[scan] !== '"' && text[scan] !== "'") scan--; if (scan >= 1 && (text[scan] === '"' || text[scan] === "'") && text[scan - 1] === "@") { adjustedWord = { ...word, start: scan - 1 }; } const charBeforeWord = adjustedWord.start > 0 ? text[adjustedWord.start - 1] : ""; const noSpaceBefore = charBeforeWord === "" || charBeforeWord === " " || charBeforeWord === "." || charBeforeWord === "(" || charBeforeWord === "[" || charBeforeWord === "{"; const rawInsertText = item.value ?? item.label; const insertText = noSpaceBefore ? rawInsertText : " " + rawInsertText; const { value, cursorPosition } = replaceWordAtCursor(text, adjustedWord, insertText); textarea.value = value; textarea.selectionStart = cursorPosition; textarea.selectionEnd = cursorPosition; onValueChange(value); onAccepted(value, cursorPosition); }, [onValueChange, onAccepted, textareaRef]); return { acceptCompletion }; }