diff options
author | usodhi <61431818+usodhi@users.noreply.github.com> | 2021-01-20 20:07:48 -0500 |
---|---|---|
committer | usodhi <61431818+usodhi@users.noreply.github.com> | 2021-01-20 20:07:48 -0500 |
commit | 7b49bca26f95e7bf1e878d4987f061511a5def39 (patch) | |
tree | b160034ebfd770c73071203410b468778fa93697 /src/client/views/pdf/AnchorMenu.tsx | |
parent | e4c9218e217b617e513259cac90b077431890eaa (diff) | |
parent | 68785a97178d229935c0429791081d7c09312dc3 (diff) |
Merge branch 'master' of https://github.com/browngraphicslab/Dash-Web into filters
Diffstat (limited to 'src/client/views/pdf/AnchorMenu.tsx')
-rw-r--r-- | src/client/views/pdf/AnchorMenu.tsx | 157 |
1 files changed, 157 insertions, 0 deletions
diff --git a/src/client/views/pdf/AnchorMenu.tsx b/src/client/views/pdf/AnchorMenu.tsx new file mode 100644 index 000000000..e2bd5a73d --- /dev/null +++ b/src/client/views/pdf/AnchorMenu.tsx @@ -0,0 +1,157 @@ +import React = require("react"); +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { Tooltip } from "@material-ui/core"; +import { action, computed, observable } 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 { AntimodeMenu, AntimodeMenuProps } from "../AntimodeMenu"; +import { ButtonDropdown } from "../nodes/formattedText/RichTextMenu"; +import "./AnchorMenu.scss"; + +@observer +export class AnchorMenu extends AntimodeMenu<AntimodeMenuProps> { + static Instance: AnchorMenu; + + private _commentCont = React.createRef<HTMLButtonElement>(); + 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 public _colorBtn = false; + @observable public Highlighting: boolean = false; + @observable public Status: "marquee" | "annotation" | "" = ""; + + public StartDrag: (e: PointerEvent, ele: HTMLElement) => void = unimplementedFunction; + public Highlight: (color: string) => Opt<Doc> = (color: string) => 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 Marquee: { left: number; top: number; width: number; height: number; } | undefined; + public get Active() { return this._left > 0; } + + constructor(props: Readonly<{}>) { + super(props); + + AnchorMenu.Instance = this; + AnchorMenu.Instance._canFade = false; + } + + pointerDown = (e: React.PointerEvent) => { + setupMoveUpEvents(this, e, (e: PointerEvent) => { + this.StartDrag(e, this._commentCont.current!); + return true; + }, returnFalse, returnFalse); + } + + @action + highlightClicked = (e: React.MouseEvent) => { + if (!this.Highlight(this.highlightColor) && this.Pinned) { + this.Highlighting = !this.Highlighting; + } + } + + @computed get highlighter() { + const button = + <button className="antimodeMenu-button color-preview-button" title="" key="highlighter-button" onClick={this.highlightClicked}> + <FontAwesomeIcon icon="highlighter" size="lg" style={{ transition: "transform 0.1s", transform: this.Highlighting ? "" : "rotate(-45deg)" }} /> + <div className="color-preview" style={{ backgroundColor: this.highlightColor }}></div> + </button>; + + const dropdownContent = + <div className="dropdown"> + <p>Change highlighter color:</p> + <div className="color-wrapper"> + {this._palette.map(color => { + if (color) { + return this.highlightColor === color ? + <button className="color-button active" key={`active ${color}`} style={{ backgroundColor: color }} onPointerDown={e => this.changeHighlightColor(color, e)}></button> : + <button className="color-button" key={`inactive ${color}`} style={{ backgroundColor: color }} onPointerDown={e => this.changeHighlightColor(color, e)}></button>; + } + })} + </div> + </div>; + return ( + <Tooltip key="highlighter" title={<div className="dash-tooltip">{"Click to Highlight"}</div>}> + <ButtonDropdown key={"highlighter"} button={button} dropdownContent={dropdownContent} pdf={true} /> + </Tooltip> + ); + } + + @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<HTMLInputElement>) => { this._keyValue = e.currentTarget.value; }; + @action valueChanged = (e: React.ChangeEvent<HTMLInputElement>) => { 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, + + <Tooltip key="annotate" title={<div className="dash-tooltip">{"Drag to Place Annotation"}</div>}> + <button className="antimodeMenu-button annotate" ref={this._commentCont} onPointerDown={this.pointerDown} style={{ cursor: "grab" }}> + <FontAwesomeIcon icon="comment-alt" size="lg" /> + </button> + </Tooltip>, + ] : [ + <Tooltip key="trash" title={<div className="dash-tooltip">{"Remove Link Anchor"}</div>}> + <button className="antimodeMenu-button" onPointerDown={this.Delete}> + <FontAwesomeIcon icon="trash-alt" size="lg" /> + </button> + </Tooltip>, + <Tooltip key="Pin" title={<div className="dash-tooltip">{"Pin to Presentation"}</div>}> + <button className="antimodeMenu-button" onPointerDown={this.PinToPres}> + <FontAwesomeIcon icon="map-pin" size="lg" /> + </button> + </Tooltip>, + <Tooltip key="pushpin" title={<div className="dash-tooltip">{"toggle pushpin behavior"}</div>}> + <button className="antimodeMenu-button" style={{ color: this.IsPushpin() ? "black" : "white", backgroundColor: this.IsPushpin() ? "white" : "black" }} onPointerDown={this.MakePushpin}> + <FontAwesomeIcon icon="thumbtack" size="lg" /> + </button> + </Tooltip>, + // <div key="7" className="anchorMenu-addTag" > + // <input onChange={this.keyChanged} placeholder="Key" style={{ gridColumn: 1 }} /> + // <input onChange={this.valueChanged} placeholder="Value" style={{ gridColumn: 3 }} /> + // </div>, + // <button key="8" className="antimodeMenu-button" title={`Add tag: ${this._keyValue} with value: ${this._valueValue}`} onPointerDown={this.addTag}> + // <FontAwesomeIcon style={{ transition: "all .2s" }} color={this._added ? "#42f560" : "white"} icon="check" size="lg" /></button>, + ]; + + return this.getElement(buttons); + } +}
\ No newline at end of file |