Overview
The insertCompositionText inputType is triggered during IME (Input Method Editor) composition when text is being composed. This is particularly relevant for languages that require composition, such as Chinese, Japanese, and Korean.
Basic Behavior
Scenario: Korean IME composition
During composition (typing "한")
After committing (pressing Enter/Space)
IME Composition Flow
1. Composition Start
compositionstartevent fires- User begins typing characters that require composition
2. Composition Update
compositionupdateevent firesinsertCompositionTextinputType may fire inbeforeinputorinputevents- Composition text is shown (often with underline or highlight)
3. Composition End
compositionendevent fires- Final text is committed to the DOM
- May trigger
insertTextorinsertCompositionTextevents
Browser-Specific Behavior
Chrome/Edge
- Fires
insertCompositionTextduring composition updates - Composition text is shown with underline styling
- May fire multiple
insertCompositionTextevents as user types
Firefox
- Similar behavior to Chrome
- Composition handling may differ slightly
Safari
- IME composition behavior may differ, especially on macOS
- May use different event patterns
Critical Edge Cases
⚠️ macOS Korean IME + Formatting Shortcuts
macOS + Korean IME: During IME composition with a collapsed cursor, pressing formatting shortcuts (e.g., Cmd + B) may cause unexpected behavior:
- Formatting
beforeinputevent may not fire insertCompositionTextmay fire instead- Composition may be cancelled or committed partially
See formatBold - IME Composition for detailed workarounds.
⚠️ Composition Cancellation
Pressing certain keys during composition (e.g., Backspace, Delete, Escape) may cancel the composition:
- Composition text may be lost
- More text than expected may be deleted
- Event order may be unpredictable
See deleteContentBackward - IME Composition for details.
Editor-Specific Handling
Different editor frameworks handle IME composition differently. Here's how major editors implement insertCompositionText:
IME Composition Handling
Slate tracks composition state and handles composition text:
import { Editor, Transforms } from 'slate';
let isComposing = false;
element.addEventListener('compositionstart', () => {
isComposing = true;
});
element.addEventListener('beforeinput', (e) => {
if (e.inputType === 'insertCompositionText' && e.data) {
e.preventDefault();
// Insert composition text
Transforms.insertText(editor, e.data);
}
});
element.addEventListener('compositionend', () => {
isComposing = false;
// Finalize composition text if needed
});
- Composition state: Tracks composition state separately from regular text insertion.
- Text insertion: Uses
Transforms.insertText()to insert composition text. - State management: Maintains composition state to handle edge cases.
IME Composition Handling
ProseMirror uses composition state in the view:
view.dom.addEventListener('compositionstart', () => {
view.composing = true;
});
view.dom.addEventListener('beforeinput', (e) => {
if (e.inputType === 'insertCompositionText' && e.data) {
e.preventDefault();
const { state, dispatch } = view;
// Insert composition text
if (insertText(state, e.data, state.selection.$from.marks(), dispatch)) {
// Handled
}
}
});
view.dom.addEventListener('compositionend', () => {
view.composing = false;
});
- View.composing: ProseMirror tracks composition state in
view.composing. - insertText command: Uses same
insertTextcommand as regular text insertion.
IME Composition Handling
Draft.js handles composition through input events:
let isComposing = false;
element.addEventListener('compositionstart', () => {
isComposing = true;
});
element.addEventListener('beforeinput', (e) => {
if (e.inputType === 'insertCompositionText' && e.data) {
e.preventDefault();
const contentState = editorState.getCurrentContent();
const selection = editorState.getSelection();
const newContentState = Modifier.insertText(
contentState,
selection,
e.data,
editorState.getCurrentInlineStyle()
);
const newState = EditorState.push(
editorState,
newContentState,
'insert-characters'
);
setEditorState(newState);
}
});
element.addEventListener('compositionend', () => {
isComposing = false;
});
- Composition tracking: Tracks composition state to handle edge cases.
- Modifier.insertText: Uses
Modifier.insertText()to insert composition text.