Utilities for making changes to editor content with proper immutable updates. These tools provide both low-level content manipulation and high-level rich text operations.
Low-level utility functions for modifying ContentState objects. All methods return new immutable ContentState instances.
/**
* Low-level content modification utilities
*/
const Modifier: {
/**
* Replace text in specified range
* @param contentState - Current content state
* @param targetRange - Selection range to replace
* @param text - Replacement text
* @param inlineStyle - Optional inline styles to apply
* @param entityKey - Optional entity key to apply
* @returns New ContentState with text replaced
*/
replaceText(
contentState: ContentState,
targetRange: SelectionState,
text: string,
inlineStyle?: DraftInlineStyle,
entityKey?: ?string
): ContentState;
/**
* Insert text at specified range (collapses range first if needed)
* @param contentState - Current content state
* @param targetRange - Selection range for insertion
* @param text - Text to insert
* @param inlineStyle - Optional inline styles to apply
* @param entityKey - Optional entity key to apply
* @returns New ContentState with text inserted
*/
insertText(
contentState: ContentState,
targetRange: SelectionState,
text: string,
inlineStyle?: DraftInlineStyle,
entityKey?: ?string
): ContentState;
/**
* Move text from one location to another
* @param contentState - Current content state
* @param removalRange - Range of text to move
* @param targetRange - Destination for moved text
* @returns New ContentState with text moved
*/
moveText(
contentState: ContentState,
removalRange: SelectionState,
targetRange: SelectionState
): ContentState;
/**
* Replace range with content fragment
* @param contentState - Current content state
* @param targetRange - Range to replace
* @param fragment - Content blocks to insert
* @returns New ContentState with fragment inserted
*/
replaceWithFragment(
contentState: ContentState,
targetRange: SelectionState,
fragment: BlockMap
): ContentState;
/**
* Remove content in specified range
* @param contentState - Current content state
* @param targetRange - Range to remove
* @param removalDirection - Direction of removal (forward/backward)
* @returns New ContentState with content removed
*/
removeRange(
contentState: ContentState,
targetRange: SelectionState,
removalDirection: DraftRemovalDirection
): ContentState;
/**
* Split block at specified position
* @param contentState - Current content state
* @param targetRange - Position to split (should be collapsed)
* @returns New ContentState with block split
*/
splitBlock(
contentState: ContentState,
targetRange: SelectionState
): ContentState;
/**
* Apply inline style to range
* @param contentState - Current content state
* @param targetRange - Range to style
* @param inlineStyle - Style name to apply
* @returns New ContentState with style applied
*/
applyInlineStyle(
contentState: ContentState,
targetRange: SelectionState,
inlineStyle: string
): ContentState;
/**
* Remove inline style from range
* @param contentState - Current content state
* @param targetRange - Range to modify
* @param inlineStyle - Style name to remove
* @returns New ContentState with style removed
*/
removeInlineStyle(
contentState: ContentState,
targetRange: SelectionState,
inlineStyle: string
): ContentState;
/**
* Set block type for blocks in range
* @param contentState - Current content state
* @param targetRange - Range of blocks to modify
* @param blockType - New block type
* @returns New ContentState with block types changed
*/
setBlockType(
contentState: ContentState,
targetRange: SelectionState,
blockType: DraftBlockType
): ContentState;
/**
* Set block data for blocks in range
* @param contentState - Current content state
* @param targetRange - Range of blocks to modify
* @param blockData - New block data
* @returns New ContentState with block data set
*/
setBlockData(
contentState: ContentState,
targetRange: SelectionState,
blockData: Map<any, any>
): ContentState;
/**
* Merge block data for blocks in range
* @param contentState - Current content state
* @param targetRange - Range of blocks to modify
* @param blockData - Block data to merge
* @returns New ContentState with block data merged
*/
mergeBlockData(
contentState: ContentState,
targetRange: SelectionState,
blockData: Map<any, any>
): ContentState;
/**
* Apply entity to range
* @param contentState - Current content state
* @param targetRange - Range to apply entity
* @param entityKey - Entity key to apply (null to remove)
* @returns New ContentState with entity applied
*/
applyEntity(
contentState: ContentState,
targetRange: SelectionState,
entityKey: ?string
): ContentState;
};Usage Examples:
import { Modifier, EditorState, SelectionState } from "draft-js";
function insertTextExample(editorState) {
const contentState = editorState.getCurrentContent();
const selection = editorState.getSelection();
// Insert text with bold styling
const newContentState = Modifier.insertText(
contentState,
selection,
"Hello World!",
OrderedSet(['BOLD'])
);
return EditorState.push(editorState, newContentState, 'insert-characters');
}
function applyStyleExample(editorState) {
const contentState = editorState.getCurrentContent();
const selection = editorState.getSelection();
// Apply italic style to selected text
const newContentState = Modifier.applyInlineStyle(
contentState,
selection,
'ITALIC'
);
return EditorState.push(editorState, newContentState, 'change-inline-style');
}
function changeBlockTypeExample(editorState) {
const contentState = editorState.getCurrentContent();
const selection = editorState.getSelection();
// Change current block to header
const newContentState = Modifier.setBlockType(
contentState,
selection,
'header-one'
);
return EditorState.push(editorState, newContentState, 'change-block-type');
}High-level utilities for common rich text editing operations. These functions work directly with EditorState.
/**
* High-level rich text editing utilities
*/
const RichUtils: {
/**
* Handle keyboard commands (bold, italic, undo, etc.)
* @param editorState - Current editor state
* @param command - Command string from key binding
* @returns New EditorState or null if not handled
*/
handleKeyCommand(editorState: EditorState, command: DraftEditorCommand): ?EditorState;
/**
* Toggle inline style (add if not present, remove if present)
* @param editorState - Current editor state
* @param inlineStyle - Style name to toggle
* @returns New EditorState with style toggled
*/
toggleInlineStyle(editorState: EditorState, inlineStyle: string): EditorState;
/**
* Toggle block type
* @param editorState - Current editor state
* @param blockType - Block type to toggle to
* @returns New EditorState with block type changed
*/
toggleBlockType(editorState: EditorState, blockType: DraftBlockType): EditorState;
/**
* Toggle link entity on selection
* @param editorState - Current editor state
* @param targetSelection - Selection to apply link to
* @param entityKey - Link entity key (null to remove link)
* @returns New EditorState with link toggled
*/
toggleLink(
editorState: EditorState,
targetSelection: SelectionState,
entityKey: ?string
): EditorState;
/**
* Insert soft newline (line break within block)
* @param editorState - Current editor state
* @returns New EditorState with soft newline inserted
*/
insertSoftNewline(editorState: EditorState): EditorState;
/**
* Handle backspace key press
* @param editorState - Current editor state
* @returns New EditorState or null if not handled
*/
onBackspace(editorState: EditorState): ?EditorState;
/**
* Handle delete key press
* @param editorState - Current editor state
* @returns New EditorState or null if not handled
*/
onDelete(editorState: EditorState): ?EditorState;
/**
* Handle tab key press (for list indentation)
* @param event - Keyboard event
* @param editorState - Current editor state
* @param maxDepth - Maximum nesting depth
* @returns New EditorState with depth adjusted
*/
onTab(
event: SyntheticKeyboardEvent,
editorState: EditorState,
maxDepth: number
): EditorState;
/**
* Toggle code formatting
* @param editorState - Current editor state
* @returns New EditorState with code toggled
*/
toggleCode(editorState: EditorState): EditorState;
/**
* Get current block type
* @param editorState - Current editor state
* @returns Block type of current block
*/
getCurrentBlockType(editorState: EditorState): DraftBlockType;
/**
* Check if current block contains link
* @param editorState - Current editor state
* @returns True if current selection contains a link
*/
currentBlockContainsLink(editorState: EditorState): boolean;
/**
* Try to remove block-level styling
* @param editorState - Current editor state
* @returns New ContentState or null if no change
*/
tryToRemoveBlockStyle(editorState: EditorState): ?ContentState;
};Usage Examples:
import { RichUtils, EditorState } from "draft-js";
// Handle keyboard commands
function handleKeyCommand(command, editorState) {
const newState = RichUtils.handleKeyCommand(editorState, command);
if (newState) {
return newState;
}
return editorState;
}
// Toggle formatting
function toggleBold(editorState) {
return RichUtils.toggleInlineStyle(editorState, 'BOLD');
}
function toggleItalic(editorState) {
return RichUtils.toggleInlineStyle(editorState, 'ITALIC');
}
function toggleHeader(editorState) {
return RichUtils.toggleBlockType(editorState, 'header-one');
}
// Check current state
function isCurrentBlockHeader(editorState) {
const blockType = RichUtils.getCurrentBlockType(editorState);
return blockType.startsWith('header-');
}
// Handle special keys
function handleTab(e, editorState) {
const newState = RichUtils.onTab(e, editorState, 4);
return newState;
}
function handleReturn(e, editorState) {
if (e.shiftKey) {
return RichUtils.insertSoftNewline(editorState);
}
return editorState;
}Utilities for working with atomic blocks - blocks that contain non-text content like images, videos, or embeds.
/**
* Utilities for atomic blocks (media, embeds, etc.)
*/
const AtomicBlockUtils: {
/**
* Insert atomic block at current selection
* @param editorState - Current editor state
* @param entityKey - Entity key for the atomic content
* @param character - Character to represent the atomic block
* @returns New EditorState with atomic block inserted
*/
insertAtomicBlock(
editorState: EditorState,
entityKey: string,
character: string
): EditorState;
/**
* Move atomic block to new position
* @param editorState - Current editor state
* @param atomicBlock - The atomic block to move
* @param targetRange - Destination selection
* @param insertionMode - How to insert ('before' | 'after')
* @returns New EditorState with atomic block moved
*/
moveAtomicBlock(
editorState: EditorState,
atomicBlock: ContentBlock,
targetRange: SelectionState,
insertionMode?: DraftInsertionType
): EditorState;
};Usage Examples:
import { AtomicBlockUtils, Entity, EditorState } from "draft-js";
// Insert image
function insertImage(editorState, src, alt) {
// Create entity for the image
const entityKey = Entity.create('IMAGE', 'IMMUTABLE', {
src: src,
alt: alt
});
// Insert atomic block
return AtomicBlockUtils.insertAtomicBlock(
editorState,
entityKey,
' ' // Space character as placeholder
);
}
// Insert video embed
function insertVideo(editorState, videoUrl) {
const entityKey = Entity.create('VIDEO', 'IMMUTABLE', {
src: videoUrl
});
return AtomicBlockUtils.insertAtomicBlock(
editorState,
entityKey,
'📹' // Video emoji as placeholder
);
}
// Move atomic block
function moveAtomicBlockUp(editorState, atomicBlock) {
const selection = editorState.getSelection();
const targetRange = selection.merge({
anchorKey: atomicBlock.getKey(),
focusKey: atomicBlock.getKey()
});
return AtomicBlockUtils.moveAtomicBlock(
editorState,
atomicBlock,
targetRange,
'before'
);
}// Removal direction
type DraftRemovalDirection = 'backward' | 'forward';
// Insertion type for atomic blocks
type DraftInsertionType = 'replace' | 'before' | 'after';
// Editor commands
type DraftEditorCommand = 'backspace' | 'backspace-word' | 'backspace-to-start-of-line' |
'delete' | 'delete-word' | 'delete-to-end-of-block' | 'enter' | 'forward-delete' |
'insert-characters' | 'insert-compose-character' | 'move-selection-to-start-of-block' |
'move-selection-to-end-of-block' | 'secondary-cut' | 'secondary-paste' | 'split-block' |
'transpose-characters' | 'undo' | 'redo' | 'bold' | 'code' | 'italic' | 'strikethrough' |
'underline';
// Block merge behavior
type BlockDataMergeBehavior = 'REPLACE_WITH_NEW_DATA' | 'MERGE_OLD_DATA_TO_NEW_DATA';
// Entity mutability
type DraftEntityMutability = 'MUTABLE' | 'IMMUTABLE' | 'SEGMENTED';