Expand description
Native-grade text selection primitives for BasicTextField.
This module holds the pure, unit-tested building blocks the text field uses to offer Android/iOS-style selection: tap-count classification, word and line/paragraph boundary detection, and the geometry of the draggable teardrop selection handles (their shapes, their hit regions, and the selection math that a handle drag produces).
Keeping these as free functions makes the touch behavior testable without a
renderer and keeps TextFieldModifierNode focused on wiring.
Enums§
- Handle
Kind - Which selection handle a teardrop represents.
- Selection
Granularity - The unit of text a tap gesture selects, growing with the tap count the way
mature text editors do (Android
TextView, iOSUITextView, VS Code):
Constants§
- HANDLE_
GRAB_ SLOP - Finger-sized grab slop (px) added around a handle’s drawn teardrop to enlarge
its touch target, matching Android’s generous handle hit area. A bare
teardrop (~2·
HANDLE_RADIUSacross) is far smaller than a fingertip, so a touch-DOWN aimed at a handle routinely lands a few px off it; without this slop the press falls through to the field below and places a caret, which collapses the selection. The slop is applied to the sides and BELOW the tip (where the bulb and the grabbing finger sit) but never ABOVE the tip — seecrate::widgets::selection_handle, which keeps the box off the glyph line so a double-tap still reaches the field to escalate into a word selection. - HANDLE_
RADIUS - Radius of a selection/cursor handle bulb in px (Android uses ~11dp).
- MULTI_
TAP_ SLOP_ PX - Maximum distance (px) between consecutive taps that still counts as a
multi-tap. A tap that lands far from the previous one starts a fresh
single tap even if it arrives quickly, matching Android’s
ViewConfigurationdouble-tap slop behavior. - MULTI_
TAP_ TIMEOUT_ MS - Maximum time between taps that still counts as a multi-tap, in milliseconds.
Functions§
- caret_
visual_ line - Given the source byte ranges of the visual (wrapped) lines and a caret
byte
offset, returns the(visual_line_index, line_start_byte)the caret sits on. - classify_
tap_ count - Classifies a press into a 1-based tap count from the previous tap’s count, the time since it, and the distance from it.
- find_
line_ boundaries - Returns the byte range
[start, end)of the line containingpos, delimited by\n(the newline itself is excluded from the range). - find_
paragraph_ boundaries - Returns the byte range
[start, end)of the paragraph containingpos. - handle_
path_ data - SVG path data for a handle teardrop whose tip sits at
(tip_x, tip_y). - resolve_
selection_ tap_ count - Resolves the effective tap count for a press, folding in the “tap inside an
existing selection” gesture so it drives the same word → line → paragraph
granularity ladder (
tap_selection_granularity) as a rapid multi-tap. - selection_
after_ handle_ drag - Computes the selection
(min, max)that results from dragging one handle to a new textoffset, keeping the opposite (fixed) edge anchored. - tap_
selection_ granularity - Maps a 1-based tap count to the granularity it selects.