equal
deleted
inserted
replaced
29 }, |
29 }, |
30 marks: { |
30 marks: { |
31 bold: { |
31 bold: { |
32 fontWeight: 'bold' |
32 fontWeight: 'bold' |
33 }, |
33 }, |
34 // This is a "temporary" mark added when the hovering menu is open |
34 category: props => { |
35 highlight: { |
|
36 textDecoration: 'underline', |
|
37 textDecorationStyle: 'dotted', |
|
38 backgroundColor: '#ccc', |
|
39 }, |
|
40 // This is the mark actually used for annotations |
|
41 annotation: props => { |
|
42 const data = props.mark.data; |
35 const data = props.mark.data; |
43 return <span style={{ backgroundColor: data.get('color') }}>{props.children}</span> |
36 return <span style={{ backgroundColor: data.get('color') }}>{props.children}</span> |
44 }, |
37 }, |
45 italic: { |
38 italic: { |
46 fontStyle: 'italic' |
39 fontStyle: 'italic' |
52 } |
45 } |
53 |
46 |
54 const annotationCategories = [ |
47 const annotationCategories = [ |
55 { key: 'important', name: 'Important', color: '#F1C40F' }, |
48 { key: 'important', name: 'Important', color: '#F1C40F' }, |
56 { key: 'keyword', name: 'Mot-clé', color: '#2ECC71' }, |
49 { key: 'keyword', name: 'Mot-clé', color: '#2ECC71' }, |
57 { key: 'comment', name: 'Commentaire', color: '#3498DB' } |
50 { key: 'comment', name: 'Commentaire', color: '#3498DB', hasComment: true } |
58 ]; |
51 ]; |
59 |
52 |
60 /** |
53 /** |
61 * The rich text example. |
54 * The rich text example. |
62 * |
55 * |
225 * @param {String} type |
218 * @param {String} type |
226 */ |
219 */ |
227 |
220 |
228 onClickMark = (e, type) => { |
221 onClickMark = (e, type) => { |
229 e.preventDefault() |
222 e.preventDefault() |
230 let { state, hoveringMenu } = this.state |
223 const { state } = this.state |
231 |
224 const transform = state.transform() |
232 let toggleMarkOptions; |
225 |
233 let isPortalOpen = false; |
226 let isPortalOpen = false; |
234 |
227 |
235 if (type === 'highlight') { |
228 if (type === 'category') { |
236 toggleMarkOptions = { type: type, data: { text: this.state.currentSelectionText } } |
229 // Can't use toggleMark here, because it expects the same object |
237 isPortalOpen = !this.state.isPortalOpen; |
230 // @see https://github.com/ianstormtaylor/slate/issues/873 |
|
231 if (this.hasMark('category')) { |
|
232 state.marks.forEach(mark => transform.removeMark(mark)); |
|
233 } else { |
|
234 isPortalOpen = !this.state.isPortalOpen; |
|
235 } |
238 } else { |
236 } else { |
239 toggleMarkOptions = type; |
237 transform.toggleMark(type) |
240 } |
238 } |
241 |
|
242 state = state |
|
243 .transform() |
|
244 .toggleMark(toggleMarkOptions) |
|
245 .apply() |
|
246 |
239 |
247 this.setState({ |
240 this.setState({ |
248 state: state, |
241 state: transform.apply(), |
249 isPortalOpen: isPortalOpen |
242 isPortalOpen: isPortalOpen |
250 }) |
243 }) |
251 } |
244 } |
252 |
245 |
253 /** |
246 /** |
312 // When the portal opens, cache the menu element. |
305 // When the portal opens, cache the menu element. |
313 this.setState({ hoveringMenu: portal.firstChild }) |
306 this.setState({ hoveringMenu: portal.firstChild }) |
314 } |
307 } |
315 |
308 |
316 onPortalClose = (portal) => { |
309 onPortalClose = (portal) => { |
317 |
|
318 let { state } = this.state |
310 let { state } = this.state |
319 const transform = state.transform(); |
311 const transform = state.transform(); |
320 |
|
321 state.marks.forEach(mark => { |
|
322 if (mark.type === 'highlight') { |
|
323 transform.removeMark(mark) |
|
324 } |
|
325 }); |
|
326 |
312 |
327 this.setState({ |
313 this.setState({ |
328 state: transform.apply(), |
314 state: transform.apply(), |
329 isPortalOpen: false |
315 isPortalOpen: false |
330 }) |
316 }) |
334 |
320 |
335 const { state } = this.state; |
321 const { state } = this.state; |
336 const transform = state.transform(); |
322 const transform = state.transform(); |
337 |
323 |
338 state.marks.forEach(mark => transform.removeMark(mark)); |
324 state.marks.forEach(mark => transform.removeMark(mark)); |
339 |
|
340 transform.addMark({ |
325 transform.addMark({ |
341 type: 'annotation', |
326 type: 'category', |
342 data: { |
327 data: { |
343 text: this.state.currentSelectionText, |
328 text: this.state.currentSelectionText, |
344 color: category.color, |
329 color: category.color, |
345 key: category.key |
330 key: category.key |
346 } |
331 } |
348 |
333 |
349 this.setState({ |
334 this.setState({ |
350 state: transform.apply(), |
335 state: transform.apply(), |
351 isPortalOpen: false |
336 isPortalOpen: false |
352 }); |
337 }); |
353 |
|
354 } |
338 } |
355 |
339 |
356 /** |
340 /** |
357 * Render. |
341 * Render. |
358 * |
342 * |
378 return ( |
362 return ( |
379 <div className="menu toolbar-menu"> |
363 <div className="menu toolbar-menu"> |
380 {this.renderMarkButton('bold', 'format_bold')} |
364 {this.renderMarkButton('bold', 'format_bold')} |
381 {this.renderMarkButton('italic', 'format_italic')} |
365 {this.renderMarkButton('italic', 'format_italic')} |
382 {this.renderMarkButton('underlined', 'format_underlined')} |
366 {this.renderMarkButton('underlined', 'format_underlined')} |
383 {this.renderMarkButton('highlight', 'label')} |
367 {this.renderMarkButton('category', 'label')} |
384 |
368 |
385 {this.renderBlockButton('numbered-list', 'format_list_numbered')} |
369 {this.renderBlockButton('numbered-list', 'format_list_numbered')} |
386 {this.renderBlockButton('bulleted-list', 'format_list_bulleted')} |
370 {this.renderBlockButton('bulleted-list', 'format_list_bulleted')} |
387 </div> |
371 </div> |
388 ) |
372 ) |