Skip to content

Instantly share code, notes, and snippets.

@sylvainbx
Last active December 9, 2022 03:17
Show Gist options
  • Save sylvainbx/e281f0596617b6119559f05388318e7d to your computer and use it in GitHub Desktop.
Save sylvainbx/e281f0596617b6119559f05388318e7d to your computer and use it in GitHub Desktop.
React wysiwyg text editor
import React, { Component, PropTypes } from 'react';
import {
bold,
italic,
underline,
strikethrough,
superscript,
subscript,
unordered,
ordered,
left,
center,
right,
justify,
eraser,
undo,
redo,
Editor,
} from 'react-draft-wysiwyg';
import _ from 'lodash';
import { EditorState, convertFromRaw } from 'draft-js';
export default class TextEditor extends Component {
constructor(props) {
super(props);
this.state = {
editorState: TextEditor.initialState(props.rawState),
};
this.toolbar = {
options: ['inline', 'blockType', 'list', 'textAlign', 'remove', 'history'],
inline: {
inDropdown: false,
className: undefined,
component: undefined,
dropdownClassName: undefined,
options: ['bold', 'italic', 'underline', 'strikethrough', 'superscript', 'subscript'],
bold: { icon: bold, className: undefined },
italic: { icon: italic, className: undefined },
underline: { icon: underline, className: undefined },
strikethrough: { icon: strikethrough, className: undefined },
superscript: { icon: superscript, className: undefined },
subscript: { icon: subscript, className: undefined },
},
blockType: {
inDropdown: true,
options: ['Normal', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'Blockquote'],
className: undefined,
component: undefined,
dropdownClassName: undefined,
},
list: {
inDropdown: false,
className: undefined,
component: undefined,
dropdownClassName: undefined,
options: ['unordered', 'ordered'],
unordered: { icon: unordered, className: undefined },
ordered: { icon: ordered, className: undefined },
},
textAlign: {
inDropdown: false,
className: undefined,
component: undefined,
dropdownClassName: undefined,
options: ['left', 'center', 'right', 'justify'],
left: { icon: left, className: undefined },
center: { icon: center, className: undefined },
right: { icon: right, className: undefined },
justify: { icon: justify, className: undefined },
},
remove: { icon: eraser, className: undefined, component: undefined },
history: {
inDropdown: false,
className: undefined,
component: undefined,
dropdownClassName: undefined,
options: ['undo', 'redo'],
undo: { icon: undo, className: undefined },
redo: { icon: redo, className: undefined },
},
};
}
componentWillReceiveProps(nextProps) {
if (!_.isEqual(this.props.rawState, nextProps.rawState)) {
this.setState({
editorState: TextEditor.initialState(nextProps.rawState),
});
}
}
onEditorStateChange(editorState) {
this.setState({ editorState });
this.props.onChange(editorState);
}
static initialState(rawState) {
if (rawState) {
if (!rawState.entityMap) { rawState.entityMap = {}; }
const contentState = convertFromRaw(rawState);
return EditorState.createWithContent(contentState);
}
return EditorState.createEmpty();
}
render() {
const { editorState } = this.state;
const { placeholder } = this.props;
return (
<div className="m-t-md">
<Editor editorState={editorState}
toolbarClassName="text-editor__toolbar"
wrapperClassName="text-editor__wrapper"
editorClassName="text-editor__editor"
onEditorStateChange={this.onEditorStateChange.bind(this)}
placeholder={placeholder}
toolbar={this.toolbar} />
</div>
);
}
}
TextEditor.propTypes = {
rawState: PropTypes.object,
placeholder: PropTypes.string.isRequired,
onChange: PropTypes.func.isRequired,
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment