text-input-cursor
v0.1.1
Published
An expo module to get the cursor's on screen coordinates in a text input. Helps to build suggestion tooltips etc.
Maintainers
Readme
text-input-cursor
An Expo module for retrieving the on-screen coordinates of the text cursor in TextInput components. This module enables precise positioning of UI elements such as autocomplete dropdowns, mention suggestions, and tooltips relative to the cursor position.
Installation
npm install text-input-cursoror
yarn add text-input-cursorDemo


Usage
Standard Mode
The TextInputWithCursor component provides automatic cursor tracking with real-time coordinate updates on every text change.
import { useState } from 'react';
import { View, StyleSheet } from 'react-native';
import { TextInputWithCursor, type CursorCoordinates } from 'text-input-cursor';
export default function Example() {
const [text, setText] = useState('');
const [cursorCoords, setCursorCoords] = useState<CursorCoordinates | null>(null);
return (
<View style={styles.container}>
<View>
<TextInputWithCursor
value={text}
onChangeText={setText}
onCursorCoordinatesChange={({ coordinates }) => {
setCursorCoords(coordinates);
}}
placeholder="Type @ to mention someone..."
multiline
style={styles.input}
/>
{cursorCoords && (
<View
style={[
styles.dropdown,
{
top: cursorCoords.y,
left: cursorCoords.x,
}
]}
>
{/* Your dropdown content */}
</View>
)}
</View>
</View>
);
}Performance Mode
For performance-critical applications, use getCursorCoordinates to fetch coordinates only when needed. This approach eliminates unnecessary calculations during normal typing and only queries cursor position when specific triggers are detected.
import { useState, useRef } from 'react';
import { View, TextInput } from 'react-native';
import { getCursorCoordinates, type CursorCoordinates } from 'text-input-cursor';
export default function PerformanceExample() {
const [text, setText] = useState('');
const [cursorCoords, setCursorCoords] = useState<CursorCoordinates | null>(null);
const inputRef = useRef<TextInput>(null);
const handleTextChange = async (newText: string) => {
setText(newText);
// Code to detect @ symbol
// Code to check if mention is still active (no space after @)
if (/* mention detected */) {
// Fetch coordinates only when needed
const coords = await getCursorCoordinates(inputRef);
setCursorCoords(coords);
} else {
setCursorCoords(null);
}
};
return (
<View style={styles.container}>
<View>
<TextInput
ref={inputRef}
value={text}
onChangeText={handleTextChange}
placeholder="Type @ to mention someone..."
multiline
style={styles.input}
/>
{cursorCoords && (
<View
style={[
styles.dropdown,
{
top: cursorCoords.y,
left: cursorCoords.x,
}
]}
>
{/* Your dropdown content */}
</View>
)}
</View>
</View>
);
}Important: Coordinate Positioning
The returned coordinates (x, y) are relative to the TextInput component, not the screen. To position elements correctly:
- Wrap the TextInput and positioned elements in a common parent View
- Use
position: 'absolute'on the positioned element - Apply the coordinates directly to the element's
topandleftstyle properties
The parent View establishes the coordinate space for both the TextInput and the absolutely positioned element. Make sure the parent View doesn't have a padding.
API Reference
TextInputWithCursor
A component that extends React Native's TextInput with automatic cursor tracking.
Props
- All standard
TextInputprops onCursorCoordinatesChange?: (event: CursorCoordinatesChangeEvent) => void
CursorCoordinatesChangeEvent
{
coordinates: CursorCoordinates | null;
cursorPosition: number;
}getCursorCoordinates
Function to retrieve cursor coordinates on demand.
function getCursorCoordinates(
inputRef: RefObject<TextInput>
): Promise<CursorCoordinates | null>CursorCoordinates
{
x: number; // Horizontal position (points)
y: number; // Vertical position (points)
lineHeight: number; // Height of cursor line (points)
}Returns null if the input reference is unavailable, platform is unsupported, or an error occurs.
Platform Support
| Platform | Support | |----------|---------| | iOS | ✅ | | Android | ✅ | | Web | ✅ |
Implementation Details
This module uses native platform APIs for accurate cursor positioning. Improvements and suggestions are welcome!
- iOS:
UITextView.caretRect(for:)andUITextField.caretRect(for:) - Android:
Layout.getPrimaryHorizontal(),Layout.getLineTop(), andLayout.getLineBottom() - Web: Shadow element technique that creates an invisible mirror div with identical styles and text content, using
getBoundingClientRect()on a span element to measure the exact cursor position
License
MIT
