equal
deleted
inserted
replaced
1 import { Editor, Plain, Raw } from 'slate' |
1 import { Editor, Plain, Raw } from 'slate' |
2 import React from 'react' |
2 import React from 'react' |
3 import moment from 'moment'; |
3 import moment from 'moment'; |
4 import HtmlSerializer from '../HtmlSerializer' |
4 import HtmlSerializer from '../HtmlSerializer' |
|
5 import AnnotationPlugin from '../AnnotationPlugin'; |
|
6 |
|
7 const plugins = []; |
5 |
8 |
6 /** |
9 /** |
7 * Define the default node type. |
10 * Define the default node type. |
8 */ |
11 */ |
9 |
12 |
15 * @type {Object} |
18 * @type {Object} |
16 */ |
19 */ |
17 |
20 |
18 const schema = { |
21 const schema = { |
19 nodes: { |
22 nodes: { |
20 'block-quote': props => <blockquote {...props.attributes}>{props.children}</blockquote>, |
|
21 'bulleted-list': props => <ul {...props.attributes}>{props.children}</ul>, |
23 'bulleted-list': props => <ul {...props.attributes}>{props.children}</ul>, |
22 'heading-one': props => <h1 {...props.attributes}>{props.children}</h1>, |
|
23 'heading-two': props => <h2 {...props.attributes}>{props.children}</h2>, |
|
24 'list-item': props => <li {...props.attributes}>{props.children}</li>, |
24 'list-item': props => <li {...props.attributes}>{props.children}</li>, |
25 'numbered-list': props => <ol {...props.attributes}>{props.children}</ol>, |
25 'numbered-list': props => <ol {...props.attributes}>{props.children}</ol>, |
26 }, |
26 }, |
27 marks: { |
27 marks: { |
28 bold: { |
28 bold: { |
29 fontWeight: 'bold' |
29 fontWeight: 'bold' |
30 }, |
30 }, |
31 code: { |
31 // TODO Check if we can move this to the plugin using the schema option |
32 fontFamily: 'monospace', |
32 // https://docs.slatejs.org/reference/plugins/plugin.html#schema |
33 backgroundColor: '#eee', |
33 annotation: { |
34 padding: '3px', |
34 textDecoration: 'underline', |
35 borderRadius: '4px' |
35 textDecorationStyle: 'dotted', |
|
36 backgroundColor: 'yellow', |
36 }, |
37 }, |
37 italic: { |
38 italic: { |
38 fontStyle: 'italic' |
39 fontStyle: 'italic' |
39 }, |
40 }, |
40 underlined: { |
41 underlined: { |
56 * |
57 * |
57 * @type {Object} |
58 * @type {Object} |
58 */ |
59 */ |
59 constructor(props) { |
60 constructor(props) { |
60 super(props); |
61 super(props); |
|
62 |
|
63 const annotationPlugin = AnnotationPlugin({ |
|
64 onChange: (text) => { |
|
65 this.setState({ currentSelectionText: text }); |
|
66 } |
|
67 }); |
|
68 |
|
69 plugins.push(annotationPlugin); |
|
70 |
61 this.state = { |
71 this.state = { |
62 state: Plain.deserialize(''), |
72 state: Plain.deserialize(''), |
63 startedAt: null, |
73 startedAt: null, |
64 finishedAt: null |
74 finishedAt: null, |
|
75 currentSelectionText: '' |
65 }; |
76 }; |
66 } |
77 } |
67 |
78 |
68 componentDidMount() { |
79 componentDidMount() { |
69 this.focus(); |
80 this.focus(); |
172 mark = 'italic' |
183 mark = 'italic' |
173 break |
184 break |
174 case 'u': |
185 case 'u': |
175 mark = 'underlined' |
186 mark = 'underlined' |
176 break |
187 break |
177 case '`': |
|
178 mark = 'code' |
|
179 break |
|
180 default: |
188 default: |
181 return |
189 return |
182 } |
190 } |
183 |
191 |
184 state = state |
192 state = state |
199 |
207 |
200 onClickMark = (e, type) => { |
208 onClickMark = (e, type) => { |
201 e.preventDefault() |
209 e.preventDefault() |
202 let { state } = this.state |
210 let { state } = this.state |
203 |
211 |
|
212 let toggleMarkOptions; |
|
213 if (type === 'annotation') { |
|
214 toggleMarkOptions = { type: type, data: { text: this.state.currentSelectionText } } |
|
215 } else { |
|
216 toggleMarkOptions = type; |
|
217 } |
|
218 |
204 state = state |
219 state = state |
205 .transform() |
220 .transform() |
206 .toggleMark(type) |
221 .toggleMark(toggleMarkOptions) |
207 .apply() |
222 .apply() |
208 |
223 |
209 this.setState({ state }) |
224 this.setState({ state }) |
210 } |
225 } |
211 |
226 |
292 return ( |
307 return ( |
293 <div className="menu toolbar-menu"> |
308 <div className="menu toolbar-menu"> |
294 {this.renderMarkButton('bold', 'format_bold')} |
309 {this.renderMarkButton('bold', 'format_bold')} |
295 {this.renderMarkButton('italic', 'format_italic')} |
310 {this.renderMarkButton('italic', 'format_italic')} |
296 {this.renderMarkButton('underlined', 'format_underlined')} |
311 {this.renderMarkButton('underlined', 'format_underlined')} |
297 {this.renderMarkButton('code', 'code')} |
312 {this.renderMarkButton('annotation', 'label')} |
298 {this.renderBlockButton('heading-one', 'looks_one')} |
313 |
299 {this.renderBlockButton('heading-two', 'looks_two')} |
|
300 {this.renderBlockButton('block-quote', 'format_quote')} |
|
301 {this.renderBlockButton('numbered-list', 'format_list_numbered')} |
314 {this.renderBlockButton('numbered-list', 'format_list_numbered')} |
302 {this.renderBlockButton('bulleted-list', 'format_list_bulleted')} |
315 {this.renderBlockButton('bulleted-list', 'format_list_bulleted')} |
303 </div> |
316 </div> |
304 ) |
317 ) |
305 } |
318 } |
354 <Editor |
367 <Editor |
355 ref="editor" |
368 ref="editor" |
356 spellCheck |
369 spellCheck |
357 placeholder={'Enter some rich text...'} |
370 placeholder={'Enter some rich text...'} |
358 schema={schema} |
371 schema={schema} |
|
372 plugins={plugins} |
359 state={this.state.state} |
373 state={this.state.state} |
360 onChange={this.onChange} |
374 onChange={this.onChange} |
361 onKeyDown={this.onKeyDown} |
375 onKeyDown={this.onKeyDown} |
362 /> |
376 /> |
363 </div> |
377 </div> |