Drag'n'Drop

Supported Environment

  • Desktop: Yes
  • Mobile: No
  • Screen-reader: No

Getting Started

npm install @draft-js-plugins/editor
npm install @draft-js-plugins/focus
npm install @draft-js-plugins/drag-n-drop
gettingStarted.js
// It is important to import the Editor which accepts plugins.

import Editor from '@draft-js-plugins/editor';

import createImagePlugin from '@draft-js-plugins/image';
import React from 'react';

const imagePlugin = createImagePlugin();

// The Editor accepts an array of plugins. In this case, only the imagePlugin
// is passed in, although it is possible to pass in multiple plugins.
const MyEditor = ({ editorState, onChange }) => (
  <Editor
    editorState={editorState}
    onChange={onChange}
    plugins={[imagePlugin]}
  />
);

export default MyEditor;

Importing the default styles

The plugin ships with a default styling available at this location in the installed package:  node_modules/@draft-js-plugins/drag-n-drop/lib/plugin.css

Webpack Usage

  • 1. Install Webpack loaders:  npm i style-loader css-loader --save-dev
  • 2. Add the below section to Webpack config (if your config already has a loaders array, simply add the below loader object to your existing list.
    module.exports = {
      module: {
        loaders: [
          {
            test: /plugin\.css$/,
            loaders: ['style-loader', 'css'],
          },
        ],
      },
    };
    
  • 3. Add the below import line to your component to tell Webpack to inject the style to your component.
    import '@draft-js-plugins/image/lib/plugin.css';
  • 4. Restart Webpack.

Configuration Parameters

Image + Drag'n'Drop

You can have images in your text field which are draggable. Hover over the image press down your mouse button and drag it to another position inside the editor.
You can checkout the alignment tool plugin documentation to see how to build a compatible block plugin …
Editor.js
import React, { Component } from 'react';
import { convertFromRaw, EditorState } from 'draft-js';

import Editor, { composeDecorators } from '@draft-js-plugins/editor';

import createImagePlugin from '@draft-js-plugins/image';

import createFocusPlugin from '@draft-js-plugins/focus';

import createBlockDndPlugin from '@draft-js-plugins/drag-n-drop';
import editorStyles from './editorStyles.module.css';

const focusPlugin = createFocusPlugin();
const blockDndPlugin = createBlockDndPlugin();

const decorator = composeDecorators(
  focusPlugin.decorator,
  blockDndPlugin.decorator
);
const imagePlugin = createImagePlugin({ decorator });

const plugins = [blockDndPlugin, focusPlugin, imagePlugin];

/* eslint-disable */
const initialState = {
  entityMap: {
    0: {
      type: 'IMAGE',
      mutability: 'IMMUTABLE',
      data: {
        src: '/images/canada-landscape-small.jpg',
      },
    },
  },
  blocks: [
    {
      key: '9gm3s',
      text:
        'You can have images in your text field which are draggable. Hover over the image press down your mouse button and drag it to another position inside the editor.',
      type: 'unstyled',
      depth: 0,
      inlineStyleRanges: [],
      entityRanges: [],
      data: {},
    },
    {
      key: 'ov7r',
      text: ' ',
      type: 'atomic',
      depth: 0,
      inlineStyleRanges: [],
      entityRanges: [
        {
          offset: 0,
          length: 1,
          key: 0,
        },
      ],
      data: {},
    },
    {
      key: 'e23a8',
      text:
        'You can checkout the alignment tool plugin documentation to see how to build a compatible block plugin …',
      type: 'unstyled',
      depth: 0,
      inlineStyleRanges: [],
      entityRanges: [],
      data: {},
    },
  ],
};
/* eslint-enable */

export default class CustomImageEditor extends Component {
  state = {
    editorState: EditorState.createWithContent(convertFromRaw(initialState)),
  };

  onChange = (editorState) => {
    this.setState({
      editorState,
    });
  };

  focus = () => {
    this.editor.focus();
  };

  render() {
    return (
      <div>
        <div className={editorStyles.editor} onClick={this.focus}>
          <Editor
            editorState={this.state.editorState}
            onChange={this.onChange}
            plugins={plugins}
            ref={(element) => {
              this.editor = element;
            }}
          />
        </div>
      </div>
    );
  }
}
editorStyles.css
.editor {
  box-sizing: border-box;
  border: 1px solid #ddd;
  cursor: text;
  padding: 16px;
  border-radius: 2px;
  margin-bottom: 2em;
  box-shadow: inset 0px 1px 8px -3px #ABABAB;
  background: #fefefe;
}

.editor :global(.public-DraftEditor-content) {
  min-height: 140px;
}

.options {
  margin-bottom: 20px;
}