client/src/components/SlateEditor/CategoryButton.js
changeset 173 0e6703cd0968
equal deleted inserted replaced
172:4b780ebbedc6 173:0e6703cd0968
       
     1 import React from 'react';
       
     2 import * as R from 'ramda';
       
     3 import { PortalWithState } from 'react-portal';
       
     4 import CategoriesTooltip from './CategoriesTooltip';
       
     5 import { defaultAnnotationsCategories } from '../../constants';
       
     6 
       
     7 /**
       
     8  * Render a category toolbar button.
       
     9  *
       
    10  * @param {String} type
       
    11  * @param {String} icon
       
    12  * @return {Element}
       
    13  */
       
    14 export default class CategoryButton extends React.Component {
       
    15 
       
    16   constructor(props) {
       
    17     super(props);
       
    18 
       
    19     this.hoveringMenuRef = React.createRef();
       
    20   }
       
    21 
       
    22   get hoveringMenu() {
       
    23     if(this.hoveringMenuRef) {
       
    24       return this.hoveringMenuRef.current;
       
    25     }
       
    26     return null;
       
    27   }
       
    28 
       
    29   updateMenu = () => {
       
    30 
       
    31     const hoveringMenu = this.hoveringMenu;
       
    32 
       
    33     if (!hoveringMenu) return
       
    34 
       
    35     const selection = window.getSelection()
       
    36 
       
    37     if (selection.isCollapsed) {
       
    38       return
       
    39     }
       
    40 
       
    41     const range = selection.getRangeAt(0)
       
    42     const rect = range.getBoundingClientRect()
       
    43 
       
    44     hoveringMenu.style.opacity = 1
       
    45     hoveringMenu.style.top = `${rect.top + rect.height + window.scrollY + hoveringMenu.offsetHeight}px`
       
    46     hoveringMenu.style.left = `${rect.left + window.scrollX - hoveringMenu.offsetWidth / 2 + rect.width / 2}px`
       
    47   }
       
    48 
       
    49   render = () => {
       
    50     const isActive = this.props.isActive;
       
    51     const onClickCategoryButton = this.props.onClickCategoryButton;
       
    52     const onCategoryClick = this.props.onCategoryClick;
       
    53     const annotationCategories = this.props.annotationCategories;
       
    54 
       
    55     const markActivation = "button sticky-top" + ((!isActive)?" text-primary":" text-dark");
       
    56 
       
    57     return (
       
    58       <PortalWithState
       
    59         // closeOnOutsideClick
       
    60         closeOnEsc
       
    61         onOpen={this.updateMenu}
       
    62       >
       
    63         {({ openPortal, closePortal, isOpen, portal }) => {
       
    64           const onMouseDown = R.partial(onClickCategoryButton, [openPortal, closePortal, isOpen]);
       
    65           const onCategoryClickHandler = R.partial(onCategoryClick, [closePortal,]);
       
    66           return (
       
    67             <React.Fragment>
       
    68               <span className={markActivation} onMouseDown={onMouseDown} data-active={isActive}>
       
    69                 <span className="material-icons">label</span>
       
    70               </span>
       
    71               {portal(
       
    72                 <div className="hovering-menu" ref={this.hoveringMenuRef}>
       
    73                   <CategoriesTooltip categories={annotationCategories || defaultAnnotationsCategories} onCategoryClick={onCategoryClickHandler} />
       
    74                 </div>
       
    75               )}
       
    76             </React.Fragment>
       
    77           )}
       
    78         }
       
    79       </PortalWithState>
       
    80     )
       
    81   }
       
    82 }