The text as of the current session's start — what a cancel reverts to.
The last COMMITTED text — what an idle revert returns to.
true when the text differs from the committed value's text.
dirty, synchronously.
Parse/validation error for the current text (a message key; null when valid).
error, synchronously (the commit gate runs inside event handlers).
The last successfully parsed value — what the commit channel delivers.
The live display text.
text readable synchronously (the handlers run outside render).
Whether the user has EDITED since the session started — what Escape claims the key on. Distinct
from dirty (text ≠ committed) and from "text ≠ baseline": a round-trip back to the
starting text leaves this true.
A session is starting: the CURRENT text becomes the cancel baseline.
Explicit cancel (a dialog's Cancel, the adornment ✗) — always fires the commit channel.
Explicit accept (a dialog's OK, the adornment ✓).
Read + clear the one-shot guard: true means a done key already delivered this gesture's commit
and the blur that follows it must not deliver a second one.
The shared done-key policy — Escape / Enter / Tab, per changeOn (see the module doc). Returns
true when the key was the field's to handle, so the host can stop there.
The keys a focused input owns NATIVELY — consume them so the app's command dispatch never sees
them. Returns true when the key was consumed; call AFTER handleDoneKeys.
Parse next → error state + last valid value, emitting on the live channel per changeOn.
Deliver the COMMIT channel once for a finished edit. An accept while the text is INVALID is swallowed (the stale last-valid value must not escape; the error stays shown to fix or Escape); a cancel always fires. A delivered accept re-bases the committed text, so the field reads clean and a follow-up blur cannot re-deliver the same accept.
Any new key resets the one-shot blur guard — call at the TOP of the host's key handler.
Adopt next as the committed text (an outside value change): clean, unerrored, revert target.
Optionalvalue: V | nullRestore the session-start text (a cancel) and re-parse it.
Restore the committed text (the idle, field-level Escape) and re-parse it.
Set the error state directly (e.g. clearing it alongside a revert).
Set the display text (and re-derive dirty). Does NOT parse — pair with liveChange.
The edit/commit state machine shared by every value-controlled field — the part of a field that has nothing to do with what it edits: the two baselines, the dirty flag, the live vs commit channels, and the done-key policy.
The rules it owns, once, for every field:
committedTextis the last ACCEPTED value;baselineTextis the text when the current session started. They differ because the live-change model applies every intermediate change — "the value before" can then only mean before-the-session, not before-the-last-change.onDonewithreason: 'cancel'). Idle + dirty → a plain revert to the committed text, no commit channel. An UNTOUCHED session → the key is NOT captured, so a host dialog still closes on it. "Touched", not "changed": an edit that lands back on the starting text is still one to Escape out of.changeOn: 'done'captures it (the field is the commit point);'live'lets it bubble to the host's default button, finishing any open session first.Hosts keep their own concerns — a formula field's reference bus and grammar, a plain field's validation — and wire them in through UseEditCommitOptions.parse and EditCommitSession.