Incular logoIncular
API ReferenceState & Async

UndoHistory

Widget-independent undo and redo over the editing controller.

UndoHistoryController observes the authoritative TextEditingController and exposes availability through a Signal, so only status readers rebuild.

MethodEffect
new(editor)Track from the current value
status() / state_signal()Tracked availability snapshot
can_undo() / can_redo()Capability queries
undo() / redo()Step history, returns success
clear()Drop history, keep text
set_max_entries(n)Capacity; 0 disables
use incular::prelude::*;

fn main() {
    let controller = TextEditingController::with_text("hello");
    let history = UndoHistoryController::new(controller.clone());
    controller.set_text("hello, world");
    let _ = history.undo();
    let app = Application::new(move |_cx| {
        Container::builder()
            .padding(EdgeInsets::all(24.0))
            .alignment(Alignment::CENTER)
            .child(Text::new(format!(
                "undo: {}, redo: {}",
                history.can_undo(),
                history.can_redo()
            )))
            .build()
            .into()
    })
    .expect("valid application");
    incular::run(app).expect("run application");
}

UndoHistoryState { can_undo: false, can_redo: false } by default. Wrap an editor in the UndoHistory widget to configure capacity declaratively with UndoHistory::new(editor).max_entries(100).

Policy: undoable = committed text transitions (typing, deletion, cut/paste, programmatic edits, IME commits); transient = preedit, selection, caret. Redo clears on the next text change; controller replacement restarts history; restoration rebaselines without recording a step.

Related: EditableText.