Back to API Reference
Class

UniTextEditable

sealed
Inherits:MonoBehaviour
Implements:ITextDocumentISavedStateProviderIInputBehaviorChangeSinkISelectHandlerIDeselectHandlerISubmitHandlerICancelHandlerIUpdateSelectedHandler

Editing capability for UniTextSelectable: text storage (gap buffer), undo/redo, IME composition, validators, caret rendering, input intents, touch gesture pipeline, keyboard / clipboard handling, and the public mutation API (InsertText, Cut/Copy/Paste, Undo/Redo, etc.).

Remarks

The component requires UniTextSelectable on the same GameObject as UniTextBase; form-field policies are composed through input behaviors. Add a ContentSizeFitter or place it under a layout group to size its RectTransform from the text; sizing is measured through the UniTextBase component's own ILayoutElement implementation. A pointer click activates it and places the caret; Unity UI navigation reaches it through the hidden UniTextFocusable the editor manages automatically. Put it directly under a RectMask2D to make that parent the clipping viewport and enable internal scrolling when content overflows.
public OrderedEvent<InputEdit> InputFilter{ get }

Hook: veto or rewrite any document mutation before it applies — typing, paste, IME commit, deletions, cut, transpose. Not consulted for in-progress IME composition, undo/redo replay, or programmatic Text writes. Hooks run by ascending order, each seeing the previous one's result; equal orders retain subscription order and Rejected is sticky. Behaviors subscribe in their OnEnable.

public OrderedEvent<KeyResolve> KeyResolver{ get }

Ordered hook for contributing a key-to-action binding before the platform key map. Lower orders resolve first; after one sets an action, later hooks must preserve it.

public OrderedEvent<KeyboardRequest> KeyboardResolver{ get }

Ordered hook for composing keyboard configuration each time the soft keyboard is shown. Lower orders contribute first; equal orders retain subscription order.

public LengthLimit LengthLimit{ get; set }

Length cap published by the enforcing behavior (LengthLimitBehavior) for counters to display; Max 0 = none. Read-only for consumers — enforcement and configuration live on the behavior, and it republishes on every edit, so an external write here would neither cap input nor survive.

public UniTextSelectable Selectable{ get }

Sibling selection component on the same GameObject. Resolved once via GetComponent<T>; RequireComponent guarantees presence.

public TextSelection Selection{ get }

Current caret or selection range.

public UniTextBase TextComponent{ get }

Text component whose document this editor mutates.

public int CodepointCount{ get }

Number of codepoints in the currently navigable editing view: visible document in Hidden, synthesized source in Raw or Reveal.

public int CharCount{ get }

Number of UTF-16 units in the currently navigable editing view.

public int Version{ get }

Monotonic document version incremented after committed edits.

public string Text{ get; set }

Serialized source representation of the attributed document. Setting imports configured markup; getting preserves the imported source byte-for-byte until an edit and otherwise exports current spans.

public string VisibleText{ get }

Visible document text without serialized markup, independent of the current markup presentation mode.

public int CaretPosition{ get; set }

Caret position (codepoint index). Equivalent to Selection.Focus.

public int SelectionStart{ get }

Selection start (codepoint index, inclusive).

public int SelectionEnd{ get }

Selection end (codepoint index, exclusive).

public string SelectedText{ get }

Currently selected text. Allocates a string. Empty when no selection.

public bool ReadOnly{ get; set }

Read-only mode. Text can be selected and copied but not edited.

public bool ArrowKeyEscapesFormatting{ get; set }

Whether a repeated outward arrow at a formatting boundary clears an explicitly retained typing context. Off unless published by TextFormattingBehavior.

public bool IsActive{ get }

True while the editor is active, including while its input source is completing release.

public bool IsComposing{ get }

True while an IME composition (marked text) is in progress.

public bool CanUndo{ get }

True when an undo step is available.

public bool CanRedo{ get }

True when a redo step is available.

public MarkupVisibility MarkupVisibility{ get; set }

How this field presents its markup tags — hidden and atomic (default), revealed around the caret, or shown as raw source. Replaces the former AutoConvert flag.

public List<ChromeRule> MarkupChrome{ get }

Rules styling the markup tag characters wherever they are visible — every tag under Raw, the caret's tags under RevealActiveRange. Each rule's Selector picks which markup it targets; rules of different modifier kinds compose, same-kind rules resolve by specificity. Call RefreshMarkup after mutating at runtime.

