Add selection semantics: flows, boundaries, and semantic Text props - #985
Draft
chiga0 wants to merge 2 commits into
Draft
Add selection semantics: flows, boundaries, and semantic Text props#985chiga0 wants to merge 2 commits into
chiga0 wants to merge 2 commits into
Conversation
added 2 commits
August 3, 2026 13:51
Expose the composited frame as a read-only grid of cells that apps owning their input (e.g. alternate-screen apps handling mouse events) can subscribe to, and let them push a selection region that Ink highlights before serialization. Frames are only generated while subscribers are registered, listeners are notified outside the render pass with coalesced notifications, and selections are normalized to reading order so reverse drags work.
Build on the frame controller with the selection semantics needed to
extract copied text:
- `<Text>` gains `selectable`, `selectionFlow`, `selectionBreakAfter`,
and `selectionJoiner` props.
- Squashing text nodes now tracks per-node selection attributes, so
nested `<Text>` props (e.g. `selectable={false}`) survive instead of
being overwritten by the outer node's attributes.
- Frame cells expose `selectable` and `flowId`; frames carry a
`boundaries` grid describing how adjacent text joins when copied
(wrap points, source newlines, explicit `selectionBreakAfter`).
- The selection highlight skips non-selectable cells, matching what a
copy would include.
Semantics are only resolved when observable (cells captured or a
selection applied); the rendered output stays byte-identical to the
plain path.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Second part of the split suggested in #980, stacked on #984 (the diff against
masterincludes #984 until it merges — review that one first). Adds the selection semantics needed to extract copied text: flows, boundaries, and semantic<Text>props.What's included
<Text>gainsselectable,selectionFlow,selectionBreakAfter, andselectionJoinerprops (documented in the readme).selectableandflowId; frames carry aboundariesgrid describing how adjacent text joins when copied (wrap points with the consumed whitespace, source newlines, explicitselectionBreakAfterboundaries).Concerns from the #980 review addressed here
Textnodes are squashed — squashing now tracks per-node selection attributes (squashTextNodesWithMetadata), so an innerselectable={false}(orselectionFlowoverride) is preserved per cell instead of being overwritten by the outer node. Arbitrary<Transform>functions may rewrite visible text, so subtrees transformed by them fall back to one uniform segment (verified byte-identical output); color/style transforms keep full granularity.selectable(both directions), nesting through color transforms, highlight skipping non-selectable cells (ASCII, wide characters, box backgrounds), shared/distinct/nested flows, and boundary placement (hard,softwith custom joiner, source newlines, wrapping).Performance
Semantics are only resolved when they can be observed (cells captured or a selection applied), extending the opt-in from #984. With neither, the render path is unchanged. The semantic path produces byte-identical output to the plain path (verified for nested/colored text, wrapping, padding, wide characters, multi-line text).
Kept as a draft until #984 lands.