client/src/components/SlateEditor.js
changeset 25 e04714a1d4eb
parent 21 284e866f55c7
child 26 930e486ad0a8
equal deleted inserted replaced
24:3b3999550508 25:e04714a1d4eb
    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     )