/* eslint-disable react/jsx-props-no-spreading */ import { action, computed, makeObservable } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import { Doc, DocListCast, Opt } from '../../../fields/Doc'; import { Id } from '../../../fields/FieldSymbols'; import { List } from '../../../fields/List'; import { BoolCast, DocCast, NumCast, StrCast } from '../../../fields/Types'; import { LinkFollower } from '../../util/LinkFollower'; import { LinkManager } from '../../util/LinkManager'; import { undoable } from '../../util/UndoManager'; import { ObservableReactComponent } from '../ObservableReactComponent'; import { OpenWhere } from '../nodes/DocumentView'; import { FieldViewProps } from '../nodes/FieldView'; import { AnchorMenu } from './AnchorMenu'; import './Annotation.scss'; import { Highlight } from '../../../fields/DocSymbols'; interface IAnnotationProps extends FieldViewProps { anno: Doc; dataDoc: Doc; fieldKey: string; showInfo?: (anno: Opt) => void; pointerEvents?: () => Opt; } @observer export class Annotation extends ObservableReactComponent { constructor(props: any) { super(props); makeObservable(this); } @computed get linkHighlighted() { const found = LinkManager.Instance.getAllDirectLinks(this._props.anno).find(link => { const a1 = LinkManager.getOppositeAnchor(link, this._props.anno); return a1 && Doc.GetBrushStatus(DocCast(a1.annotationOn, a1)); }); return found; } linkHighlightedFunc = () => this.linkHighlighted; highlightedFunc = () => this._props.anno[Highlight]; deleteAnnotation = undoable(() => { const docAnnotations = DocListCast(this._props.dataDoc[this._props.fieldKey]); this._props.dataDoc[this._props.fieldKey] = new List(docAnnotations.filter(a => a !== this._props.anno)); AnchorMenu.Instance.fadeOut(true); this._props.select(false); }, 'delete annotation'); pinToPres = undoable(() => this._props.pinToPres(this._props.anno, {}), 'pin to pres'); render() { return (
{DocListCast(this._props.anno.text_inlineAnnotations).map(a => ( // eslint-disable-next-line no-use-before-define ))}
); } } interface IRegionAnnotationProps extends IAnnotationProps { document: Doc; linkHighlighted: () => Doc | undefined; highlighted: () => any; deleteAnnotation: () => void; pinToPres: (...args: any[]) => void; pointerEvents?: () => Opt; } @observer class RegionAnnotation extends ObservableReactComponent { private _mainCont: React.RefObject = React.createRef(); @computed get regionDoc() { return DocCast(this._props.document.embedContainer, this._props.document); } makeTargetToggle = undoable(() => { this.regionDoc.followLinkToggle = !this.regionDoc.followLinkToggle }, "set link toggle"); // prettier-ignore isTargetToggler = () => BoolCast(this.regionDoc.followLinkToggle); showTargetTrail = undoable((anchor: Doc) => { const trail = DocCast(anchor.presentationTrail); if (trail) { Doc.ActivePresentation = trail; this._props.addDocTab(trail, OpenWhere.replaceRight); } }, 'show target trail'); @action onContextMenu = (e: React.MouseEvent) => { AnchorMenu.Instance.Status = 'annotation'; AnchorMenu.Instance.Delete = this._props.deleteAnnotation; AnchorMenu.Instance.Pinned = false; AnchorMenu.Instance.PinToPres = this._props.pinToPres; AnchorMenu.Instance.MakeTargetToggle = this.makeTargetToggle; AnchorMenu.Instance.IsTargetToggler = this.isTargetToggler; AnchorMenu.Instance.ShowTargetTrail = () => this.showTargetTrail(this.regionDoc); AnchorMenu.Instance.jumpTo(e.clientX, e.clientY, true); e.stopPropagation(); e.preventDefault(); }; @action onPointerDown = (e: React.PointerEvent) => { if (e.button === 2 || e.ctrlKey) { e.stopPropagation(); e.preventDefault(); } else if (e.button === 0) { e.stopPropagation(); LinkFollower.FollowLink(undefined, this.regionDoc, false); } }; render() { const brushed = this.regionDoc && Doc.GetBrushHighlightStatus(this.regionDoc); return (
{ Doc.BrushDoc(this._props.anno); this._props.showInfo?.(this._props.anno); })} onPointerLeave={action(() => { Doc.UnBrushDoc(this._props.anno); this._props.showInfo?.(undefined); })} onPointerDown={this.onPointerDown} onContextMenu={this.onContextMenu} style={{ left: NumCast(this._props.document.x), top: NumCast(this._props.document.y), width: NumCast(this._props.document._width), height: NumCast(this._props.document._height), opacity: brushed === Doc.DocBrushStatus.highlighted ? 0.5 : undefined, pointerEvents: this._props.pointerEvents?.() as any, outline: this._props.linkHighlighted() ? 'solid 1px lightBlue' : undefined, backgroundColor: this._props.highlighted() ? 'orange' : StrCast(this._props.document.backgroundColor), }} /> ); } }