client/src/components/SlateEditor/CategoryButton.js
author ymh <ymh.work@gmail.com>
Fri, 16 Nov 2018 11:19:13 +0100
changeset 173 0e6703cd0968
permissions -rw-r--r--
Correct the Note editor. Split the source file in sub components. Correct a timing problem on the editor checkbox.

import React from 'react';
import * as R from 'ramda';
import { PortalWithState } from 'react-portal';
import CategoriesTooltip from './CategoriesTooltip';
import { defaultAnnotationsCategories } from '../../constants';

/**
 * Render a category toolbar button.
 *
 * @param {String} type
 * @param {String} icon
 * @return {Element}
 */
export default class CategoryButton extends React.Component {

  constructor(props) {
    super(props);

    this.hoveringMenuRef = React.createRef();
  }

  get hoveringMenu() {
    if(this.hoveringMenuRef) {
      return this.hoveringMenuRef.current;
    }
    return null;
  }

  updateMenu = () => {

    const hoveringMenu = this.hoveringMenu;

    if (!hoveringMenu) return

    const selection = window.getSelection()

    if (selection.isCollapsed) {
      return
    }

    const range = selection.getRangeAt(0)
    const rect = range.getBoundingClientRect()

    hoveringMenu.style.opacity = 1
    hoveringMenu.style.top = `${rect.top + rect.height + window.scrollY + hoveringMenu.offsetHeight}px`
    hoveringMenu.style.left = `${rect.left + window.scrollX - hoveringMenu.offsetWidth / 2 + rect.width / 2}px`
  }

  render = () => {
    const isActive = this.props.isActive;
    const onClickCategoryButton = this.props.onClickCategoryButton;
    const onCategoryClick = this.props.onCategoryClick;
    const annotationCategories = this.props.annotationCategories;

    const markActivation = "button sticky-top" + ((!isActive)?" text-primary":" text-dark");

    return (
      <PortalWithState
        // closeOnOutsideClick
        closeOnEsc
        onOpen={this.updateMenu}
      >
        {({ openPortal, closePortal, isOpen, portal }) => {
          const onMouseDown = R.partial(onClickCategoryButton, [openPortal, closePortal, isOpen]);
          const onCategoryClickHandler = R.partial(onCategoryClick, [closePortal,]);
          return (
            <React.Fragment>
              <span className={markActivation} onMouseDown={onMouseDown} data-active={isActive}>
                <span className="material-icons">label</span>
              </span>
              {portal(
                <div className="hovering-menu" ref={this.hoveringMenuRef}>
                  <CategoriesTooltip categories={annotationCategories || defaultAnnotationsCategories} onCategoryClick={onCategoryClickHandler} />
                </div>
              )}
            </React.Fragment>
          )}
        }
      </PortalWithState>
    )
  }
}