public IReadOnlyList<BaseModifier> ModifiersAtCaret{ get }

Modifiers currently covering the caret / selection. Reused list — copy to keep.

public static UniTextEditable ActiveEditor{ get }

Currently active editor across the application — THE "current editor" authority. Selection UI (ISelectionHandles / IInsertionHandle, IMagnifier, ITextContextMenu) pulls geometry and document state from here at call time — implementations are never bound to a specific field, so they can never render against a stale one. Set on Activate, cleared when Deactivate completes.

public PlainTextPastePolicy PlainTextPaste{ get; set }

How plain-text paste is interpreted: Literal inserts it verbatim, Parse reparses it as this field's markup, Auto (default) picks by MarkupVisibility.

public bool RichPaste{ get; set }

Whether paste reads the formatting channels (UniText source, HTML, Markdown). Off — every paste inserts the clipboard's plain text only, regardless of what the source app offers.

public TypingMarkupPolicy TypingMarkup{ get; set }

Whether hand-typed markup is parsed or kept literal — see TypingMarkupPolicy. Default Parse.

public ValidationState Validation{ get }

Current content-validity state — written by validators (via AutoValidateBehavior) or app code through SetValidation, read by field decorators.

public int CopyTextTo()

Copies the currently navigable editing view into a caller-provided buffer. Returns the number of UTF-16 units written without allocating; use Text for serialized markup.

public bool TextEquals()

Compares the currently navigable editing view to a known string without allocation.

public bool TextEquals()

Compares the currently navigable editing view to a known string without allocation.

public T GetBehavior()

Returns the first attached behavior of type T, or.

public void GetBehaviors()

Appends every attached behavior of type T (local then preset) to results.

public void SetText()

Replaces the entire text content, resetting selection and undo history and discarding any in-progress composition.

public void SetTextProgrammatic(string value, bool recordUndo, bool preserveHistory, string reason)

Replaces the text from a non-user source (network sync, state restoration, remote collaboration), discarding any in-progress composition first.

public void MoveCaretTo()

Programmatically moves the caret to codepointIndex (clamped).

public void Select()

Programmatically selects the range [start, end] (clamped).

public void ClearUndoHistory()

Clears the undo/redo history.

public void RefreshMarkup()

Re-renders after a MarkupChrome mutation.

public bool IsStyleActive()

Whether typing now would produce T-styled text — the toolbar state query: a pending typing style wins, otherwise the spans at the caret decide.

public bool IsStyleActive()
public bool IsStyleActive()

Whether typing now would produce text matching exemplar's style (by modifier signature — a composite matches its ordered child types). A pending typing style wins; otherwise the spans at the caret decide.

public bool TryGetStyleParameter()

The parameter the active T style carries at the caret / selection — the color-swatch query for toolbars. A pending typing style wins; otherwise the covering span's parameter is returned. when the style is not active.

public bool TryGetStyleParameter()
public bool TryGetStyleParameter()

The parameter the active style matching exemplar carries at the caret / selection — the color-swatch query for toolbars. A pending typing style wins; otherwise the covering span's parameter is returned. when the style is not active or its value is mixed.

public void Activate()

Activates the editor, optionally requests a soft keyboard, and makes the caret visible. Queues the request while another editor is still releasing its input source.

public void Deactivate()

Begins releasing the current editing session and completes after its input source has quiesced. The editor remains active until completion; repeated requests are idempotent.

public void Defocus()

Releases input focus the canonical way: clears the EventSystem selection when this editor holds it (which deactivates via OnDeselect), otherwise deactivates directly.

public void OnAttachedToCell()

Invoked by a virtualised list host (Android RecyclerView, iOS UITableView, Unity scroll-pool, custom) when this editor's GameObject is recycled into a new cell position. Re-arms input lazily on the next focus. The owning component is expected to call RestoreState first when state needs to be preserved across reuse.

public void OnDetachedFromCell()

Releases editing state and invokes completion when the object may be safely recycled by its virtualised-list host.

public void HandleScroll()

Handles mouse wheel scroll. Arrives through the editor's own IScrollHandler; custom gesture pipelines call directly. No-op standalone (no clipping viewport) or while the content fits the viewport.

public Vector2 GetCaretScreenPosition()

Screen-space caret position for codepointIndex (document space) — bottom picks the caret rect's bottom or top edge. The geometry query selection-UI implementations (ISelectionHandles, IMagnifier, system toolbars) issue against ActiveEditor to place themselves.

