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

Commit

Permalink
Re-write DraftEditorExample in the website using react hooks (#2287)
Browse files Browse the repository at this point in the history
Summary:
Also took the oportunity to clean up the component- it had unused imports and `_handleKeyCommand` was returning a boolean instead of `"handled"` and `"not-handled"`.

`yarn && yarn start`, used the editor.
Pull Request resolved: #2287

Differential Revision: D19598449

Pulled By: claudiopro

fbshipit-source-id: 275ef520c10f941236138211c8eb572c6df28f9d
  • Loading branch information
mrkev authored and facebook-github-bot committed Jan 28, 2020
1 parent bf5611c commit 9b9376b
Showing 1 changed file with 101 additions and 116 deletions.
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 = () => {
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;

0 comments on commit 9b9376b

Please sign in to comment.