docs/solutions/ui-bugs/2026-05-07-slate-react-native-ime-history-boundaries-need-explicit-push-metadata.md
Lexical's #2479 history row separates delayed IME/native text commits into
distinct undo steps. Slate's browser runtime imported the same native edits as
adjacent insert_text operations, and generic Slate history merged adjacent
text operations until something structural interrupted them.
undoes delayed Hiragana IME compositions as separate history steps inserted すし もじあ, but one undo returned the editor to the
initial document.a plus immediate IME す should still undo together.slate-history adjacent text merge heuristic. It has
no browser input timing context.Track the last browser-native text input time inside slate-react and attach
history: { mode: 'push' } only when the next browser-native text commit lands
after the merge interval.
The policy lives in
.tmp/slate-v2/packages/slate-react/src/editable/input-history.ts:
export const getNativeTextInputHistoryMetadata = (
editor: Editor,
): EditorUpdateMetadata | undefined => {
const currentTime = now();
const previousTime = EDITOR_TO_LAST_NATIVE_TEXT_INPUT_TIME.get(editor);
EDITOR_TO_LAST_NATIVE_TEXT_INPUT_TIME.set(editor, currentTime);
if (
previousTime !== undefined &&
currentTime - previousTime > NATIVE_TEXT_INPUT_HISTORY_MERGE_INTERVAL_MS
) {
return { history: { mode: "push" } };
}
};
Apply that metadata when the browser runtime imports native text:
compositionend fallback insertion in composition-state.tsdom-repair-queue.tsKeep the composition-predelete path on forced merge, because that path repairs
one logical composition commit.
The generic history package should not guess browser pause semantics from operation shape. Browser-native text input is the layer that knows when a real user input commit happened, so it can label delayed commits as new undo units.
Immediate native typing and immediate IME composition still merge because the metadata helper returns no explicit push inside the interval. Delayed input commits push a fresh batch before history's adjacent-text heuristic can merge them.
history metadata at the browser input boundary over global
changes to slate-history unless the generic history contract itself is
wrong.