Skip to content

Text and input API

Declared by <huxerui/text.h>, <huxerui/text_input.h>, <huxerui/validation.h>, and <huxerui/clipboard.h>.

  • FontFamilyKind: System, Monospace, or Named.
  • FontWeight: Thin, ExtraLight, Light, Regular, Medium, SemiBold, Bold, ExtraBold, or Black.
  • FontSlant: Normal or Italic.
  • Font: System(size), named/fallback family construction, and fluent size/weight/slant updates; equality compares descriptor values.
  • TextDecoration: None, Underline, StrikeThrough flags; bitwise |, &, and HasTextDecoration support combinations.
  • TextStyle: font, foreground, and decoration.
  • TextDirection: Auto, LeftToRight, or RightToLeft.
  • TextShapingOptions: locale/language and direction inputs.
  • TextAlign: Leading, Center, or Trailing.
  • TextWrap: NoWrap or Word.
  • TextLayoutOptions: shaping options, alignment, and wrapping; maximum width is the separate MeasureText argument.
  • FontMetrics, TextRunMetrics, and TextLayoutMetrics: ascent/descent/leading, run geometry, overall size, baselines, and line data.
  • TextMeasurer platform interface and UseTextMeasurer() extension hook.
  • TextOffset is signed 64-bit; TextInputSessionId is unsigned 64-bit.
  • TextAffinity: Upstream or Downstream; TextPosition, TextRange, and TextSelection model caret/range state.
  • TextEditingValue contains UTF-8 text, selection, and composition range with validation/equality helpers.

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, or Url.

  • TextCapitalization: None, Characters, Words, or Sentences.

  • TextInputAction: Default, Done, Go, Next, Search, Send, or Newline.

  • TextInputConfiguration: type, capitalization, action, multiline, secure, autocorrect, and read-only flags.

  • TextInputResultCode: Ok, SessionMismatch, Rejected, or ReadOnly.

  • TextInputSyncAction: None, Update, or Restart.

  • TextInputEndReason: FocusLost, ClientRemoved, Disabled, ReadOnly, or RuntimeDestroyed.

  • TextInputKeyResult: Unhandled or Handled.

  • State/result structures: TextInputState, TextInputApplyResult, TextInputContext, TextInputGeometry, and TextInputPositionResult.

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.

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.

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.

#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.

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.

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.

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.

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.

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.