public void InsertText(string text)

Inserts text at the current caret position, replacing any active selection. Convenience overload that accepts a string. See InsertText.

public void InsertText(ReadOnlySpan<char> text)

Inserts text at the current caret position, replacing any active selection. Applies the configured input-filter chain and records the accepted edit for undo.

public void DeletePrevious()

Deletes the current selection or the grapheme cluster before the caret.

public void DeleteNext()

Deletes the grapheme cluster after the caret, or deletes the current selection. Equivalent to the Delete key. Document-space cluster resolution — see DeletePrevious.

public void DeleteSelection()

Deletes the currently selected text range and collapses the selection to the start of the deleted range. Does nothing if there is no selection.

public void DeleteWordPrevious()

Deletes from the caret to the previous word boundary, or deletes the selection. Equivalent to Ctrl+Backspace (Windows) / Option+Backspace (macOS).

public void DeleteWordNext()

Deletes from the caret to the next word boundary, or deletes the selection. Equivalent to Ctrl+Delete (Windows) / Option+Delete (macOS).

public void DeleteToLineStart()

Deletes from the caret to the start of the current line. Equivalent to Cmd+Backspace (macOS).

public void DeleteToLineEnd()

Deletes from the caret to the end of the current line. Equivalent to Ctrl+K (macOS Emacs kill-line).

public void TransposeCharacters()

Swaps the two grapheme clusters before the caret. If the caret is at position 0, does nothing. If the caret is at position 1 (only one cluster before it), does nothing. Equivalent to Ctrl+T (macOS Emacs transpose-chars).

public void Copy()

Copies the selected text to the system clipboard. Does nothing if there is no selection or if the field is in password mode. Walks every built-in clipboard adapter and writes the resulting items as one atomic multi-format clipboard transaction (plain text + custom UniText format + optional HTML / Markdown), so the consumer's paste picks the richest format it understands. When the selection's markup is visible to the user — Raw, or a revealed range under RevealActiveRange — the copy carries only that visible text as plain text and no semantic channels: what is on screen is what pastes.

public void Cut()

Cuts the selected text to the system clipboard (copy + delete selection). Does nothing if there is no selection or if the field is in password mode.

public void Paste()

Pastes text from the system clipboard at the current caret position, replacing any active selection. Probes the built-in clipboard adapters by Priority descending — a cheap HasFormat availability check, then one payload transfer, then deserialize; the first success wins, so only one format ever crosses the clipboard. UniText source (lossless custom format) wins over HTML / Markdown, which win over plain text. The adapter resolves the payload to visible text and destination formatting spans, then inserts both in one document transaction. A format transfers only when the field has a style that renders it; unmatched formatting degrades to plain text. Plain text inserts verbatim.

public void PastePlain()

Pastes the plain-text clipboard channel only, ignoring rich formats — the paste-without-formatting command (Ctrl+Shift+V / Shift+Cmd+V).

public Task PasteAsync()

