Skip to content
This repository has been archived by the owner on Feb 6, 2023. It is now read-only.

Re-write DraftEditorExample in the website using react hooks #2287

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
217 changes: 101 additions & 116 deletions website/src/components/DraftEditorExample/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,111 +6,102 @@
*/

import React from 'react';
import Link from '@docusaurus/Link';
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
import useBaseUrl from '@docusaurus/useBaseUrl';
import {Editor, EditorState, RichUtils, getDefaultKeyBinding} from 'draft-js';
import classnames from 'classnames';

import Layout from '@theme/Layout';

import './css/example.css';
import './css/draft.css';
import './css/rich-editor.css';

class RichEditorExample extends React.Component {
constructor(props) {
super(props);
this.state = {editorState: EditorState.createEmpty()};

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

this.handleKeyCommand = this._handleKeyCommand.bind(this);
this.mapKeyToEditorCommand = this._mapKeyToEditorCommand.bind(this);
this.toggleBlockType = this._toggleBlockType.bind(this);
this.toggleInlineStyle = this._toggleInlineStyle.bind(this);
}

_handleKeyCommand(command, editorState) {
const newState = RichUtils.handleKeyCommand(editorState, command);
if (newState) {
this.onChange(newState);
return true;
}
return false;
}
const {useState, useRef, useCallback} = React;

_mapKeyToEditorCommand(e) {
switch (e.keyCode) {
case 9: // TAB
const newEditorState = RichUtils.onTab(
e,
this.state.editorState,
4 /* maxDepth */,
);
if (newEditorState !== this.state.editorState) {
this.onChange(newEditorState);
}
return;
}
return getDefaultKeyBinding(e);
}
function RichEditorExample(props) {
const [editorState, setEditorState] = useState(EditorState.createEmpty());
const editor = useRef(null);

_toggleBlockType(blockType) {
this.onChange(RichUtils.toggleBlockType(this.state.editorState, blockType));
}
const focus = () => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: can you rename to focusEditor? This is shadowing the window.focus() method

if (editor.current) editor.current.focus();
};

_toggleInlineStyle(inlineStyle) {
this.onChange(
RichUtils.toggleInlineStyle(this.state.editorState, inlineStyle),
);
}
const handleKeyCommand = useCallback(
(command, editorState) => {
const newState = RichUtils.handleKeyCommand(editorState, command);
if (newState) {
setEditorState(newState);
return 'handled';
}
return 'not-handled';
},
[editorState, setEditorState],
);

render() {
const {editorState} = this.state;

// If the user changes block type before entering any text, we can
// either style the placeholder or hide it. Let's just hide it now.
let className = 'RichEditor-editor';
var contentState = editorState.getCurrentContent();
if (!contentState.hasText()) {
if (
contentState
.getBlockMap()
.first()
.getType() !== 'unstyled'
) {
className += ' RichEditor-hidePlaceholder';
const mapKeyToEditorCommand = useCallback(
e => {
switch (e.keyCode) {
case 9: // TAB
const newEditorState = RichUtils.onTab(
e,
editorState,
4 /* maxDepth */,
);
if (newEditorState !== editorState) {
setEditorState(newEditorState);
}
return null;
}
return getDefaultKeyBinding(e);
},
[editorState, setEditorState],
);

// If the user changes block type before entering any text, we can
// either style the placeholder or hide it. Let's just hide it now.
let className = 'RichEditor-editor';
var contentState = editorState.getCurrentContent();
if (!contentState.hasText()) {
if (
contentState
.getBlockMap()
.first()
.getType() !== 'unstyled'
) {
className += ' RichEditor-hidePlaceholder';
}
}

return (
<div className="RichEditor-root">
<BlockStyleControls
editorState={editorState}
onToggle={this.toggleBlockType}
/>
<InlineStyleControls
return (
<div className="RichEditor-root">
<BlockStyleControls
editorState={editorState}
onToggle={blockType => {
const newState = RichUtils.toggleBlockType(editorState, blockType);
setEditorState(newState);
}}
/>
<InlineStyleControls
editorState={editorState}
onToggle={inlineStyle => {
const newState = RichUtils.toggleInlineStyle(
editorState,
inlineStyle,
);
setEditorState(newState);
}}
/>
<div className={className} onClick={focus}>
<Editor
blockStyleFn={getBlockStyle}
customStyleMap={styleMap}
editorState={editorState}
onToggle={this.toggleInlineStyle}
handleKeyCommand={handleKeyCommand}
keyBindingFn={mapKeyToEditorCommand}
onChange={setEditorState}
placeholder="Tell a story..."
ref={editor}
spellCheck={true}
/>
<div className={className} onClick={this.focus}>
<Editor
blockStyleFn={getBlockStyle}
customStyleMap={styleMap}
editorState={editorState}
handleKeyCommand={this.handleKeyCommand}
keyBindingFn={this.mapKeyToEditorCommand}
onChange={this.onChange}
placeholder="Tell a story..."
ref={ref => (this.editor = ref)}
spellCheck={true}
/>
</div>
</div>
);
}
</div>
);
}

// Custom overrides for "code" style.
Expand All @@ -132,27 +123,22 @@ function getBlockStyle(block) {
}
}

class StyleButton extends React.Component {
constructor() {
super();
this.onToggle = e => {
e.preventDefault();
this.props.onToggle(this.props.style);
};
function StyleButton({onToggle, active, label, style}) {
let className = 'RichEditor-styleButton';
if (active) {
className += ' RichEditor-activeButton';
}

render() {
let className = 'RichEditor-styleButton';
if (this.props.active) {
className += ' RichEditor-activeButton';
}

return (
<span className={className} onMouseDown={this.onToggle}>
{this.props.label}
</span>
);
}
return (
<span
className={className}
onMouseDown={e => {
e.preventDefault();
onToggle(style);
}}>
{label}
</span>
);
}

const BLOCK_TYPES = [
Expand All @@ -168,8 +154,7 @@ const BLOCK_TYPES = [
{label: 'Code Block', style: 'code-block'},
];

const BlockStyleControls = props => {
const {editorState} = props;
function BlockStyleControls({editorState, onToggle}) {
const selection = editorState.getSelection();
const blockType = editorState
.getCurrentContent()
Expand All @@ -183,13 +168,13 @@ const BlockStyleControls = props => {
key={type.label}
active={type.style === blockType}
label={type.label}
onToggle={props.onToggle}
onToggle={onToggle}
style={type.style}
/>
))}
</div>
);
};
}

const INLINE_STYLES = [
{label: 'Bold', style: 'BOLD'},
Expand All @@ -198,21 +183,21 @@ const INLINE_STYLES = [
{label: 'Monospace', style: 'CODE'},
];

const InlineStyleControls = props => {
const currentStyle = props.editorState.getCurrentInlineStyle();
function InlineStyleControls({editorState, onToggle}) {
const currentStyle = editorState.getCurrentInlineStyle();
return (
<div className="RichEditor-controls">
{INLINE_STYLES.map(type => (
<StyleButton
key={type.label}
active={currentStyle.has(type.style)}
label={type.label}
onToggle={props.onToggle}
onToggle={onToggle}
style={type.style}
/>
))}
</div>
);
};
}

export default RichEditorExample;