Lexical uses a command-based architecture for handling user interactions and editor actions. Commands provide a clean way to implement features and allow plugins to intercept and customize behavior.
Creating Commands
createCommand
function createCommand<T>(type?: string): LexicalCommand<T>
Creates a new command with an optional type identifier for debugging.
A debug label for the command
import { createCommand } from 'lexical';
type InsertImagePayload = {
src: string;
altText: string;
};
export const INSERT_IMAGE_COMMAND = createCommand<InsertImagePayload>('INSERT_IMAGE_COMMAND');
Built-in Commands
Text Commands
CONTROLLED_TEXT_INSERTION_COMMAND
CONTROLLED_TEXT_INSERTION_COMMAND: LexicalCommand<InputEvent | string>
Inserts text at the current selection.
editor.dispatchCommand(CONTROLLED_TEXT_INSERTION_COMMAND, 'Hello');
REMOVE_TEXT_COMMAND
REMOVE_TEXT_COMMAND: LexicalCommand<InputEvent | null>
Removes text at the selection.
FORMAT_TEXT_COMMAND
FORMAT_TEXT_COMMAND: LexicalCommand<TextFormatType>
Applies text formatting to the selection.
import { FORMAT_TEXT_COMMAND } from 'lexical';
editor.dispatchCommand(FORMAT_TEXT_COMMAND, 'bold');
editor.dispatchCommand(FORMAT_TEXT_COMMAND, 'italic');
Payload types:
'bold'
'italic'
'underline'
'strikethrough'
'code'
'subscript'
'superscript'
'highlight'
'lowercase'
'uppercase'
'capitalize'
Deletion Commands
DELETE_CHARACTER_COMMAND
DELETE_CHARACTER_COMMAND: LexicalCommand<boolean>
Deletes a character. Payload is true for backward (backspace), false for forward (delete).
editor.dispatchCommand(DELETE_CHARACTER_COMMAND, true); // Backspace
editor.dispatchCommand(DELETE_CHARACTER_COMMAND, false); // Delete
DELETE_WORD_COMMAND
DELETE_WORD_COMMAND: LexicalCommand<boolean>
Deletes a word. Payload is true for backward, false for forward.
DELETE_LINE_COMMAND
DELETE_LINE_COMMAND: LexicalCommand<boolean>
Deletes a line. Payload is true for backward, false for forward.
Insertion Commands
INSERT_PARAGRAPH_COMMAND
INSERT_PARAGRAPH_COMMAND: LexicalCommand<void>
Inserts a new paragraph.
editor.dispatchCommand(INSERT_PARAGRAPH_COMMAND, undefined);
INSERT_LINE_BREAK_COMMAND
INSERT_LINE_BREAK_COMMAND: LexicalCommand<boolean>
Inserts a line break. Payload is false to move cursor (Shift+Enter), true to not move (Ctrl+O on macOS).
editor.dispatchCommand(INSERT_LINE_BREAK_COMMAND, false);
INSERT_TAB_COMMAND
INSERT_TAB_COMMAND: LexicalCommand<void>
Inserts a tab character.
FORMAT_ELEMENT_COMMAND: LexicalCommand<ElementFormatType>
Sets element alignment.
editor.dispatchCommand(FORMAT_ELEMENT_COMMAND, 'center');
Payload types:
'left'
'center'
'right'
'justify'
'start'
'end'
'' (no alignment)
INDENT_CONTENT_COMMAND
INDENT_CONTENT_COMMAND: LexicalCommand<void>
Increases indentation.
OUTDENT_CONTENT_COMMAND
OUTDENT_CONTENT_COMMAND: LexicalCommand<void>
Decreases indentation.
History Commands
UNDO_COMMAND
UNDO_COMMAND: LexicalCommand<void>
Undoes the last change.
editor.dispatchCommand(UNDO_COMMAND, undefined);
REDO_COMMAND
REDO_COMMAND: LexicalCommand<void>
Redoes the last undone change.
CAN_UNDO_COMMAND
CAN_UNDO_COMMAND: LexicalCommand<boolean>
Indicates whether undo is available.
CAN_REDO_COMMAND
CAN_REDO_COMMAND: LexicalCommand<boolean>
Indicates whether redo is available.
Clipboard Commands
COPY_COMMAND
COPY_COMMAND: LexicalCommand<ClipboardEvent | KeyboardEvent | null>
Triggered on copy action.
CUT_COMMAND
CUT_COMMAND: LexicalCommand<ClipboardEvent | KeyboardEvent | null>
Triggered on cut action.
PASTE_COMMAND
PASTE_COMMAND: LexicalCommand<ClipboardEvent | InputEvent | KeyboardEvent>
Triggered on paste action.
Selection Commands
SELECT_ALL_COMMAND
SELECT_ALL_COMMAND: LexicalCommand<KeyboardEvent>
Selects all content.
editor.dispatchCommand(SELECT_ALL_COMMAND, event);
SELECTION_CHANGE_COMMAND
SELECTION_CHANGE_COMMAND: LexicalCommand<void>
Dispatched when selection changes.
Keyboard Commands
KEY_ENTER_COMMAND
KEY_ENTER_COMMAND: LexicalCommand<KeyboardEvent | null>
Triggered on Enter key.
KEY_BACKSPACE_COMMAND
KEY_BACKSPACE_COMMAND: LexicalCommand<KeyboardEvent>
Triggered on Backspace key.
KEY_DELETE_COMMAND
KEY_DELETE_COMMAND: LexicalCommand<KeyboardEvent>
Triggered on Delete key.
KEY_ESCAPE_COMMAND
KEY_ESCAPE_COMMAND: LexicalCommand<KeyboardEvent>
Triggered on Escape key.
KEY_TAB_COMMAND
KEY_TAB_COMMAND: LexicalCommand<KeyboardEvent>
Triggered on Tab key.
KEY_ARROW_UP_COMMAND
KEY_ARROW_UP_COMMAND: LexicalCommand<KeyboardEvent>
Triggered on Arrow Up key.
KEY_ARROW_DOWN_COMMAND
KEY_ARROW_DOWN_COMMAND: LexicalCommand<KeyboardEvent>
Triggered on Arrow Down key.
KEY_ARROW_LEFT_COMMAND
KEY_ARROW_LEFT_COMMAND: LexicalCommand<KeyboardEvent>
Triggered on Arrow Left key.
KEY_ARROW_RIGHT_COMMAND
KEY_ARROW_RIGHT_COMMAND: LexicalCommand<KeyboardEvent>
Triggered on Arrow Right key.
KEY_SPACE_COMMAND
KEY_SPACE_COMMAND: LexicalCommand<KeyboardEvent>
Triggered on Space key.
KEY_DOWN_COMMAND
KEY_DOWN_COMMAND: LexicalCommand<KeyboardEvent>
Triggered on any key press.
Navigation Commands
MOVE_TO_START
MOVE_TO_START: LexicalCommand<KeyboardEvent>
Moves cursor to start (Cmd+Left on macOS, Ctrl+Left elsewhere).
MOVE_TO_END
MOVE_TO_END: LexicalCommand<KeyboardEvent>
Moves cursor to end (Cmd+Right on macOS, Ctrl+Right elsewhere).
Focus Commands
FOCUS_COMMAND
FOCUS_COMMAND: LexicalCommand<FocusEvent>
Triggered when editor gains focus.
BLUR_COMMAND
BLUR_COMMAND: LexicalCommand<FocusEvent>
Triggered when editor loses focus.
Mouse Commands
CLICK_COMMAND
CLICK_COMMAND: LexicalCommand<MouseEvent>
Triggered on click.
Drag and Drop Commands
DRAGSTART_COMMAND
DRAGSTART_COMMAND: LexicalCommand<DragEvent>
Triggered when drag starts.
DRAGOVER_COMMAND
DRAGOVER_COMMAND: LexicalCommand<DragEvent>
Triggered during drag over.
DRAGEND_COMMAND
DRAGEND_COMMAND: LexicalCommand<DragEvent>
Triggered when drag ends.
DROP_COMMAND
DROP_COMMAND: LexicalCommand<DragEvent>
Triggered on drop.
Composition Commands
COMPOSITION_START_COMMAND
COMPOSITION_START_COMMAND: LexicalCommand<CompositionEvent>
Triggered when IME composition starts.
COMPOSITION_END_COMMAND
COMPOSITION_END_COMMAND: LexicalCommand<CompositionEvent>
Triggered when IME composition ends.
BEFORE_INPUT_COMMAND: LexicalCommand<InputEvent>
Triggered before input.
INPUT_COMMAND: LexicalCommand<InputEvent>
Triggered on input.
Editor Commands
CLEAR_EDITOR_COMMAND
CLEAR_EDITOR_COMMAND: LexicalCommand<void>
Clears all editor content.
CLEAR_HISTORY_COMMAND
CLEAR_HISTORY_COMMAND: LexicalCommand<void>
Clears the undo/redo history.
Registering Command Handlers
Use editor.registerCommand() to listen for commands:
import { FORMAT_TEXT_COMMAND, COMMAND_PRIORITY_NORMAL } from 'lexical';
const removeListener = editor.registerCommand(
FORMAT_TEXT_COMMAND,
(formatType) => {
// Handle the command
console.log('Format:', formatType);
return false; // Let other handlers run
},
COMMAND_PRIORITY_NORMAL
);
// Later, cleanup
removeListener();
Command Priorities
Command handlers execute in order of priority (highest first):
COMMAND_PRIORITY_EDITOR = 0 // Lowest priority
COMMAND_PRIORITY_LOW = 1
COMMAND_PRIORITY_NORMAL = 2 // Default priority
COMMAND_PRIORITY_HIGH = 3
COMMAND_PRIORITY_CRITICAL = 4 // Highest priority
Higher priority handlers run first and can stop propagation by returning true:
editor.registerCommand(
FORMAT_TEXT_COMMAND,
(formatType) => {
if (formatType === 'bold') {
// Custom bold handling
return true; // Stop propagation
}
return false; // Let other handlers run
},
COMMAND_PRIORITY_HIGH
);
Custom Commands
Create and use custom commands for your features:
import { createCommand, LexicalCommand } from 'lexical';
type MyCommandPayload = {
value: string;
};
export const MY_CUSTOM_COMMAND: LexicalCommand<MyCommandPayload> =
createCommand('MY_CUSTOM_COMMAND');
// Register handler
editor.registerCommand(
MY_CUSTOM_COMMAND,
(payload) => {
console.log('Custom command:', payload.value);
return true;
},
COMMAND_PRIORITY_NORMAL
);
// Dispatch
editor.dispatchCommand(MY_CUSTOM_COMMAND, { value: 'hello' });
Best Practices
Return Values
Return true to stop propagation, false to allow other handlers:
editor.registerCommand(
FORMAT_TEXT_COMMAND,
(formatType) => {
if (shouldHandleFormatting(formatType)) {
handleFormatting(formatType);
return true; // I handled it, stop propagation
}
return false; // Let other handlers try
},
COMMAND_PRIORITY_HIGH
);
Clean Up Listeners
Always clean up command listeners when components unmount:
const removeCommand = editor.registerCommand(
MY_COMMAND,
handler,
COMMAND_PRIORITY_NORMAL
);
// In React:
useEffect(() => {
return () => removeCommand();
}, [editor]);
Use Appropriate Priorities
- Use
CRITICAL for essential behavior that must run first
- Use
HIGH for important features
- Use
NORMAL for standard plugins
- Use
LOW for fallback behavior
- Use
EDITOR for default editor behavior