-
Notifications
You must be signed in to change notification settings - Fork 4
/
EditorField.tsx
126 lines (114 loc) · 3.32 KB
/
EditorField.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
import * as React from "react";
import {
Editor,
EditorState,
ContentState,
RichUtils,
convertFromHTML,
compositeDecorator,
} from "draft-js";
import { convertToHTML } from "draft-convert";
import { Button } from "library-simplified-reusable-components";
export interface EditorFieldState {
editorState: EditorState;
}
export interface EditorFieldProps {
defaultContent?: string;
content: string;
disabled: boolean;
}
export default class EditorField extends React.Component<
EditorFieldProps,
EditorFieldState
> {
static defaultProps = {
defaultContent: "<p>Update the content for this field.</p>",
};
constructor(props) {
super(props);
// "<p></p>" is the default that DraftJS outputs when the content
// summary is empty. This value, however, breaks when trying to create
// a contentState from `ContentState.createFromBlockArray` since
// `blocksFromHTML.contentBlocks` is an empty array.
const content =
!props.content || props.content === "<p></p>" || props.content === ""
? props.defaultContent
: props.content;
let blocksFromHTML;
try {
blocksFromHTML = convertFromHTML(JSON.parse(content));
} catch {
blocksFromHTML = convertFromHTML(content);
}
const contentState = ContentState.createFromBlockArray(
blocksFromHTML.contentBlocks,
blocksFromHTML.entityMap
);
this.state = {
editorState: EditorState.createWithContent(
contentState,
compositeDecorator
),
};
this.onChange = this.onChange.bind(this);
this.handleKeyCommand = this.handleKeyCommand.bind(this);
this.getValue = this.getValue.bind(this);
this.changeStyle = this.changeStyle.bind(this);
this.renderButton = this.renderButton.bind(this);
}
onChange(editorState) {
this.setState({ editorState });
}
handleKeyCommand(command, editorState) {
const newState = RichUtils.handleKeyCommand(editorState, command);
if (newState) {
this.onChange(newState);
return "handled";
}
return "not-handled";
}
renderButton(style: string): JSX.Element {
const buttonContent = React.createElement(
style[0].toLowerCase(),
null,
style
);
const isActive =
this.state.editorState.getSelection().getHasFocus() &&
this.state.editorState.getCurrentInlineStyle().has(style.toUpperCase());
return (
<Button
content={buttonContent}
mouseDown={true}
key={style}
callback={(e) => {
this.changeStyle(e, style.toUpperCase());
}}
className={`btn inline squared${isActive ? " active" : ""}`}
disabled={this.props.disabled}
type="button"
/>
);
}
changeStyle(e, style: string) {
e.preventDefault();
this.onChange(RichUtils.toggleInlineStyle(this.state.editorState, style));
}
getValue() {
return convertToHTML(this.state.editorState.getCurrentContent());
}
render() {
const styles = ["Bold", "Italic", "Underline"];
return (
<div className="editor-field">
<ul>{styles.map((style) => this.renderButton(style))}</ul>
<Editor
editorState={this.state.editorState}
onChange={this.onChange}
handleKeyCommand={this.handleKeyCommand}
readOnly={this.props.disabled}
/>
</div>
);
}
}