import React = require('react'); import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { Tooltip } from '@material-ui/core'; import { action, computed, IReactionDisposer, observable, ObservableMap, reaction } from 'mobx'; import { observer } from 'mobx-react'; import { ColorState } from 'react-color'; import { Doc, Opt } from '../../../fields/Doc'; import { returnFalse, setupMoveUpEvents, unimplementedFunction, Utils } from '../../../Utils'; import { SelectionManager } from '../../util/SelectionManager'; import { AntimodeMenu, AntimodeMenuProps } from '../AntimodeMenu'; import { LinkPopup } from '../linking/LinkPopup'; import { ButtonDropdown } from '../nodes/formattedText/RichTextMenu'; import './AnchorMenu.scss'; @observer export class AnchorMenu extends AntimodeMenu { static Instance: AnchorMenu; private _disposer: IReactionDisposer | undefined; private _commentCont = React.createRef(); private _palette = [ 'rgba(208, 2, 27, 0.8)', 'rgba(238, 0, 0, 0.8)', 'rgba(245, 166, 35, 0.8)', 'rgba(248, 231, 28, 0.8)', 'rgba(245, 230, 95, 0.616)', 'rgba(139, 87, 42, 0.8)', 'rgba(126, 211, 33, 0.8)', 'rgba(65, 117, 5, 0.8)', 'rgba(144, 19, 254, 0.8)', 'rgba(238, 169, 184, 0.8)', 'rgba(224, 187, 228, 0.8)', 'rgba(225, 223, 211, 0.8)', 'rgba(255, 255, 255, 0.8)', 'rgba(155, 155, 155, 0.8)', 'rgba(0, 0, 0, 0.8)', ]; @observable private _keyValue: string = ''; @observable private _valueValue: string = ''; @observable private _added: boolean = false; @observable private highlightColor: string = 'rgba(245, 230, 95, 0.616)'; @observable private _showLinkPopup: boolean = false; @observable public Highlighting: boolean = false; @observable public Status: 'marquee' | 'annotation' | '' = ''; public onMakeAnchor: () => Opt = () => undefined; // Method to get anchor from text search public OnCrop: (e: PointerEvent) => void = unimplementedFunction; public OnClick: (e: PointerEvent) => void = unimplementedFunction; public StartDrag: (e: PointerEvent, ele: HTMLElement) => void = unimplementedFunction; public StartCropDrag: (e: PointerEvent, ele: HTMLElement) => void = unimplementedFunction; public Highlight: (color: string, isPushpin: boolean) => Opt = (color: string, isPushpin: boolean) => undefined; public GetAnchor: (savedAnnotations?: ObservableMap) => Opt = () => undefined; public Delete: () => void = unimplementedFunction; public AddTag: (key: string, value: string) => boolean = returnFalse; public PinToPres: () => void = unimplementedFunction; public MakePushpin: () => void = unimplementedFunction; public IsPushpin: () => boolean = returnFalse; public get Active() { return this._left > 0; } constructor(props: Readonly<{}>) { super(props); AnchorMenu.Instance = this; AnchorMenu.Instance._canFade = false; } componentDidMount() { this._disposer = reaction( () => SelectionManager.Views(), selected => { this._showLinkPopup = false; AnchorMenu.Instance.fadeOut(true); } ); } pointerDown = (e: React.PointerEvent) => { setupMoveUpEvents( this, e, (e: PointerEvent) => { this.StartDrag(e, this._commentCont.current!); return true; }, returnFalse, e => this.OnClick?.(e) ); }; cropDown = (e: React.PointerEvent) => { setupMoveUpEvents( this, e, (e: PointerEvent) => { this.StartCropDrag(e, this._commentCont.current!); return true; }, returnFalse, e => this.OnCrop?.(e) ); }; @action highlightClicked = (e: React.MouseEvent) => { if (!this.Highlight(this.highlightColor, false) && this.Pinned) { this.Highlighting = !this.Highlighting; } AnchorMenu.Instance.fadeOut(true); }; @action toggleLinkPopup = (e: React.MouseEvent) => { //ignore the potential null type error because this method cannot be called unless the user selects text and clicks the link button //change popup visibility field to visible this._showLinkPopup = !this._showLinkPopup; }; @computed get highlighter() { const button = ( ); const dropdownContent = (

Change highlighter color:

{this._palette.map(color => { if (color) { return this.highlightColor === color ? ( ) : ( ); } })}
); return ( {'Click to Highlight'}}>
); } @action changeHighlightColor = (color: string, e: React.PointerEvent) => { const col: ColorState = { hex: color, hsl: { a: 0, h: 0, s: 0, l: 0, source: '' }, hsv: { a: 0, h: 0, s: 0, v: 0, source: '' }, rgb: { a: 0, r: 0, b: 0, g: 0, source: '' }, oldHue: 0, source: '', }; e.preventDefault(); e.stopPropagation(); this.highlightColor = Utils.colorString(col); }; @action keyChanged = (e: React.ChangeEvent) => { this._keyValue = e.currentTarget.value; }; @action valueChanged = (e: React.ChangeEvent) => { this._valueValue = e.currentTarget.value; }; @action addTag = (e: React.PointerEvent) => { if (this._keyValue.length > 0 && this._valueValue.length > 0) { this._added = this.AddTag(this._keyValue, this._valueValue); setTimeout( action(() => (this._added = false)), 1000 ); } }; render() { const buttons = this.Status === 'marquee' ? [ this.highlighter, {'Drag to Place Annotation'}}> , //NOTE: link popup is currently in progress {'Find document to link to selected text'}}> , , AnchorMenu.Instance.StartCropDrag === unimplementedFunction ? ( <> ) : ( {'Click/Drag to create cropped image'}}> ), ] : [ {'Remove Link Anchor'}}> , {'Pin to Presentation'}}> , {'toggle pushpin behavior'}}> , //
// // //
, // , ]; return this.getElement(buttons); } }