CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-draft-js

A React framework for building text editors with immutable data models.

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

editor-components.mddocs/

Editor Components

Core React components for rendering the rich text editor interface and individual content blocks.

Capabilities

DraftEditor (exported as Editor)

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}
    />
  );
}

DraftEditorBlock (exported as EditorBlock)

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}
    />
  );
}

Types

Component-Related Types

// 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;
}

Install with Tessl CLI

npx tessl i tessl/npm-draft-js

docs

conversion-utilities.md

data-models.md

editor-components.md

entity-system.md

index.md

key-bindings-utilities.md

text-modification.md

tile.json