Expand description
day-piece-texteditor: a styled-text editor bound two-way to a Signal<StyledText>
(docs/texteditor.md).
let doc = Signal::new(StyledText::markdown("**Hello**, _world_.", Font::Body));
let sel = Signal::new(0..0);
column((
// The toolbar is ordinary Day pieces; the piece ships no chrome of its own.
button("B").action(move || doc.update(|d| {
let on = !d.style_of(sel.get_untracked(), Font::Body).bold();
d.apply(sel.get_untracked(), Font::Body, move |s| s.set_bold(on));
})),
text_editor(doc).selection(sel).min_lines(8),
))It edits the same StyledText a label renders and the Markdown / HTML / RTF codecs read and
write, in each platform’s own rich-text view: NSTextView, UITextView, GtkTextView,
QTextEdit, an EditText over a SpannableStringBuilder, RichEditBox, the ArkTS
RichEditor, and a contenteditable element. There is no composed tier and there must not
be one: a hand-rolled editor loses IME composition, bidirectional cursor movement, the
platform’s undo stack, dictation, and the accessibility tree, and loses them invisibly.
§Who owns the attributes
Day does. The native view owns the characters (typing, deletion, IME, undo, autocorrect)
and reports them as Event::TextChanged; the piece diffs that against the text it last knew,
reflows its runs over the edit (StyledText::reflow), and writes the signal. Attributes only
ever travel Day → native.
That is why every arm turns the platform’s own formatting UI off (iOS’s
allowsEditingTextAttributes, the macOS font panel) rather than reading it back: an editor
whose attributes can change from two directions has to reconcile them, and reconciling an
attributed string across eight toolkits is a much larger promise than this piece makes.
Everything a toolbar does goes through the bound signal instead, in Rust, where it behaves
identically on all nine targets and is testable on the headless one. docs/texteditor.md records
the per-toolkit hook a future read-back would use.
Modules§
- highlight
- Syntax highlighting as runs (docs/texteditor.md §9): a tokenizer is a pure function from text
to
Vec<TextRun>, andTextEditor::highlightre-runs it on every edit and pushes the runs back as an attributes patch, so the caret and the undo stack stay where they are. Nothing here touches a toolkit; the same runs restyle all eight arms, and a test asserts them on the headless one.
Structs§
- Editor
Props - Full props (realize). Only
doc,selectionandeditablechange after build. - Text
Editor - A styled-text editor bound two-way to a
StyledTextsignal. Build withtext_editor.
Enums§
Constants§
- HIGHLIGHT_
LIMIT - The size past which a live highlighter leaves the text plain (512 KiB); see
TextEditor::highlight_limit. - KEY_
PREFIX - The prefix a claimed key rides on that same channel:
"key Enter","key Tab", the day key name anEvent::Keywould carry on a backend that can send one. - KIND
- SEL_
PREFIX - The prefix a selection report carries in its payload. The tag cannot cross a JNI / C-ABI / JS
boundary (§8.2), so the payload has to be self-describing:
"sel <start> <end>", in BYTE offsets, which every arm converts into from its own indexing. - TEXT_
PREFIX - The prefix a text report carries on the same channel, for a backend whose piece bridge can
only send
Event::Custom(HarmonyOS’s ArkTS side is the one that has to):"txt <the text>", the whole document, exactly asEvent::TextChangedcarries it.
Traits§
- Text
Editor Builder - Builder methods of
TextEditor, reachable through aDecorated(docs/api-style.md “Typed builders and erasure”): generic modifiers and typed ones chain in any order.
Functions§
- auto_
indent - The indentation a new line takes after Enter typed at
newline_at: the previous line’s leading whitespace, one level deeper when that line ends in an opening bracket.Nonewhen there is nothing to insert. - byte_
of_ char - A character offset back to a byte offset, clamped into the string.
- byte_
of_ utf16 - A UTF-16 offset back to a byte offset, clamped into the string.
- char_
range - A byte range as a character range (GTK’s
TextIter, ArkUI’s spans). - closer_
after - The closer to type after an opener typed at
at, when the caret sits at the end of its line or before whitespace or another closer:{[(and the two quotes.Nonewhere a closer would land inside a word. - diff_
edit - Recover a single contiguous edit from the old and new text:
(offset, removed, inserted)in bytes. - flatten
- A single-line editor’s text: every line break a space, byte for byte, so the offsets of an edit computed against the raw text still hold.
- selection_
payload - The selection payload every arm emits.
- support
- Whether the compiled backend edits styled text natively.
- tab_
indent - The spaces a Tab inserts at
caret: to the next tab stop of widthindent, counted in characters from the start of the caret’s line. - text_
editor text_editor(doc): the platform’s rich-text view over aStyledTextsignal.- text_
editor_ text text_editor_text(text): the same editor over a plainStringsignal, for an app whose model holds text rather than a document (a request body, a file). The piece keeps aStyledTextof its own: edits write the string, a string the app writes replaces the document’s text, and aTextEditor::highlightsupplies whatever styling there is.- text_
payload - The text payload for an arm that has only the custom channel; see
TEXT_PREFIX. - utf16_
range - A byte range as a UTF-16 range (Apple, Android, XAML).
Type Aliases§
- Highlighter
- What
TextEditor::highlighttakes: text in, runs over every byte of it out.