Package Exports
- react-native-advanced-selectable-text
Readme
react-native-advanced-selectable-text
High-performance, fully customizable text selection component for React Native using Skia rendering. Achieve "ChatGPT-style" text selection with custom cursors, handles, and floating menus.
Features
- π¨ Skia-powered rendering - Smooth 60fps selection animations
- π± Cross-platform - iOS, Android, and Web (Expo compatible)
- π Multiple Instances - Coordinated selection across many components (perfect for chat feeds)
- β¨ Customizable - Selection colors, cursor styles, handle appearance
- π― Precise selection - Draggable handles with swap support
- π¬ Floating menu - Animated action menu with custom options
- β‘ Reanimated worklets - UI thread gesture handling
- π‘οΈ Strongly Typed - Full TypeScript support, zero
any
Installation
# npm
npm install react-native-advanced-selectable-text
# yarn
yarn add react-native-advanced-selectable-text
# bun
bun add react-native-advanced-selectable-textPeer Dependencies
This package requires the following peer dependencies:
# npm
npm install @shopify/react-native-skia react-native-gesture-handler react-native-reanimated react-native-worklets
# Expo
npx expo install @shopify/react-native-skia react-native-gesture-handler react-native-reanimated react-native-workletsBasic Usage
Wrap your application (or specific screen) with SelectionProvider to enable coordinated selection handling.
import {
SelectableText,
SelectionProvider,
useSelection,
} from "react-native-selectable-text";
import { GestureHandlerRootView } from "react-native-gesture-handler";
function Example() {
const { selection, clearSelection } = useSelection();
return (
<View style={{ flex: 1 }} onTouchStart={() => clearSelection()}>
<SelectableSkiaText
text="Long-press me for selection!"
menuOptions={[
{ label: "Copy", onPress: (text) => console.log("Copy:", text) },
]}
/>
</View>
);
}
export default function App() {
return (
<GestureHandlerRootView style={{ flex: 1 }}>
<SelectionProvider>
<Example />
</SelectionProvider>
</GestureHandlerRootView>
);
}Advanced: Coordinated chat list
When using SelectionProvider, multiple SelectableSkiaText instances will automatically coordinate. Starting a selection in one message will automatically clear the selection in others.
<SelectionProvider>
<ScrollView>
{messages.map((msg) => (
<SelectableSkiaText
key={msg.id}
text={msg.content}
menuOptions={globalMenuOptions}
/>
))}
</ScrollView>
</SelectionProvider>Props
| Prop | Type | Default | Description |
|---|---|---|---|
text |
string |
required | The text content to display |
menuOptions |
MenuOption[] |
required | Array of menu options |
fontSize |
number |
16 |
Font size in points |
fontFamily |
string |
System font | Font family name |
textColor |
string |
#000000 |
Text color |
selectionColor |
string |
rgba(59, 130, 246, 0.3) |
Selection highlight color |
cursorColor |
string |
#3b82f6 |
Cursor and handle color |
width |
number |
Container width | Fixed width for text layout |
style |
ViewStyle |
- | Container style |
selection |
Selection | null |
- | Overrides internal selection (controlled mode) |
onSelectionChange |
(selection: Selection | null) => void |
- | Selection change callback |
Hooks
useSelection()
Used inside a SelectionProvider to access or manipulate the active selection.
const {
selection, // Current active selection object
clearSelection, // Function to clear all selections in the provider
setSelection, // Manually set the selection
onSelectionChange, // Standard handler for SelectableSkiaText
} = useSelection();Architecture
- Skia Paragraph API: Used for advanced text layout and measuring glyph positions.
- Selection Coordination: Controlled via React Context and internal unique instance IDs.
- Gesture Performance: All gestures run on the UI thread using Reanimated worklets for lag-free handle dragging.
Development
# Install dependencies
bun install
# Build the library
bun run build
# Run example app
cd apps/example
bun run ios # or βandroidβLicense
MIT