Text and input API
Declared by <huxerui/text.h>, <huxerui/text_input.h>, <huxerui/validation.h>, and <huxerui/clipboard.h>.
Fonts and styles
Section titled “Fonts and styles”FontFamilyKind:System,Monospace, orNamed.FontWeight:Thin,ExtraLight,Light,Regular,Medium,SemiBold,Bold,ExtraBold, orBlack.FontSlant:NormalorItalic.Font:System(size), named/fallback family construction, and fluent size/weight/slant updates; equality compares descriptor values.TextDecoration:None,Underline,StrikeThroughflags; bitwise|,&, andHasTextDecorationsupport combinations.TextStyle:font,foreground, anddecoration.
Shaping and layout
Section titled “Shaping and layout”TextDirection:Auto,LeftToRight, orRightToLeft.TextShapingOptions: locale/language and direction inputs.TextAlign:Leading,Center, orTrailing.TextWrap:NoWraporWord.TextLayoutOptions: shaping options, alignment, and wrapping; maximum width is the separateMeasureTextargument.FontMetrics,TextRunMetrics, andTextLayoutMetrics: ascent/descent/leading, run geometry, overall size, baselines, and line data.TextMeasurerplatform interface andUseTextMeasurer()extension hook.
Editing values
Section titled “Editing values”TextOffsetis signed 64-bit;TextInputSessionIdis unsigned 64-bit.TextAffinity:UpstreamorDownstream;TextPosition,TextRange, andTextSelectionmodel caret/range state.TextEditingValuecontains UTF-8 text, selection, and composition range with validation/equality helpers.
IME command boundary
Section titled “IME command boundary”TextInputCommandKind values are SetSelection, BeginComposition, UpdateComposition, CommitText, FinishComposition, CancelComposition, and DeleteSurrounding.
TextInputCoordinateSpace is Text or Composition; TextInputUnit is Utf16CodeUnit or UnicodeCodePoint.
TextInputCommand and TextInputCommandBatch carry revisioned platform edits.
-
TextInputType:Text,Email,Number,Decimal,Phone, orUrl. -
TextCapitalization:None,Characters,Words, orSentences. -
TextInputAction:Default,Done,Go,Next,Search,Send, orNewline. -
TextInputConfiguration: type, capitalization, action, multiline, secure, autocorrect, and read-only flags. -
TextInputResultCode:Ok,SessionMismatch,Rejected, orReadOnly. -
TextInputSyncAction:None,Update, orRestart. -
TextInputEndReason:FocusLost,ClientRemoved,Disabled,ReadOnly, orRuntimeDestroyed. -
TextInputKeyResult:UnhandledorHandled. -
State/result structures:
TextInputState,TextInputApplyResult,TextInputContext,TextInputGeometry, andTextInputPositionResult.
TextInputClient and TextSelectionClient are mounted extension interfaces. PlatformTextInput is the adapter interface for begin/update/end session, keyboard, geometry queries, selection menus, and platform synchronization.
Validation
Section titled “Validation”ValidationStatus is None, Valid, Invalid, or Pending. ValidationResult has named factories and IsInvalid. Required and EmailAddress accept optional localized messages. Validate(value, rules...) evaluates until a rule is non-valid.
Clipboard
Section titled “Clipboard”TextEditingAction is Cut, Copy, Paste, or SelectAll. TextSelectionMenuLabels supplies localized labels. Clipboard is obtained with UseApplication().Clipboard(). On the UI thread, check IsAvailable(), use ReadText() for an optional string, and WriteText(text) for a success flag. Invalid UTF-8 is rejected. An unavailable or disconnected service fails safely. The Web service is unavailable; browser-owned TextField clipboard operations are a separate path.
Complete controlled TextField example
Section titled “Complete controlled TextField example”#include <huxerui/huxerui.h>
using namespace huxerui;
[[huxerui::composable]]View AccountEmail() { auto email = UseState(TextEditingValue::FromText(""));
return TextField(email) .Label("Email") .Placeholder("name@example.com") .Variant(TextFieldVariant::Outlined) .InputConfiguration({ .type = TextInputType::Email, .action = TextInputAction::Done, }) .Validation(Validate(email->text, Required(), EmailAddress())) .OnChanged([email](const TextEditingValue& next) { email = next; });}Writing the complete event value preserves selection, affinity, and composition. Validation reports domain state and does not rewrite the edit.
Attributed text and links
Section titled “Attributed text and links”TextSpan(text).Style(TextSpanStyle).Link(Uri) builds character runs. AttributedText accepts text, an initializer list of spans, or a span range. It owns shared immutable text/styles/links; copying it is suitable for State and component arguments.
AttributedText::FromRanges(text, styles, links = {}) accepts UTF-16 ranges. Each style/link list must be ordered and non-overlapping within itself; endpoints must not split surrogate pairs. Style and link ranges are independent and may cross one another. WithStyles(...) replaces styles while preserving the shared body and links. PlainText(), Length(), StyleRanges(), LinkRanges(), and TextInRange() inspect content.
TextSpanStyle partially overrides font, size, weight, slant, foreground, background, and decoration. An unset field inherits; TextDecoration::None explicitly clears decoration. It is not a complete TextStyle replacement.
TextEvents::LinkActivated provides a TextLinkActivation. Links do not open themselves: decide whether to navigate internally, invoke application policy, or open an allowed external target. See Text for a complete example.
Selection across virtual content
Section titled “Selection across virtual content”TextSelectionSource is an immutable logical snapshot with Count(), IdAt(), IndexOf(), and BlockAt(). Each TextSelectionBlock contains attributed text and a separator (newline by default). IDs are TextBlockId, stable across reorder rather than derived from current positions.
Attach a source with SelectionArea::Source(snapshot) and identify each rendered Text using SelectionBlock(id). This lets copying traverse offscreen logical blocks. A rendered Text must match its entire source block. Source methods must return synchronously and without I/O; publish a new snapshot when content changes.
Build selection values correctly
Section titled “Build selection values correctly”TextSelection{anchor, active, affinity} preserves selection direction. Range() orders the endpoints into a half-open TextRange; it does not validate them against text or preserve which end is active. IsCollapsed() only compares endpoints. Endpoints must be in bounds in UTF-16 units and cannot split a surrogate pair.
TextEditingValue::FromText validates UTF-8, places a downstream caret at the UTF-16 end, and clears composition. That is appropriate for loading/resetting a document, not for accepting a user’s normal edit. Copy the complete OnChanged proposal for ordinary typing so selection direction and provisional IME composition survive.
composition = std::nullopt means no composition. A collapsed composition range is still an active composition; do not test its length to decide whether IME work exists. Input session IDs and synchronization revisions belong to the input client/adapter, not application TextEditingValue.
Validation timing and rule composition
Section titled “Validation timing and rule composition”ValidationResult::None() means no validation presentation, Valid() means checked and valid, Invalid(message) supplies an error, and Pending(message = {}) reports unfinished validation. IsInvalid() tests only the Invalid status. Validate starts at Valid and stops at the first rule returning anything other than Valid, including None or Pending.
The built-in Required and EmailAddress rules are synchronous. For remote validation, publish an application-owned Pending result, launch a scoped request, and replace it only if the result still corresponds to the current input. Cancel obsolete tasks or track request identity. Do not make the rule itself block or launch a request on every render.
Decide whether to show errors immediately, after editing, or after submission in application state. For example, choose between None and Validate based on a submitted flag. Validation does not reject keyboard input, change selection, or rewrite text; use the editor’s length/line policies for input mechanics.
App API versus adapter API
Section titled “App API versus adapter API”Applications normally use TextField, TextEditingValue, input hints, and ValidationResult. A custom input extension implements TextInputClient only when it truly owns an editor; a platform backend implements PlatformTextInput to connect IME operations. These interfaces are not necessary for changing a field’s keyboard type or adding an action.
At that boundary, keep the captured nonzero session ID and current revision with every delayed edit. A stale session must not target the next focused field. Commands use the declared TextInputCoordinateSpace and TextInputUnit, validate the batch against the current value, and preserve the distinction between text UTF-8 bytes, UTF-16 offsets, Unicode scalars, and grapheme limits. See the TextField component for the application-facing configuration surface.

