Core React components for rendering the rich text editor interface and individual content blocks.
The main React component that renders the rich text editor interface. It manages user interactions, keyboard events, and renders the content blocks.
/**
* Main Draft.js editor component
* @param props - Editor configuration and event handlers
*/
const Editor: React.ComponentType<{
// Core props
editorState: EditorState,
onChange: (editorState: EditorState) => void,
// Display props
placeholder?: string,
readOnly?: boolean,
tabIndex?: number,
// Styling props
customStyleMap?: {[styleName: string]: React.CSSProperties},
blockRenderMap?: DraftBlockRenderMap,
blockRendererFn?: (block: ContentBlock) => ?{
component: React.ComponentType<any>,
props?: {[key: string]: any},
editable?: boolean
},
blockStyleFn?: (block: ContentBlock) => string,
// Event handling
keyBindingFn?: (e: SyntheticKeyboardEvent) => ?string,
handleKeyCommand?: (command: string, editorState: EditorState, eventTimeStamp: number) => DraftHandleValue,
handleBeforeInput?: (chars: string, editorState: EditorState, eventTimeStamp: number) => DraftHandleValue,
handlePastedText?: (text: string, html?: string, editorState: EditorState) => DraftHandleValue,
handlePastedFiles?: (files: Array<Blob>) => DraftHandleValue,
handleDroppedFiles?: (selection: SelectionState, files: Array<Blob>) => DraftHandleValue,
handleDrop?: (selection: SelectionState, dataTransfer: Object, isInternal: DraftDragType) => DraftHandleValue,
handleReturn?: (e: SyntheticKeyboardEvent, editorState: EditorState) => DraftHandleValue,
// Focus/blur events
onEscape?: (e: SyntheticKeyboardEvent) => void,
onTab?: (e: SyntheticKeyboardEvent) => void,
onUpArrow?: (e: SyntheticKeyboardEvent) => void,
onRightArrow?: (e: SyntheticKeyboardEvent) => void,
onDownArrow?: (e: SyntheticKeyboardEvent) => void,
onLeftArrow?: (e: SyntheticKeyboardEvent) => void,
onBlur?: (e: SyntheticEvent) => void,
onFocus?: (e: SyntheticEvent) => void,
// Clipboard events
onCut?: (e: SyntheticClipboardEvent) => void,
onCopy?: (e: SyntheticClipboardEvent) => void,
onSelect?: (e: SyntheticEvent) => void,
// Accessibility
ariaActiveDescendantID?: string,
ariaAutoComplete?: string,
ariaControls?: string,
ariaDescribedBy?: string,
ariaExpanded?: boolean,
ariaLabel?: string,
ariaLabelledBy?: string,
ariaMultiline?: boolean,
role?: string,
// Advanced
spellCheck?: boolean,
stripPastedStyles?: boolean,
autoCapitalize?: string,
autoComplete?: string,
autoCorrect?: string,
textAlignment?: DraftTextAlignment,
textDirectionality?: DraftTextDirectionality,
webDriverTestID?: string
}>;Usage Examples:
import React, { useState } from "react";
import { Editor, EditorState, RichUtils } from "draft-js";
// Basic editor setup
function BasicEditor() {
const [editorState, setEditorState] = useState(EditorState.createEmpty());
return (
<Editor
editorState={editorState}
onChange={setEditorState}
placeholder="Enter some text..."
/>
);
}
// Editor with key command handling
function RichEditor() {
const [editorState, setEditorState] = useState(EditorState.createEmpty());
const handleKeyCommand = (command, editorState) => {
const newState = RichUtils.handleKeyCommand(editorState, command);
if (newState) {
setEditorState(newState);
return "handled";
}
return "not-handled";
};
const handleBeforeInput = (chars, editorState) => {
// Custom input handling
return "not-handled";
};
return (
<Editor
editorState={editorState}
onChange={setEditorState}
handleKeyCommand={handleKeyCommand}
handleBeforeInput={handleBeforeInput}
placeholder="Start typing..."
spellCheck={true}
/>
);
}
// Editor with custom styling
function StyledEditor() {
const [editorState, setEditorState] = useState(EditorState.createEmpty());
const customStyleMap = {
'HIGHLIGHT': {
backgroundColor: 'yellow',
},
'STRIKETHROUGH': {
textDecoration: 'line-through',
},
};
const blockStyleFn = (contentBlock) => {
const type = contentBlock.getType();
if (type === 'blockquote') {
return 'superFancyBlockquote';
}
};
return (
<Editor
editorState={editorState}
onChange={setEditorState}
customStyleMap={customStyleMap}
blockStyleFn={blockStyleFn}
/>
);
}Component responsible for rendering individual content blocks within the editor. Usually used internally by DraftEditor, but can be customized through blockRendererFn.
/**
* Component for rendering individual content blocks
* Used internally by DraftEditor, customizable via blockRendererFn prop
*/
const EditorBlock: React.ComponentType<{
block: ContentBlock,
blockProps?: any,
blockStyleFn: (block: ContentBlock) => string,
contentState: ContentState,
customStyleMap: {[key: string]: React.CSSProperties},
decorator: ?DraftDecoratorType,
direction: DraftTextDirectionality,
forceSelection: boolean,
offsetKey: string,
selection: SelectionState,
tree: List<any>
}>;Usage Example with Custom Block Renderer:
import React, { useState } from "react";
import { Editor, EditorState } from "draft-js";
// Custom block component
function ImageBlock(props) {
const entity = props.contentState.getEntity(props.block.getEntityAt(0));
const { src, alt } = entity.getData();
return (
<div>
<img src={src} alt={alt} style={{ maxWidth: '100%' }} />
</div>
);
}
function EditorWithCustomBlocks() {
const [editorState, setEditorState] = useState(EditorState.createEmpty());
const blockRendererFn = (contentBlock) => {
const type = contentBlock.getType();
if (type === 'atomic') {
return {
component: ImageBlock,
editable: false,
};
}
return null;
};
return (
<Editor
editorState={editorState}
onChange={setEditorState}
blockRendererFn={blockRendererFn}
/>
);
}// Handle values for event handlers
type DraftHandleValue = 'handled' | 'not-handled';
// Drag types
type DraftDragType = 'internal' | 'external';
// Text alignment
type DraftTextAlignment = 'left' | 'center' | 'right';
// Text directionality
type DraftTextDirectionality = 'LTR' | 'RTL' | 'NEUTRAL';
// Block render configuration
interface DraftBlockRenderConfig {
element: string;
wrapper?: React.ComponentType<any>;
aliasedElements?: Array<string>;
}
// Block render map
type DraftBlockRenderMap = Immutable.Map<DraftBlockType, DraftBlockRenderConfig>;
// Style map for inline styles
type DraftStyleMap = {[styleName: string]: React.CSSProperties};
// Block renderer function return type
interface BlockRendererResult {
component: React.ComponentType<any>;
props?: {[key: string]: any};
editable?: boolean;
}