168 lines
4.2 KiB
JavaScript
Raw Normal View History

2018-03-05 14:30:28 +01:00
/**
*
* Wysiwyg
*
*/
import React from 'react';
2018-03-06 18:20:05 +01:00
import { ContentState, convertFromHTML, Editor, EditorState, getDefaultKeyBinding, RichUtils, convertToRaw } from 'draft-js';
2018-03-05 14:30:28 +01:00
import PropTypes from 'prop-types';
import { FormattedMessage } from 'react-intl';
2018-03-05 19:23:06 +01:00
import { isEmpty } from 'lodash';
2018-03-05 14:30:28 +01:00
import cn from 'classnames';
2018-03-06 18:20:05 +01:00
import Controls from 'components/WysiwygInlineControls';
2018-03-05 14:30:28 +01:00
import styles from './styles.scss';
2018-03-06 18:20:05 +01:00
const styleMap = {
CODE: {
backgroundColor: 'rgba(0, 0, 0, 0.05)',
fontFamily: '"Inconsolata", "Menlo", "Consolas", monospace',
fontSize: 16,
padding: 2,
},
};
function getBlockStyle(block) {
switch (block.getType()) {
case 'blockquote': return 'RichEditor-blockquote';
default: return null;
}
}
2018-03-05 14:30:28 +01:00
class Wysiwyg extends React.Component {
2018-03-06 18:20:05 +01:00
constructor(props) {
super(props);
this.state = { editorState: EditorState.createEmpty(), isFocused: false };
this.focus = () => {
this.setState({ isFocused: true });
return this.refs.editor.focus();
}
}
2018-03-05 14:30:28 +01:00
componentDidMount() {
if (this.props.autoFocus) {
this.focus();
}
2018-03-05 19:23:06 +01:00
if (!isEmpty(this.props.value)) {
this.setInitialValue(this.props);
}
}
componentWillReceiveProps(nextProps) {
if (nextProps.value !== this.props.value && !this.state.hasInitialValue) {
this.setInitialValue(nextProps);
}
2018-03-05 14:30:28 +01:00
}
2018-03-06 18:20:05 +01:00
handleKeyCommand(command, editorState) {
const newState = RichUtils.handleKeyCommand(editorState, command);
if (newState) {
this.onChange(newState);
return true;
}
return false;
2018-03-05 14:30:28 +01:00
}
2018-03-05 19:23:06 +01:00
onChange = (editorState) => {
2018-03-06 18:20:05 +01:00
this.setState({ editorState });
this.props.onChange({ target: {
2018-03-05 19:23:06 +01:00
value: editorState.getCurrentContent().getPlainText(),
2018-03-06 18:20:05 +01:00
name: this.props.name,
type: 'textarea',
}});
}
2018-03-05 19:23:06 +01:00
2018-03-06 18:20:05 +01:00
mapKeyToEditorCommand = (e) => {
if (e.keyCode === 9 /* TAB */) {
const newEditorState = RichUtils.onTab(
e,
this.state.editorState,
4, /* maxDepth */
);
if (newEditorState !== this.state.editorState) {
this.onChange(newEditorState);
}
return;
}
return getDefaultKeyBinding(e);
}
toggleBlockType = (blockType) => {
this.onChange(
RichUtils.toggleBlockType(
this.state.editorState,
blockType
)
);
2018-03-05 19:23:06 +01:00
}
2018-03-05 14:30:28 +01:00
2018-03-06 18:20:05 +01:00
toggleInlineStyle = (inlineStyle) => {
this.onChange(
RichUtils.toggleInlineStyle(
this.state.editorState,
inlineStyle
)
);
}
2018-03-05 14:30:28 +01:00
2018-03-05 19:23:06 +01:00
setInitialValue = (props) => {
2018-03-06 18:20:05 +01:00
const contentState = ContentState.createFromText(props.value);
let editorState = EditorState.createWithContent(contentState);
2018-03-05 19:23:06 +01:00
// Get the cursor at the end
editorState = EditorState.moveFocusToEnd(editorState);
this.setState({ editorState, hasInitialValue: true });
}
2018-03-06 18:20:05 +01:00
previewHTML = () => {
const blocksFromHTML = convertFromHTML(this.props.value);
const contentState = ContentState.createFromBlockArray(blocksFromHTML);
const editorState = EditorState.createWithContent(contentState);
this.setState({ editorState });
}
2018-03-05 14:30:28 +01:00
render() {
const { editorState } = this.state;
return (
2018-03-06 18:20:05 +01:00
<div className={cn(styles.editorWrapper, this.state.isFocused && styles.editorFocus)}>
<Controls
editorState={editorState}
onToggle={this.toggleInlineStyle}
onToggleBlock={this.toggleBlockType}
previewHTML={this.previewHTML}
2018-03-05 19:23:06 +01:00
/>
2018-03-06 18:20:05 +01:00
<div className={styles.editor} onClick={this.focus}>
<Editor
blockStyleFn={getBlockStyle}
customStyleMap={styleMap}
editorState={editorState}
handleKeyCommand={this.handleKeyCommand}
keyBindingFn={this.mapKeyToEditorCommand}
onBlur={() => this.setState({ isFocused: false })}
onChange={this.onChange}
placeholder={this.props.placeholder}
ref="editor"
spellCheck={true}
/>
<input className={styles.editorInput} value="" tabIndex="-1" />
</div>
</div>
2018-03-05 14:30:28 +01:00
);
}
}
Wysiwyg.defaultProps = {
2018-03-05 19:23:06 +01:00
autoFocus: false,
2018-03-06 18:20:05 +01:00
placeholder: '',
2018-03-05 14:30:28 +01:00
};
Wysiwyg.propTypes = {
autoFocus: PropTypes.bool,
placeholder: PropTypes.string,
};
export default Wysiwyg;