A Plugin is simply a plain JavaScript object containing a couple deeper nested objects or functions e.g.
const customPlugin = {
blockStyleFn: (contentBlock) => {
if (contentBlock.getType() === 'blockquote') {
return 'superFancyBlockquote';
}
},
customStyleMap: {
'STRIKETHROUGH': {
textDecoration: 'line-through',
},
},
};
As most plugins take some kind of configuration we recommend you to always export a function that creates this object. This is aligned with all the core plugins and leads to a consistent developer experience.
export default createCustomPlugin = (config) => {
const blockStyleFn = (contentBlock) => {
if (contentBlock.getType() === 'blockquote') {
return 'superFancyBlockquote';
}
};
const customStyleMap = {
'STRIKETHROUGH': {
textDecoration: 'line-through',
},
};
return {
blockStyleFn: blockStyleFn,
customStyleMap: customStyleMap,
};
};
A plugin accepts all standard props the Draft.js Editor Component uses. See details on Draft.js docs. Commonly used props:
- blockRendererFn
- keyBindingFn
- blockStyleFn
- blockRenderMap
- customStyleMap
- handleReturn
- handleKeyCommand
- handleBeforeInput
- handlePastedText
- handlePastedFiles
- handleDroppedFiles
- handleDrop
- onEscape
- onTab
- onUpArrow
- onRightArrow
- onDownArrow
- onLeftArrow
- onFocus
- onBlur
There is one difference compared to the original properties. All functions receive an additional argument. This argument is an object containing:
// PluginFunctions
{
getPlugins, // a function returning a list of all the plugins
getProps, // a function returning a list of all the props pass into the Editor
setEditorState, // a function to update the EditorState
getEditorState, // a function to get the current EditorState
getReadOnly, // a function returning of the Editor is set to readOnly
setReadOnly, // a function which allows to set the Editor to readOnly
getEditorRef, // a function to get the editor reference
}
In addition the a plugin accepts
initialize: (PluginFunctions) => void
onChange: (EditorState) => EditorState
willUnmount: (PluginFunctions) => void
decorators: Array<Decorator> => void
getAccessibilityProps: () => { ariaHasPopup: string, ariaExpanded: string }
Allows to initialize a plugin once the editor becomes mounted.
Allows a plugin to modify the state at the latest moment before the onChange callback of the Draft.js Editor is fired.
Usually used to clean up.
Draft.js allows to initialize an EditorState with a decorator. Many plugins also rely on decorators and therefore we decided to incorporate them in the plugin architecture. Every plugin can have multiple decorators and all of them are combined by the plugin editor.
A decorator can contain a strategy
and a component
e.g.
{
decorators: [
{
strategy: hashtagStrategy,
component: HashtagSpan,
},
],
}
You can read more about it in the original Draft.js documentation about decorators.
If you want to implement the DraftDecoratorType Interface yourself, you can include those in your decorators
array alongside the composite decorators. See draft-js-simpledecorator for an example of an implementation of DraftDecoratorType. Here's an example mixed decorators
array:
{
decorators: [
{
strategy: hashtagStrategy,
component: HashtagSpan,
},
new MyCustomDraftDecoratorType('...'),
],
}
In some rare cases like @mentions or Emoji autocompletion a plugin should be able to set certain ARIA attributes.
This currently only allows to set aria-has-popup
& aria-expanded
. Let us know in case you have further suggestions.
Keep in mind that the order of plugins can matter. The first decorator the that matches prevents the following ones to become active
for a certain text block. Same goes for handleReturn
if returned true. Therefor try to keep your plugins minimal in the sense that
they only match & manipulate the necessary block or text.