|
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 } |