Async variant of Paste. Required on WebGL for programmatic paste (toolbar icon, context menu, autofill). This is the batched collect-all read: every requested format arrives in ONE underlying clipboard access via GetItemsAsync (WebGL's single-user-activation rule allows exactly one read); must be awaited from a user-activation context on WebGL. A provider without the async seam degrades to the sync Paste probe. Runs the same pipeline, including the MediaReceived hook.

public Task PastePlainAsync()

Async variant of PastePlain — the WebGL-safe paste-without-formatting command. Same activation-context contract as PasteAsync.

public void PasteFromItems()

Pastes pre-extracted clipboard items through the adapter pipeline, bypassing Provider. Used by iOS UIPasteControl and drag-drop drop sites to avoid a second pasteboard read (which on iOS would surface the system permission prompt). A format transfers only when the field has a style that renders it.

public void Undo()

Undoes the most recent edit (a whole transaction group counts as one edit) and restores the pre-edit selection (anchor / focus / affinity).

public void Redo()

Redoes the most recently undone edit (a whole transaction group counts as one edit), placing the caret at the end of the re-applied text.

public void SelectAll()

Selects the entire text content (anchor = 0, focus = codepointCount).

public void ApplyStyleRange()

Applies T to the visible codepoint range. Undoable.

public void SetStyle()

The single style-edit primitive over the document range: applies the modifier (on = true) or removes it. Apply, remove, toggle, and clear all route here. A null exemplar with on false clears every recognised style.

public void ApplyStyle()

Applies T with parameter to the selection, or stores it as the pending typing style at a collapsed caret (SET semantics for value pickers).

public void RemoveStyleRange()

Removes T's tags from the codepoint range. Undoable.

public bool ToggleStyle()

Toggles T on the selection — wraps when any part is unstyled, strips when fully styled. With a collapsed caret, flips the pending typing style. Returns whether on.

public bool ToggleStyle()

Toggles the component's style matching exemplar (by modifier signature — a composite matches its ordered child types) on the selection, or the pending typing style at a caret. No-op when the component has no matching style with a wrappable rule. Returns whether on.

public void ClearFormatting()

Strips every style tag from the selection (clear-formatting), or resets typing styles at a collapsed caret so the next inserted text is plain. At a range edge, the default typing context is already outside; an explicitly retained context is cleared as one set.

public void InsertObject()

Inserts an inline object styled by T at the caret — a self-closing tag when the component has a tag style for it, otherwise a bare Object Replacement Character.

public void RequestDefocusAfterSubmit()

Called by a submit-defining behavior during Submitted dispatch to release focus once the dispatch completes — deferred so every subscriber observes a still-focused editor regardless of subscription order.

public void SetValidation()

Sets the validation state and fires ValidationChanged. The editor only holds the state; what to validate and when lives in an AutoValidateBehavior or app code (set Pending while an async check runs, then the result).

public MediaReceivedHook MediaReceived

Hook: consume media — a paste, a drag-and-drop, or a picker selection — before the text-adapter pipeline. Behaviors subscribe in their OnEnable; see MediaInputBehavior.

public Action<EditShape> EditApplied

Occurs synchronously after a committed edit and before the frame-coalesced TextChanged event.

public Action TextChanged

Occurs when document text or attributed ranges change. Read the navigable view without allocation through CharCount, CopyTextTo, and TextEquals; read serialized markup through Text.

public Action<string> ValueChanged

Occurs when document text or attributed ranges change. Provides the full serialized source string and allocates only when subscribed.

public Action<string> DocumentChanged

Occurs when the text content has changed, alongside TextChanged, with the originating TextChangeReason string — distinguishes user typing (input.type) from paste (input.paste), programmatic mutation (program.set), IME commit (input.type.compose), and undo/redo replay (input.restore). Everything under input.* is user-originated.

public Action<string> Submitted

Occurs when the user has submitted. Enter inserts a newline by default — a submit-resolving behavior defines what submits: SingleLineBehavior (Enter, form field) or SubmitKeyBehavior (Enter or Ctrl/Cmd+Enter, composer). Gamepad submit (EventSystem) also fires this. Carries the current text snapshot. Post-submit focus is the submit-defining behavior's policy — both carry KeepFocusOnSubmit with archetype defaults: SingleLineBehavior releases focus (form), SubmitKeyBehavior keeps it (composer); without one, focus stays.

public Action Cancelled

Occurs when the user has cancelled editing — Escape (desktop), system back (mobile). The editor does not deactivate automatically; add DefocusOnCancelBehavior or subscribe directly when cancellation should release focus. Android delivers the back key only where the platform routes it to the app: an app opted into OnBackInvokedCallback dispatch (Unity's Predictive Back Support), and Android 13/14 while the keyboard is showing, dismiss the keyboard without raising this.

public Action Focused

Occurs when the editor has gained input focus (activated) — by pointer, navigation, or programmatic select.

public Action<EditingEndReason> Defocused

Occurs when the editor has lost input focus (deactivated), carrying how the session concluded. Submitted and Cancelled report the user's intent while editing continues; this reports the end itself.

public Action<int,int> SelectionChanged

Frame-coalesced selection-change notification. Parameters: (selectionStart, selectionEnd) in codepoint indices. Fires at most once per frame after SelectionChanged mutations have settled.

public Action<bool> CompositionStateChanged

Occurs when IME composition state changes — fires on start, on commit or cancel.

public Action<CaretContext> CaretContextChanged

Occurs (frame-coalesced) when the set of modifiers covering the caret / selection has changed — on caret movement, selection change, or reflow — and when a pending typing style flips (re-query IsStyleActive<T>). Subscribe from an InputBehavior or see CaretContextBehavior for the inspector-wired form.

public Action<ValidationState> ValidationChanged

Occurs when Validation has changed.