From ced3532239c582938271635802e0d2d62703e148 Mon Sep 17 00:00:00 2001
From: vellichora <fangrui_tong@brown.edu>
Date: Tue, 7 Jan 2020 14:20:36 -0500
Subject: richtextmenu appears whenever formattedtextbox is focused

---
 src/client/util/TooltipTextMenu.tsx | 2 ++
 1 file changed, 2 insertions(+)

(limited to 'src/client/util/TooltipTextMenu.tsx')

diff --git a/src/client/util/TooltipTextMenu.tsx b/src/client/util/TooltipTextMenu.tsx
index 33257b658..2c4d08b82 100644
--- a/src/client/util/TooltipTextMenu.tsx
+++ b/src/client/util/TooltipTextMenu.tsx
@@ -20,6 +20,8 @@ import { PastelSchemaPalette, DarkPastelSchemaPalette } from '../../new_fields/S
 const { toggleMark, setBlockType } = require("prosemirror-commands");
 const { openPrompt, TextField } = require("./ProsemirrorCopy/prompt.js");
 
+// deprecated in favor of richtextmenu
+
 //appears above a selection of text in a RichTextBox to give user options such as Bold, Italics, etc.
 export class TooltipTextMenu {
     public static Toolbar: HTMLDivElement | undefined;
-- 
cgit v1.2.3-70-g09d2


From 540bda7295f6ee7c2eed848598de6f5df74b2723 Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Thu, 9 Jan 2020 10:04:24 -0500
Subject: fixed many warnings

---
 src/client/util/TooltipTextMenu.tsx                |   4 +-
 .../CollectionFreeFormLinkView.tsx                 |  12 +-
 src/client/views/nodes/DocumentView.tsx            |   1 -
 src/pen-gestures/ndollar.ts                        | 122 +++++++++++----------
 4 files changed, 71 insertions(+), 68 deletions(-)

(limited to 'src/client/util/TooltipTextMenu.tsx')

diff --git a/src/client/util/TooltipTextMenu.tsx b/src/client/util/TooltipTextMenu.tsx
index 8aa304fad..e56930624 100644
--- a/src/client/util/TooltipTextMenu.tsx
+++ b/src/client/util/TooltipTextMenu.tsx
@@ -80,7 +80,7 @@ export class TooltipTextMenu {
             span.appendChild(svg);
 
             return span;
-        }
+        };
 
         const basicItems = [ // init basicItems in minimized toolbar -- paths to svgs are obtained from fontawesome
             { mark: schema.marks.strong, dom: svgIcon("strong", "Bold", "M333.49 238a122 122 0 0 0 27-65.21C367.87 96.49 308 32 233.42 32H34a16 16 0 0 0-16 16v48a16 16 0 0 0 16 16h31.87v288H34a16 16 0 0 0-16 16v48a16 16 0 0 0 16 16h209.32c70.8 0 134.14-51.75 141-122.4 4.74-48.45-16.39-92.06-50.83-119.6zM145.66 112h87.76a48 48 0 0 1 0 96h-87.76zm87.76 288h-87.76V288h87.76a56 56 0 0 1 0 112z") },
@@ -883,7 +883,7 @@ export class TooltipTextMenu {
         if (!lastState || !lastState.doc.eq(view.state.doc) || !lastState.selection.eq(view.state.selection)) {
 
             // UPDATE LINK DROPDOWN
-            const linkTarget = await this.getTextLinkTargetTitle()
+            const linkTarget = await this.getTextLinkTargetTitle();
             const linkDom = this.createLinkTool(linkTarget ? true : false).render(this.view).dom;
             const linkDropdownDom = this.createLinkDropdown(linkTarget).render(this.view).dom;
             this.linkDom && this.tooltip.replaceChild(linkDom, this.linkDom);
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx
index 178a5bcdc..b8fbaef5c 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx
@@ -54,8 +54,8 @@ export class CollectionFreeFormLinkView extends React.Component<CollectionFreeFo
                 } else {
                     setTimeout(() => {
                         (this.props.A.props.Document[(this.props.A.props as any).fieldKey] as Doc);
-                        let m = targetBhyperlink.getBoundingClientRect();
-                        let mp = this.props.A.props.ScreenToLocalTransform().transformPoint(m.right, m.top + 5);
+                        const m = targetBhyperlink.getBoundingClientRect();
+                        const mp = this.props.A.props.ScreenToLocalTransform().transformPoint(m.right, m.top + 5);
                         this.props.A.props.Document[afield + "_x"] = mp[0] / this.props.A.props.PanelWidth() * 100;
                         this.props.A.props.Document[afield + "_y"] = mp[1] / this.props.A.props.PanelHeight() * 100;
                     }, 0);
@@ -66,8 +66,8 @@ export class CollectionFreeFormLinkView extends React.Component<CollectionFreeFo
                 } else {
                     setTimeout(() => {
                         (this.props.B.props.Document[(this.props.B.props as any).fieldKey] as Doc);
-                        let m = targetAhyperlink.getBoundingClientRect();
-                        let mp = this.props.B.props.ScreenToLocalTransform().transformPoint(m.right, m.top + 5);
+                        const m = targetAhyperlink.getBoundingClientRect();
+                        const mp = this.props.B.props.ScreenToLocalTransform().transformPoint(m.right, m.top + 5);
                         this.props.B.props.Document[afield + "_x"] = mp[0] / this.props.B.props.PanelWidth() * 100;
                         this.props.B.props.Document[afield + "_y"] = mp[1] / this.props.B.props.PanelHeight() * 100;
                     }, 0);
@@ -93,8 +93,8 @@ export class CollectionFreeFormLinkView extends React.Component<CollectionFreeFo
             apt.point.x, apt.point.y);
         const pt1 = [apt.point.x, apt.point.y];
         const pt2 = [bpt.point.x, bpt.point.y];
-        let aActive = this.props.A.isSelected() || Doc.IsBrushed(this.props.A.props.Document);
-        let bActive = this.props.A.isSelected() || Doc.IsBrushed(this.props.A.props.Document);
+        const aActive = this.props.A.isSelected() || Doc.IsBrushed(this.props.A.props.Document);
+        const bActive = this.props.A.isSelected() || Doc.IsBrushed(this.props.A.props.Document);
         return !aActive && !bActive ? (null) :
             <line key="linkLine" className="collectionfreeformlinkview-linkLine"
                 style={{ opacity: this._opacity, strokeDasharray: "2 2" }}
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index a14f69f71..10d2e2b3e 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -253,7 +253,6 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
             document.removeEventListener("touchend", this.onTouchEnd);
             document.addEventListener("touchend", this.onTouchEnd);
             if ((e.nativeEvent as any).formattedHandled) e.stopPropagation();
-            console.log("down")
         }
     }
 
diff --git a/src/pen-gestures/ndollar.ts b/src/pen-gestures/ndollar.ts
index 12c2b25bb..872c524d6 100644
--- a/src/pen-gestures/ndollar.ts
+++ b/src/pen-gestures/ndollar.ts
@@ -95,7 +95,7 @@ export class Unistroke {
 
     constructor(public Name: string, useBoundedRotationInvariance: boolean, points: Point[]) {
         this.Points = Resample(points, NumPoints);
-        var radians = IndicativeAngle(this.Points);
+        const radians = IndicativeAngle(this.Points);
         this.Points = RotateBy(this.Points, -radians);
         this.Points = ScaleDimTo(this.Points, SquareSize, OneDThreshold);
         if (useBoundedRotationInvariance) {
@@ -117,14 +117,14 @@ export class Multistroke {
     {
         this.NumStrokes = strokes.length; // number of individual strokes
 
-        var order = new Array(strokes.length); // array of integer indices
+        const order = new Array(strokes.length); // array of integer indices
         for (var i = 0; i < strokes.length; i++) {
             order[i] = i; // initialize
         }
-        var orders = new Array(); // array of integer arrays
+        const orders = new Array(); // array of integer arrays
         HeapPermute(strokes.length, order, /*out*/ orders);
 
-        var unistrokes = MakeUnistrokes(strokes, orders); // returns array of point arrays
+        const unistrokes = MakeUnistrokes(strokes, orders); // returns array of point arrays
         this.Unistrokes = new Array(unistrokes.length); // unistrokes for this multistroke
         for (var j = 0; j < unistrokes.length; j++) {
             this.Unistrokes[j] = new Unistroke(this.Name, useBoundedRotationInvariance, unistrokes[j]);
@@ -247,15 +247,15 @@ export class NDollarRecognizer {
     }
 
     Recognize = (strokes: any[], useBoundedRotationInvariance: boolean = false, requireSameNoOfStrokes: boolean = false, useProtractor: boolean = true) => {
-        var t0 = Date.now();
-        var points = CombineStrokes(strokes); // make one connected unistroke from the given strokes
-        var candidate = new Unistroke("", useBoundedRotationInvariance, points);
+        const t0 = Date.now();
+        const points = CombineStrokes(strokes); // make one connected unistroke from the given strokes
+        const candidate = new Unistroke("", useBoundedRotationInvariance, points);
 
         var u = -1;
         var b = +Infinity;
         for (var i = 0; i < this.Multistrokes.length; i++) // for each multistroke template
         {
-            if (!requireSameNoOfStrokes || strokes.length == this.Multistrokes[i].NumStrokes) // optional -- only attempt match when same # of component strokes
+            if (!requireSameNoOfStrokes || strokes.length === this.Multistrokes[i].NumStrokes) // optional -- only attempt match when same # of component strokes
             {
                 for (var j = 0; j < this.Multistrokes[i].Unistrokes.length; j++) // for each unistroke within this multistroke
                 {
@@ -276,15 +276,15 @@ export class NDollarRecognizer {
                 }
             }
         }
-        var t1 = Date.now();
-        return (u == -1) ? null : new Result(this.Multistrokes[u].Name, useProtractor ? (1.0 - b) : (1.0 - b / HalfDiagonal), t1 - t0);
+        const t1 = Date.now();
+        return (u === -1) ? null : new Result(this.Multistrokes[u].Name, useProtractor ? (1.0 - b) : (1.0 - b / HalfDiagonal), t1 - t0);
     }
 
     AddGesture = (name: string, useBoundedRotationInvariance: boolean, strokes: any[]) => {
         this.Multistrokes[this.Multistrokes.length] = new Multistroke(name, useBoundedRotationInvariance, strokes);
         var num = 0;
         for (var i = 0; i < this.Multistrokes.length; i++) {
-            if (this.Multistrokes[i].Name == name) {
+            if (this.Multistrokes[i].Name === name) {
                 num++;
             }
         }
@@ -302,17 +302,17 @@ export class NDollarRecognizer {
 // Private helper functions from here on down
 //
 function HeapPermute(n: number, order: any[], /*out*/ orders: any[]) {
-    if (n == 1) {
+    if (n === 1) {
         orders[orders.length] = order.slice(); // append copy
     } else {
         for (var i = 0; i < n; i++) {
             HeapPermute(n - 1, order, orders);
-            if (n % 2 == 1) { // swap 0, n-1
-                var tmp = order[0];
+            if (n % 2 === 1) { // swap 0, n-1
+                const tmp = order[0];
                 order[0] = order[n - 1];
                 order[n - 1] = tmp;
             } else { // swap i, n-1
-                var tmp = order[i];
+                const tmp = order[i];
                 order[i] = order[n - 1];
                 order[n - 1] = tmp;
             }
@@ -321,14 +321,14 @@ function HeapPermute(n: number, order: any[], /*out*/ orders: any[]) {
 }
 
 function MakeUnistrokes(strokes: any, orders: any) {
-    var unistrokes = new Array(); // array of point arrays
+    const unistrokes = new Array(); // array of point arrays
     for (var r = 0; r < orders.length; r++) {
         for (var b = 0; b < Math.pow(2, orders[r].length); b++) // use b's bits for directions
         {
-            var unistroke = new Array(); // array of points
+            const unistroke = new Array(); // array of points
             for (var i = 0; i < orders[r].length; i++) {
                 var pts;
-                if (((b >> i) & 1) == 1) {// is b's bit at index i on?
+                if (((b >> i) & 1) === 1) {// is b's bit at index i on?
                     pts = strokes[orders[r][i]].slice().reverse(); // copy and reverse
                 }
                 else {
@@ -345,69 +345,71 @@ function MakeUnistrokes(strokes: any, orders: any) {
 }
 
 function CombineStrokes(strokes: any) {
-    var points = new Array();
+    const points = new Array();
     for (var s = 0; s < strokes.length; s++) {
-        for (var p = 0; p < strokes[s].length; p++)
+        for (var p = 0; p < strokes[s].length; p++) {
             points[points.length] = new Point(strokes[s][p].X, strokes[s][p].Y);
+        }
     }
     return points;
 }
 function Resample(points: any, n: any) {
-    var I = PathLength(points) / (n - 1); // interval length
+    const I = PathLength(points) / (n - 1); // interval length
     var D = 0.0;
-    var newpoints = new Array(points[0]);
+    const newpoints = new Array(points[0]);
     for (var i = 1; i < points.length; i++) {
-        var d = Distance(points[i - 1], points[i]);
+        const d = Distance(points[i - 1], points[i]);
         if ((D + d) >= I) {
-            var qx = points[i - 1].X + ((I - D) / d) * (points[i].X - points[i - 1].X);
-            var qy = points[i - 1].Y + ((I - D) / d) * (points[i].Y - points[i - 1].Y);
-            var q = new Point(qx, qy);
+            const qx = points[i - 1].X + ((I - D) / d) * (points[i].X - points[i - 1].X);
+            const qy = points[i - 1].Y + ((I - D) / d) * (points[i].Y - points[i - 1].Y);
+            const q = new Point(qx, qy);
             newpoints[newpoints.length] = q; // append new point 'q'
             points.splice(i, 0, q); // insert 'q' at position i in points s.t. 'q' will be the next i
             D = 0.0;
         }
         else D += d;
     }
-    if (newpoints.length == n - 1) // somtimes we fall a rounding-error short of adding the last point, so add it if so
+    if (newpoints.length === n - 1) {// sometimes we fall a rounding-error short of adding the last point, so add it if so
         newpoints[newpoints.length] = new Point(points[points.length - 1].X, points[points.length - 1].Y);
+    }
     return newpoints;
 }
 function IndicativeAngle(points: any) {
-    var c = Centroid(points);
+    const c = Centroid(points);
     return Math.atan2(c.Y - points[0].Y, c.X - points[0].X);
 }
 function RotateBy(points: any, radians: any) // rotates points around centroid
 {
-    var c = Centroid(points);
-    var cos = Math.cos(radians);
-    var sin = Math.sin(radians);
-    var newpoints = new Array();
+    const c = Centroid(points);
+    const cos = Math.cos(radians);
+    const sin = Math.sin(radians);
+    const newpoints = new Array();
     for (var i = 0; i < points.length; i++) {
-        var qx = (points[i].X - c.X) * cos - (points[i].Y - c.Y) * sin + c.X
-        var qy = (points[i].X - c.X) * sin + (points[i].Y - c.Y) * cos + c.Y;
+        const qx = (points[i].X - c.X) * cos - (points[i].Y - c.Y) * sin + c.X;
+        const qy = (points[i].X - c.X) * sin + (points[i].Y - c.Y) * cos + c.Y;
         newpoints[newpoints.length] = new Point(qx, qy);
     }
     return newpoints;
 }
 function ScaleDimTo(points: any, size: any, ratio1D: any) // scales bbox uniformly for 1D, non-uniformly for 2D
 {
-    var B = BoundingBox(points);
-    var uniformly = Math.min(B.Width / B.Height, B.Height / B.Width) <= ratio1D; // 1D or 2D gesture test
-    var newpoints = new Array();
+    const B = BoundingBox(points);
+    const uniformly = Math.min(B.Width / B.Height, B.Height / B.Width) <= ratio1D; // 1D or 2D gesture test
+    const newpoints = new Array();
     for (var i = 0; i < points.length; i++) {
-        var qx = uniformly ? points[i].X * (size / Math.max(B.Width, B.Height)) : points[i].X * (size / B.Width);
-        var qy = uniformly ? points[i].Y * (size / Math.max(B.Width, B.Height)) : points[i].Y * (size / B.Height);
+        const qx = uniformly ? points[i].X * (size / Math.max(B.Width, B.Height)) : points[i].X * (size / B.Width);
+        const qy = uniformly ? points[i].Y * (size / Math.max(B.Width, B.Height)) : points[i].Y * (size / B.Height);
         newpoints[newpoints.length] = new Point(qx, qy);
     }
     return newpoints;
 }
 function TranslateTo(points: any, pt: any) // translates points' centroid
 {
-    var c = Centroid(points);
-    var newpoints = new Array();
+    const c = Centroid(points);
+    const newpoints = new Array();
     for (var i = 0; i < points.length; i++) {
-        var qx = points[i].X + pt.X - c.X;
-        var qy = points[i].Y + pt.Y - c.Y;
+        const qx = points[i].X + pt.X - c.X;
+        const qy = points[i].Y + pt.Y - c.Y;
         newpoints[newpoints.length] = new Point(qx, qy);
     }
     return newpoints;
@@ -417,21 +419,21 @@ function Vectorize(points: any, useBoundedRotationInvariance: any) // for Protra
     var cos = 1.0;
     var sin = 0.0;
     if (useBoundedRotationInvariance) {
-        var iAngle = Math.atan2(points[0].Y, points[0].X);
-        var baseOrientation = (Math.PI / 4.0) * Math.floor((iAngle + Math.PI / 8.0) / (Math.PI / 4.0));
+        const iAngle = Math.atan2(points[0].Y, points[0].X);
+        const baseOrientation = (Math.PI / 4.0) * Math.floor((iAngle + Math.PI / 8.0) / (Math.PI / 4.0));
         cos = Math.cos(baseOrientation - iAngle);
         sin = Math.sin(baseOrientation - iAngle);
     }
     var sum = 0.0;
-    var vector = new Array<number>();
+    const vector = new Array<number>();
     for (var i = 0; i < points.length; i++) {
-        var newX = points[i].X * cos - points[i].Y * sin;
-        var newY = points[i].Y * cos + points[i].X * sin;
+        const newX = points[i].X * cos - points[i].Y * sin;
+        const newY = points[i].Y * cos + points[i].X * sin;
         vector[vector.length] = newX;
         vector[vector.length] = newY;
         sum += newX * newX + newY * newY;
     }
-    var magnitude = Math.sqrt(sum);
+    const magnitude = Math.sqrt(sum);
     for (var i = 0; i < vector.length; i++) {
         vector[i] /= magnitude;
     }
@@ -445,7 +447,7 @@ function OptimalCosineDistance(v1: any, v2: any) // for Protractor
         a += v1[i] * v2[i] + v1[i + 1] * v2[i + 1];
         b += v1[i] * v2[i + 1] - v1[i + 1] * v2[i];
     }
-    var angle = Math.atan(b / a);
+    const angle = Math.atan(b / a);
     return Math.acos(a * Math.cos(angle) + b * Math.sin(angle));
 }
 function DistanceAtBestAngle(points: any, T: any, a: any, b: any, threshold: any) {
@@ -471,7 +473,7 @@ function DistanceAtBestAngle(points: any, T: any, a: any, b: any, threshold: any
     return Math.min(f1, f2);
 }
 function DistanceAtAngle(points: any, T: any, radians: any) {
-    var newpoints = RotateBy(points, radians);
+    const newpoints = RotateBy(points, radians);
     return PathDistance(newpoints, T.Points);
 }
 function Centroid(points: any) {
@@ -497,33 +499,35 @@ function BoundingBox(points: any) {
 function PathDistance(pts1: any, pts2: any) // average distance between corresponding points in two paths
 {
     var d = 0.0;
-    for (var i = 0; i < pts1.length; i++) // assumes pts1.length == pts2.length
+    for (var i = 0; i < pts1.length; i++) {// assumes pts1.length == pts2.length
         d += Distance(pts1[i], pts2[i]);
+    }
     return d / pts1.length;
 }
 function PathLength(points: any) // length traversed by a point path
 {
     var d = 0.0;
-    for (var i = 1; i < points.length; i++)
+    for (var i = 1; i < points.length; i++) {
         d += Distance(points[i - 1], points[i]);
+    }
     return d;
 }
 function Distance(p1: any, p2: any) // distance between two points
 {
-    var dx = p2.X - p1.X;
-    var dy = p2.Y - p1.Y;
+    const dx = p2.X - p1.X;
+    const dy = p2.Y - p1.Y;
     return Math.sqrt(dx * dx + dy * dy);
 }
 function CalcStartUnitVector(points: any, index: any) // start angle from points[0] to points[index] normalized as a unit vector
 {
-    var v = new Point(points[index].X - points[0].X, points[index].Y - points[0].Y);
-    var len = Math.sqrt(v.X * v.X + v.Y * v.Y);
+    const v = new Point(points[index].X - points[0].X, points[index].Y - points[0].Y);
+    const len = Math.sqrt(v.X * v.X + v.Y * v.Y);
     return new Point(v.X / len, v.Y / len);
 }
 function AngleBetweenUnitVectors(v1: any, v2: any) // gives acute angle between unit vectors from (0,0) to v1, and (0,0) to v2
 {
-    var n = (v1.X * v2.X + v1.Y * v2.Y);
-    var c = Math.max(-1.0, Math.min(1.0, n)); // ensure [-1,+1]
+    const n = (v1.X * v2.X + v1.Y * v2.Y);
+    const c = Math.max(-1.0, Math.min(1.0, n)); // ensure [-1,+1]
     return Math.acos(c); // arc cosine of the vector dot product
 }
 function Deg2Rad(d: any) { return (d * Math.PI / 180.0); }
\ No newline at end of file
-- 
cgit v1.2.3-70-g09d2


From 5abc4de3c3495db71b0a9bcbe2468828f674eff3 Mon Sep 17 00:00:00 2001
From: Fawn <fangrui_tong@brown.edu>
Date: Thu, 9 Jan 2020 16:41:52 -0500
Subject: minor merge

---
 package-lock.json                   |  6 +-----
 src/client/util/RichTextMenu.tsx    |  4 ++--
 src/client/util/TooltipTextMenu.tsx | 14 ++++++--------
 src/client/views/AntimodeMenu.tsx   |  2 +-
 4 files changed, 10 insertions(+), 16 deletions(-)

(limited to 'src/client/util/TooltipTextMenu.tsx')

diff --git a/package-lock.json b/package-lock.json
index cad3edd82..6aa0ffc02 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -7073,11 +7073,7 @@
                 "babel-runtime": "^6.22.0",
                 "bluebird": "^3.4.7",
                 "boolify-string": "^2.0.2",
-<<<<<<< HEAD
-                "emit-logger": "github:chocolateboy/emit-logger#b9d25a2d939e42f29c940861e9648bd0fb810070",
-=======
                 "emit-logger": "github:chocolateboy/emit-logger#better-emitter-name",
->>>>>>> 540bda7295f6ee7c2eed848598de6f5df74b2723
                 "lodash": "^4.17.4",
                 "semver": "^5.0.3",
                 "source-map-support": "^0.5.9"
@@ -18091,4 +18087,4 @@
             }
         }
     }
-}
+}
\ No newline at end of file
diff --git a/src/client/util/RichTextMenu.tsx b/src/client/util/RichTextMenu.tsx
index e367cf350..375c10da3 100644
--- a/src/client/util/RichTextMenu.tsx
+++ b/src/client/util/RichTextMenu.tsx
@@ -208,7 +208,7 @@ export default class RichTextMenu extends AntimodeMenu {
     getMarksInSelection(state: EditorState<any>) {
         const found = new Set<Mark>();
         const { from, to } = state.selection as TextSelection;
-        state.doc.nodesBetween(from, to, (node) => node.marks ?.forEach(m => found.add(m)));
+        state.doc.nodesBetween(from, to, (node) => node.marks.forEach(m => found.add(m)));
         return found;
     }
 
@@ -768,6 +768,6 @@ class ButtonDropdown extends React.Component<ButtonDropdownProps> {
                 <button className="dropdown-button antimodeMenu-button" onPointerDown={this.onDropdownClick}><FontAwesomeIcon icon="caret-down" size="sm" /></button>
                 {this.showDropdown ? this.props.dropdownContent : <></>}
             </div>
-        )
+        );
     }
 }
\ No newline at end of file
diff --git a/src/client/util/TooltipTextMenu.tsx b/src/client/util/TooltipTextMenu.tsx
index 8177593c2..1c15dca7f 100644
--- a/src/client/util/TooltipTextMenu.tsx
+++ b/src/client/util/TooltipTextMenu.tsx
@@ -18,8 +18,6 @@ import { SelectionManager } from './SelectionManager';
 import { PastelSchemaPalette, DarkPastelSchemaPalette } from '../../new_fields/SchemaHeaderField';
 const { toggleMark } = require("prosemirror-commands");
 
-// deprecated in favor of richtextmenu
-
 //appears above a selection of text in a RichTextBox to give user options such as Bold, Italics, etc.
 export class TooltipTextMenu {
     public static Toolbar: HTMLDivElement | undefined;
@@ -95,7 +93,7 @@ export class TooltipTextMenu {
             { mark: schema.marks.subscript, dom: svgIcon("subscript", "Subscript", "M496 448h-16V304a16 16 0 0 0-16-16h-48a16 16 0 0 0-14.29 8.83l-16 32A16 16 0 0 0 400 352h16v96h-16a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h96a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zM336 64h-67a16 16 0 0 0-13.14 6.87l-79.9 115-79.9-115A16 16 0 0 0 83 64H16A16 16 0 0 0 0 80v48a16 16 0 0 0 16 16h33.48l77.81 112-77.81 112H16a16 16 0 0 0-16 16v48a16 16 0 0 0 16 16h67a16 16 0 0 0 13.14-6.87l79.9-115 79.9 115A16 16 0 0 0 269 448h67a16 16 0 0 0 16-16v-48a16 16 0 0 0-16-16h-33.48l-77.81-112 77.81-112H336a16 16 0 0 0 16-16V80a16 16 0 0 0-16-16z") },
         ];
 
-        basicItems.map(({ dom, mark }) => this.basicTools?.appendChild(dom.cloneNode(true)));
+        basicItems.map(({ dom, mark }) => this.basicTools ?.appendChild(dom.cloneNode(true)));
         basicItems.concat(items).forEach(({ dom, mark }) => {
             this.tooltip.appendChild(dom);
             this._marksToDoms.set(mark, dom);
@@ -476,7 +474,7 @@ export class TooltipTextMenu {
                 const node = self.view.state.selection.$from.nodeAfter;
                 const link = node && node.marks.find(m => m.type === self.view.state.schema.marks.link);
                 const href = link!.attrs.href;
-                if (href?.indexOf(Utils.prepend("/doc/")) === 0) {
+                if (href ?.indexOf(Utils.prepend("/doc/")) === 0) {
                     const linkclicked = href.replace(Utils.prepend("/doc/"), "").split("?")[0];
                     linkclicked && DocServer.GetRefField(linkclicked).then(async linkDoc => {
                         if (linkDoc instanceof Doc) {
@@ -502,7 +500,7 @@ export class TooltipTextMenu {
         const link = this.view.state.schema.marks.link.create({ href: Utils.prepend("/doc/" + linkDocId), title: title, location: location, targetId: targetDocId });
         this.view.dispatch(this.view.state.tr.removeMark(this.view.state.selection.from, this.view.state.selection.to, this.view.state.schema.marks.link).
             addMark(this.view.state.selection.from, this.view.state.selection.to, link));
-        return this.view.state.selection.$from.nodeAfter?.text || "";
+        return this.view.state.selection.$from.nodeAfter ?.text || "";
     }
 
     // SUMMARIZER TOOL
@@ -512,7 +510,7 @@ export class TooltipTextMenu {
             const tr = state.tr.addMark(state.selection.from, state.selection.to, mark);
             const content = tr.selection.content();
             const newNode = state.schema.nodes.summary.create({ visibility: false, text: content, textslice: content.toJSON() });
-            dispatch?.(tr.replaceSelectionWith(newNode).removeMark(tr.selection.from - 1, tr.selection.from, mark));
+            dispatch ?.(tr.replaceSelectionWith(newNode).removeMark(tr.selection.from - 1, tr.selection.from, mark));
         }
     }
 
@@ -739,7 +737,7 @@ export class TooltipTextMenu {
             // get marks in the selection
             const selected_marks = new Set<Mark>();
             const { from, to } = state.selection as TextSelection;
-            state.doc.nodesBetween(from, to, (node) => node.marks?.forEach(m => selected_marks.add(m)));
+            state.doc.nodesBetween(from, to, (node) => node.marks ?.forEach(m => selected_marks.add(m)));
 
             if (this._brushdom && selected_marks.size >= 0) {
                 TooltipTextMenuManager.Instance._brushMarks = selected_marks;
@@ -851,7 +849,7 @@ export class TooltipTextMenu {
     static setMark = (mark: Mark, state: EditorState<any>, dispatch: any) => {
         if (mark) {
             const node = (state.selection as NodeSelection).node;
-            if (node?.type === schema.nodes.ordered_list) {
+            if (node ?.type === schema.nodes.ordered_list) {
                 let attrs = node.attrs;
                 if (mark.type === schema.marks.pFontFamily) attrs = { ...attrs, setFontFamily: mark.attrs.family };
                 if (mark.type === schema.marks.pFontSize) attrs = { ...attrs, setFontSize: mark.attrs.fontSize };
diff --git a/src/client/views/AntimodeMenu.tsx b/src/client/views/AntimodeMenu.tsx
index e358d88cf..4625eb92f 100644
--- a/src/client/views/AntimodeMenu.tsx
+++ b/src/client/views/AntimodeMenu.tsx
@@ -127,7 +127,7 @@ export default abstract class AntimodeMenu extends React.Component {
     }
 
     protected getDragger = () => {
-        return <div className="antimodeMenu-dragger" onPointerDown={this.dragStart} style={{ width: this.Pinned ? "20px" : "0px" }} />
+        return <div className="antimodeMenu-dragger" onPointerDown={this.dragStart} style={{ width: this.Pinned ? "20px" : "0px" }} />;
     }
 
     protected getElement(buttons: JSX.Element[]) {
-- 
cgit v1.2.3-70-g09d2


From d528b9d19a685d8447a9d54715dc94cd66034852 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Mon, 20 Jan 2020 21:18:10 -0500
Subject: fixed linking to text region.  fixed link displays.  removed old
 tooltiptextmenu.  fixed brushes in richTextMenu.

---
 src/client/util/ProsemirrorExampleTransfer.ts      |    2 -
 src/client/util/RichTextMenu.tsx                   |   25 +-
 src/client/util/RichTextRules.ts                   |    4 +-
 src/client/util/RichTextSchema.tsx                 |    3 +-
 src/client/util/TooltipLinkingMenu.tsx             |   68 --
 src/client/util/TooltipTextMenu.scss               |  372 -------
 src/client/util/TooltipTextMenu.tsx                | 1042 --------------------
 src/client/views/DocumentButtonBar.tsx             |    8 +-
 src/client/views/DocumentDecorations.tsx           |    8 -
 src/client/views/nodes/DocumentContentsView.tsx    |    2 +-
 src/client/views/nodes/FormattedTextBox.tsx        |   22 +-
 .../authentication/models/current_user_utils.ts    |    4 +-
 12 files changed, 37 insertions(+), 1523 deletions(-)
 delete mode 100644 src/client/util/TooltipLinkingMenu.tsx
 delete mode 100644 src/client/util/TooltipTextMenu.scss
 delete mode 100644 src/client/util/TooltipTextMenu.tsx

(limited to 'src/client/util/TooltipTextMenu.tsx')

diff --git a/src/client/util/ProsemirrorExampleTransfer.ts b/src/client/util/ProsemirrorExampleTransfer.ts
index c028dbf8b..da3815181 100644
--- a/src/client/util/ProsemirrorExampleTransfer.ts
+++ b/src/client/util/ProsemirrorExampleTransfer.ts
@@ -5,9 +5,7 @@ import { Schema } from "prosemirror-model";
 import { liftListItem, sinkListItem } from "./prosemirrorPatches.js";
 import { splitListItem, wrapInList, } from "prosemirror-schema-list";
 import { EditorState, Transaction, TextSelection } from "prosemirror-state";
-import { TooltipTextMenu } from "./TooltipTextMenu";
 import { SelectionManager } from "./SelectionManager";
-import { FormattedTextBox } from "../views/nodes/FormattedTextBox";
 
 const mac = typeof navigator !== "undefined" ? /Mac/.test(navigator.platform) : false;
 
diff --git a/src/client/util/RichTextMenu.tsx b/src/client/util/RichTextMenu.tsx
index 419d7caf9..f070589ae 100644
--- a/src/client/util/RichTextMenu.tsx
+++ b/src/client/util/RichTextMenu.tsx
@@ -32,8 +32,9 @@ export default class RichTextMenu extends AntimodeMenu {
     public overMenu: boolean = false; // kind of hacky way to prevent selects not being selectable
 
     private view?: EditorView;
-    private editorProps: FieldViewProps & FormattedTextBoxProps | undefined;
+    public editorProps: FieldViewProps & FormattedTextBoxProps | undefined;
 
+    public _brushMap: Map<string, Set<Mark>> = new Map();
     private fontSizeOptions: { mark: Mark | null, title: string, label: string, command: any, hidden?: boolean, style?: {} }[];
     private fontFamilyOptions: { mark: Mark | null, title: string, label: string, command: any, hidden?: boolean, style?: {} }[];
     private listTypeOptions: { node: NodeType | any | null, title: string, label: string, command: any, style?: {} }[];
@@ -142,6 +143,17 @@ export default class RichTextMenu extends AntimodeMenu {
         this.updateFromDash(view, lastState, this.editorProps);
     }
 
+
+    public MakeLinkToSelection = (linkDocId: string, title: string, location: string, targetDocId: string): string => {
+        if (this.view) {
+            const link = this.view.state.schema.marks.link.create({ href: Utils.prepend("/doc/" + linkDocId), title: title, location: location, targetId: targetDocId });
+            this.view.dispatch(this.view.state.tr.removeMark(this.view.state.selection.from, this.view.state.selection.to, this.view.state.schema.marks.link).
+                addMark(this.view.state.selection.from, this.view.state.selection.to, link));
+            return this.view.state.selection.$from.nodeAfter?.text || "";
+        }
+        return "";
+    }
+
     @action
     public async updateFromDash(view: EditorView, lastState: EditorState | undefined, props: any) {
         if (!view) {
@@ -417,6 +429,15 @@ export default class RichTextMenu extends AntimodeMenu {
 
     @action toggleBrushDropdown() { this.showBrushDropdown = !this.showBrushDropdown; }
 
+    // todo: add brushes to brushMap to save with a style name
+    onBrushNameKeyPress = (e: React.KeyboardEvent) => {
+        if (e.key === "Enter") {
+            RichTextMenu.Instance.brushMarks && RichTextMenu.Instance._brushMap.set(this._brushNameRef.current!.value, RichTextMenu.Instance.brushMarks);
+            this._brushNameRef.current!.style.background = "lightGray";
+        }
+    }
+    _brushNameRef = React.createRef<HTMLInputElement>();
+
     createBrushButton() {
         const self = this;
         function onBrushClick(e: React.PointerEvent) {
@@ -447,7 +468,7 @@ export default class RichTextMenu extends AntimodeMenu {
             <div className="dropdown">
                 <p>{label}</p>
                 <button onPointerDown={this.clearBrush}>Clear brush</button>
-                {/* <input placeholder="Enter URL"></input> */}
+                <input placeholder="-brush name-" ref={this._brushNameRef} onKeyPress={this.onBrushNameKeyPress}></input>
             </div>;
 
         return (
diff --git a/src/client/util/RichTextRules.ts b/src/client/util/RichTextRules.ts
index 29b378299..e20abb04c 100644
--- a/src/client/util/RichTextRules.ts
+++ b/src/client/util/RichTextRules.ts
@@ -5,11 +5,11 @@ import { NodeSelection, TextSelection } from "prosemirror-state";
 import { NumCast, Cast } from "../../new_fields/Types";
 import { Doc } from "../../new_fields/Doc";
 import { FormattedTextBox } from "../views/nodes/FormattedTextBox";
-import { TooltipTextMenuManager } from "../util/TooltipTextMenu";
 import { Docs, DocUtils } from "../documents/Documents";
 import { Id } from "../../new_fields/FieldSymbols";
 import { DocServer } from "../DocServer";
 import { returnFalse, Utils } from "../../Utils";
+import RichTextMenu from "./RichTextMenu";
 
 export const inpRules = {
     rules: [
@@ -264,7 +264,7 @@ export const inpRules = {
             new RegExp(/%[a-z]+$/),
             (state, match, start, end) => {
                 const color = match[0].substring(1, match[0].length);
-                const marks = TooltipTextMenuManager.Instance._brushMap.get(color);
+                const marks = RichTextMenu.Instance._brushMap.get(color);
                 if (marks) {
                     const tr = state.tr.deleteRange(start, end);
                     return marks ? Array.from(marks).reduce((tr, m) => tr.addStoredMark(m), tr) : tr;
diff --git a/src/client/util/RichTextSchema.tsx b/src/client/util/RichTextSchema.tsx
index ef90a7294..1f70cafc4 100644
--- a/src/client/util/RichTextSchema.tsx
+++ b/src/client/util/RichTextSchema.tsx
@@ -855,7 +855,8 @@ export class FootnoteView {
                 }),
                 new Plugin({
                     view(newView) {
-                        return FormattedTextBox.getToolTip(newView);
+                        // TODO -- make this work with RichTextMenu
+                        // return FormattedTextBox.getToolTip(newView);
                     }
                 })
                 ],
diff --git a/src/client/util/TooltipLinkingMenu.tsx b/src/client/util/TooltipLinkingMenu.tsx
deleted file mode 100644
index b46675a04..000000000
--- a/src/client/util/TooltipLinkingMenu.tsx
+++ /dev/null
@@ -1,68 +0,0 @@
-import { EditorState } from "prosemirror-state";
-import { EditorView } from "prosemirror-view";
-import { FieldViewProps } from "../views/nodes/FieldView";
-import "./TooltipTextMenu.scss";
-
-//appears above a selection of text in a RichTextBox to give user options such as Bold, Italics, etc.
-export class TooltipLinkingMenu {
-
-    private tooltip: HTMLElement;
-    private view: EditorView;
-    private editorProps: FieldViewProps;
-
-    constructor(view: EditorView, editorProps: FieldViewProps) {
-        this.view = view;
-        this.editorProps = editorProps;
-        this.tooltip = document.createElement("div");
-        this.tooltip.className = "tooltipMenu linking";
-
-        //add the div which is the tooltip
-        view.dom.parentNode!.parentNode!.appendChild(this.tooltip);
-
-        const target = "https://www.google.com";
-
-        const link = document.createElement("a");
-        link.href = target;
-        link.textContent = target;
-        link.target = "_blank";
-        link.style.color = "white";
-        this.tooltip.appendChild(link);
-
-        this.update(view, undefined);
-    }
-
-    //updates the tooltip menu when the selection changes
-    update(view: EditorView, lastState: EditorState | undefined) {
-        const state = view.state;
-        // Don't do anything if the document/selection didn't change
-        if (lastState && lastState.doc.eq(state.doc) &&
-            lastState.selection.eq(state.selection)) return;
-
-        // Hide the tooltip if the selection is empty
-        if (state.selection.empty) {
-            this.tooltip.style.display = "none";
-            return;
-        }
-
-        console.log("STORED:");
-        console.log(state.doc.content.firstChild!.content);
-
-        // Otherwise, reposition it and update its content
-        this.tooltip.style.display = "";
-        const { from, to } = state.selection;
-        const start = view.coordsAtPos(from), end = view.coordsAtPos(to);
-        // The box in which the tooltip is positioned, to use as base
-        const box = this.tooltip.offsetParent!.getBoundingClientRect();
-        // Find a center-ish x position from the selection endpoints (when
-        // crossing lines, end may be more to the left)
-        const left = Math.max((start.left + end.left) / 2, start.left + 3);
-        this.tooltip.style.left = (left - box.left) * this.editorProps.ScreenToLocalTransform().Scale + "px";
-        const width = Math.abs(start.left - end.left) / 2 * this.editorProps.ScreenToLocalTransform().Scale;
-        const mid = Math.min(start.left, end.left) + width;
-
-        this.tooltip.style.width = "auto";
-        this.tooltip.style.bottom = (box.bottom - start.top) * this.editorProps.ScreenToLocalTransform().Scale + "px";
-    }
-
-    destroy() { this.tooltip.remove(); }
-}
diff --git a/src/client/util/TooltipTextMenu.scss b/src/client/util/TooltipTextMenu.scss
deleted file mode 100644
index 2a38fe118..000000000
--- a/src/client/util/TooltipTextMenu.scss
+++ /dev/null
@@ -1,372 +0,0 @@
-@import "../views/globalCssVariables";
-.ProseMirror-menu-dropdown-wrap {
-    display: inline-block;
-    position: relative;
-}
-  
-.ProseMirror-menu-dropdown {
-    vertical-align: 1px;
-    cursor: pointer;
-    position: relative;
-    padding: 0 15px 0 4px;
-    background: white;
-    border-radius: 2px;
-    text-align: left;
-    font-size: 12px;
-    white-space: nowrap;
-    margin-right: 4px;
-
-    &:after {
-        content: "";
-        border-left: 4px solid transparent;
-        border-right: 4px solid transparent;
-        border-top: 4px solid currentColor;
-        opacity: .6;
-        position: absolute;
-        right: 4px;
-        top: calc(50% - 2px);
-    }
-}
-
-.ProseMirror-menu-submenu-wrap {
-    position: relative;
-    margin-right: -4px;
-}
-
-.ProseMirror-menu-dropdown-menu, 
-.ProseMirror-menu-submenu {
-    font-size: 12px;
-    background: white;
-    border: 1px solid rgb(223, 223, 223);
-    min-width: 40px;
-    z-index: 50000;
-    position: absolute;
-    box-sizing: content-box;
-
-    .ProseMirror-menu-dropdown-item {
-        cursor: pointer;
-        z-index: 100000;
-        text-align: left;
-        padding: 3px;
-
-        &:hover {
-            background-color: $light-color-secondary;
-        }
-    }
-}
-
-
-.ProseMirror-menu-submenu-label:after {
-    content: "";
-    border-top: 4px solid transparent;
-    border-bottom: 4px solid transparent;
-    border-left: 4px solid currentColor;
-    opacity: .6;
-    position: absolute;
-    right: 4px;
-    top: calc(50% - 4px);
-}
-  
-  .ProseMirror-icon {
-    display: inline-block;
-    // line-height: .8;
-    // vertical-align: -2px; /* Compensate for padding */
-    // padding: 2px 8px;
-    cursor: pointer;
-
-    &.ProseMirror-menu-disabled {
-        cursor: default;
-    }
-
-    svg {
-        fill:white;
-        height: 1em;
-    }
-
-    span {
-        vertical-align: text-top;
-      }  
-  }
-
-.wrapper {
-    position: absolute;
-    pointer-events: all;
-    display: flex;
-    align-items: center;
-    transform: translateY(-85px);
-
-    height: 35px;
-    background: #323232;
-    border-radius: 6px;
-    box-shadow: 3px 3px 3px rgba(0, 0, 0, 0.25);
-
-}
-
-.tooltipMenu, .basic-tools {
-    z-index: 20000;
-    pointer-events: all;
-    padding: 3px;
-    padding-bottom: 5px;
-    display: flex;
-    align-items: center;
-
-    .ProseMirror-example-setup-style hr {
-      padding: 2px 10px;
-      border: none;
-      margin: 1em 0;
-    }
-    
-    .ProseMirror-example-setup-style hr:after {
-      content: "";
-      display: block;
-      height: 1px;
-      background-color: silver;
-      line-height: 2px;
-    }
-}
-
-.menuicon {
-    width: 25px;
-    height: 25px;
-    cursor: pointer;
-    text-align: center;
-    line-height: 25px;
-    margin: 0 2px;
-    border-radius: 3px;
-
-    &:hover {
-        background-color: black;
-
-        #link-drag {
-            background-color: black;
-        }
-    }
-
-    &> * {
-        margin-top: 50%;
-        margin-left: 50%;
-        transform: translate(-50%, -50%);
-    }
-
-    svg {
-        fill: inherit;
-        width: 18px;
-        height: 18px;
-    }
-}
-
-.menuicon-active {
-    width: 25px;
-    height: 25px;
-    cursor: pointer;
-    text-align: center;
-    line-height: 25px;
-    margin: 0 2px;
-    border-radius: 3px;
-
-    &:hover {
-        background-color: black;
-    }
-
-    &> * {
-        margin-top: 50%;
-        margin-left: 50%;
-        transform: translate(-50%, -50%);
-    }
-
-    svg {
-        fill: greenyellow;
-        width: 18px;
-        height: 18px;
-    }
-}
-
-.colorPicker {
-    position: relative;
-
-    svg {
-        width: 18px;
-        height: 18px;
-        // margin-top: 11px;
-    }
-
-    .buttonColor {
-        position: absolute;
-        top: 24px;
-        left: 1px;
-        width: 24px;
-        height: 4px;
-        margin-top: 0;
-    }
-}
-
-#link-drag {
-    background-color: #323232;
-}
-
-.underline svg {
-    margin-top: 13px;
-}
-
-  .font-size-indicator {
-      font-size: 12px;
-      padding-right: 0px;
-  }
-  .summarize{
-      color: white;
-      height: 20px;
-      text-align: center;
-  }
-  
-
-.brush{
-    display: inline-block;
-    width: 1em;
-    height: 1em;
-    stroke-width: 0;
-    stroke: currentColor;
-    fill: currentColor;
-    margin-right: 15px;
-}
-
-.brush-active{
-    display: inline-block;
-    width: 1em;
-    height: 1em;
-    stroke-width: 3;
-    fill: greenyellow;
-    margin-right: 15px;
-}
-
-.dragger-wrapper {
-    color: #eee;
-    height: 22px;
-    padding: 0 5px;
-    box-sizing: content-box;
-    cursor: grab;
-
-    .dragger {
-        width: 18px;
-        height: 100%;
-        display: flex;
-        justify-content: space-evenly;
-    }
-
-    .dragger-line {
-        width: 2px;
-        height: 100%;
-        background-color: black;
-    }
-}
-
-.button-dropdown-wrapper {
-    display: flex;
-    align-content: center;
-
-    &:hover {
-        background-color: black;
-    }
-}
-
-.buttonSettings-dropdown {
-
-    &.ProseMirror-menu-dropdown {
-        width: 10px;
-        height: 25px;
-        margin: 0;
-        padding: 0 2px;
-        background-color: #323232;
-        text-align: center;
-
-        &:after {
-            border-top: 4px solid white;
-            right: 2px;
-        }
-
-        &:hover {
-            background-color: black;
-        }
-    }
-
-    &.ProseMirror-menu-dropdown-menu {
-        min-width: 150px;
-        left: -27px;
-        top: 31px;
-        background-color: #323232;
-        border: 1px solid #4d4d4d;
-        color: $light-color-secondary;
-        // border: none;
-        // border: 1px solid $light-color-secondary;
-        border-radius: 0 6px 6px 6px;
-        padding: 3px;
-        box-shadow: 3px 3px 3px rgba(0, 0, 0, 0.25);
-
-        .ProseMirror-menu-dropdown-item{
-            cursor: default;
-
-            &:last-child {
-                border-bottom: none;
-            }
-
-            &:hover {
-                background-color: #323232;
-            }
-
-            .button-setting, .button-setting-disabled {
-                padding: 2px;
-                border-radius: 2px;
-            }
-
-            .button-setting:hover {
-                cursor: pointer;
-                background-color: black;
-            }
-
-            .separated-button {
-                border-top: 1px solid $light-color-secondary;
-                padding-top: 6px;
-            }
-
-            input {
-               color: black;
-               border: none;
-               border-radius: 1px;
-               padding: 3px;
-            }
-
-            button {
-               padding: 6px;
-               background-color: #323232;
-               border: 1px solid black;
-               border-radius: 1px;
-
-                &:hover {
-                   background-color: black;
-                }
-            }
-        }
-
-
-    }
-}
-
-.colorPicker-wrapper {
-    display: flex;
-    flex-wrap: wrap;
-    justify-content: space-between;
-    margin-top: 3px;
-    margin-left: -3px;
-    width: calc(100% + 6px);
-}
-
-button.colorPicker {
-    width: 20px;
-    height: 20px;
-    border-radius: 15px !important;
-    margin: 3px;
-    border: none !important;
-
-    &.active {
-        border: 2px solid white !important;
-    }
-}
\ No newline at end of file
diff --git a/src/client/util/TooltipTextMenu.tsx b/src/client/util/TooltipTextMenu.tsx
deleted file mode 100644
index 1c15dca7f..000000000
--- a/src/client/util/TooltipTextMenu.tsx
+++ /dev/null
@@ -1,1042 +0,0 @@
-import { Dropdown, icons, MenuItem } from "prosemirror-menu"; //no import css
-import { Mark, MarkType, Node as ProsNode, NodeType, ResolvedPos, Schema } from "prosemirror-model";
-import { wrapInList } from 'prosemirror-schema-list';
-import { EditorState, NodeSelection, TextSelection } from "prosemirror-state";
-import { EditorView } from "prosemirror-view";
-import { Doc, Field, Opt } from "../../new_fields/Doc";
-import { Utils } from "../../Utils";
-import { DocServer } from "../DocServer";
-import { FieldViewProps } from "../views/nodes/FieldView";
-import { FormattedTextBoxProps } from "../views/nodes/FormattedTextBox";
-import { LinkManager } from "./LinkManager";
-import { schema } from "./RichTextSchema";
-import "./TooltipTextMenu.scss";
-import { Cast, NumCast, StrCast } from '../../new_fields/Types';
-import { updateBullets } from './ProsemirrorExampleTransfer';
-import { DocumentDecorations } from '../views/DocumentDecorations';
-import { SelectionManager } from './SelectionManager';
-import { PastelSchemaPalette, DarkPastelSchemaPalette } from '../../new_fields/SchemaHeaderField';
-const { toggleMark } = require("prosemirror-commands");
-
-//appears above a selection of text in a RichTextBox to give user options such as Bold, Italics, etc.
-export class TooltipTextMenu {
-    public static Toolbar: HTMLDivElement | undefined;
-
-    // editor state properties
-    private view: EditorView;
-    private editorProps: FieldViewProps & FormattedTextBoxProps | undefined;
-
-    private fontStyles: Mark[] = [];
-    private fontSizes: Mark[] = [];
-    private _marksToDoms: Map<MarkType, HTMLSpanElement> = new Map();
-    private _collapsed: boolean = false;
-
-    // editor doms
-    public tooltip: HTMLElement = document.createElement("div");
-    private wrapper: HTMLDivElement = document.createElement("div");
-
-    // editor button doms
-    private colorDom?: Node;
-    private colorDropdownDom?: Node;
-    private linkDom?: Node;
-    private highighterDom?: Node;
-    private highlighterDropdownDom?: Node;
-    private linkDropdownDom?: Node;
-    private _brushdom?: Node;
-    private _brushDropdownDom?: Node;
-    private fontSizeDom?: Node;
-    private fontStyleDom?: Node;
-    private basicTools?: HTMLElement;
-
-    static createDiv(className: string) { const div = document.createElement("div"); div.className = className; return div; }
-    static createSpan(className: string) { const div = document.createElement("span"); div.className = className; return div; }
-    constructor(view: EditorView) {
-        this.view = view;
-
-        // initialize the tooltip -- sets this.tooltip
-        this.initTooltip(view);
-
-        // initialize the wrapper
-        this.wrapper = TooltipTextMenu.createDiv("wrapper");
-        this.wrapper.appendChild(this.tooltip);
-
-        TooltipTextMenu.Toolbar = this.wrapper;
-    }
-
-    private async initTooltip(view: EditorView) {
-        const self = this;
-        this.tooltip = TooltipTextMenu.createDiv("tooltipMenu");
-        this.basicTools = TooltipTextMenu.createDiv("basic-tools");
-
-        const svgIcon = (name: string, title: string = name, dpath: string) => {
-            const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
-            svg.setAttribute("viewBox", "-100 -100 650 650");
-            const path = document.createElementNS('http://www.w3.org/2000/svg', "path");
-            path.setAttributeNS(null, "d", dpath);
-            svg.appendChild(path);
-
-            const span = TooltipTextMenu.createSpan(name + " menuicon");
-            span.title = title;
-            span.appendChild(svg);
-
-            return span;
-        };
-
-        const basicItems = [ // init basicItems in minimized toolbar -- paths to svgs are obtained from fontawesome
-            { mark: schema.marks.strong, dom: svgIcon("strong", "Bold", "M333.49 238a122 122 0 0 0 27-65.21C367.87 96.49 308 32 233.42 32H34a16 16 0 0 0-16 16v48a16 16 0 0 0 16 16h31.87v288H34a16 16 0 0 0-16 16v48a16 16 0 0 0 16 16h209.32c70.8 0 134.14-51.75 141-122.4 4.74-48.45-16.39-92.06-50.83-119.6zM145.66 112h87.76a48 48 0 0 1 0 96h-87.76zm87.76 288h-87.76V288h87.76a56 56 0 0 1 0 112z") },
-            { mark: schema.marks.em, dom: svgIcon("em", "Italic", "M320 48v32a16 16 0 0 1-16 16h-62.76l-80 320H208a16 16 0 0 1 16 16v32a16 16 0 0 1-16 16H16a16 16 0 0 1-16-16v-32a16 16 0 0 1 16-16h62.76l80-320H112a16 16 0 0 1-16-16V48a16 16 0 0 1 16-16h192a16 16 0 0 1 16 16z") },
-            { mark: schema.marks.underline, dom: svgIcon("underline", "Underline", "M32 64h32v160c0 88.22 71.78 160 160 160s160-71.78 160-160V64h32a16 16 0 0 0 16-16V16a16 16 0 0 0-16-16H272a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h32v160a80 80 0 0 1-160 0V64h32a16 16 0 0 0 16-16V16a16 16 0 0 0-16-16H32a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16zm400 384H16a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h416a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16z") },
-        ];
-        const items = [ // init items in full size toolbar
-            { mark: schema.marks.strikethrough, dom: svgIcon("strikethrough", "Strikethrough", "M496 224H293.9l-87.17-26.83A43.55 43.55 0 0 1 219.55 112h66.79A49.89 49.89 0 0 1 331 139.58a16 16 0 0 0 21.46 7.15l42.94-21.47a16 16 0 0 0 7.16-21.46l-.53-1A128 128 0 0 0 287.51 32h-68a123.68 123.68 0 0 0-123 135.64c2 20.89 10.1 39.83 21.78 56.36H16a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h480a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zm-180.24 96A43 43 0 0 1 336 356.45 43.59 43.59 0 0 1 292.45 400h-66.79A49.89 49.89 0 0 1 181 372.42a16 16 0 0 0-21.46-7.15l-42.94 21.47a16 16 0 0 0-7.16 21.46l.53 1A128 128 0 0 0 224.49 480h68a123.68 123.68 0 0 0 123-135.64 114.25 114.25 0 0 0-5.34-24.36z") },
-            { mark: schema.marks.superscript, dom: svgIcon("superscript", "Superscript", "M496 160h-16V16a16 16 0 0 0-16-16h-48a16 16 0 0 0-14.29 8.83l-16 32A16 16 0 0 0 400 64h16v96h-16a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h96a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zM336 64h-67a16 16 0 0 0-13.14 6.87l-79.9 115-79.9-115A16 16 0 0 0 83 64H16A16 16 0 0 0 0 80v48a16 16 0 0 0 16 16h33.48l77.81 112-77.81 112H16a16 16 0 0 0-16 16v48a16 16 0 0 0 16 16h67a16 16 0 0 0 13.14-6.87l79.9-115 79.9 115A16 16 0 0 0 269 448h67a16 16 0 0 0 16-16v-48a16 16 0 0 0-16-16h-33.48l-77.81-112 77.81-112H336a16 16 0 0 0 16-16V80a16 16 0 0 0-16-16z") },
-            { mark: schema.marks.subscript, dom: svgIcon("subscript", "Subscript", "M496 448h-16V304a16 16 0 0 0-16-16h-48a16 16 0 0 0-14.29 8.83l-16 32A16 16 0 0 0 400 352h16v96h-16a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h96a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zM336 64h-67a16 16 0 0 0-13.14 6.87l-79.9 115-79.9-115A16 16 0 0 0 83 64H16A16 16 0 0 0 0 80v48a16 16 0 0 0 16 16h33.48l77.81 112-77.81 112H16a16 16 0 0 0-16 16v48a16 16 0 0 0 16 16h67a16 16 0 0 0 13.14-6.87l79.9-115 79.9 115A16 16 0 0 0 269 448h67a16 16 0 0 0 16-16v-48a16 16 0 0 0-16-16h-33.48l-77.81-112 77.81-112H336a16 16 0 0 0 16-16V80a16 16 0 0 0-16-16z") },
-        ];
-
-        basicItems.map(({ dom, mark }) => this.basicTools ?.appendChild(dom.cloneNode(true)));
-        basicItems.concat(items).forEach(({ dom, mark }) => {
-            this.tooltip.appendChild(dom);
-            this._marksToDoms.set(mark, dom);
-
-            //pointer down handler to activate button effects
-            dom.addEventListener("pointerdown", e => {
-                this.view.focus();
-                if (dom.contains(e.target as Node)) {
-                    e.preventDefault();
-                    e.stopPropagation();
-                    toggleMark(mark)(this.view.state, this.view.dispatch, this.view);
-                    this.updateHighlightStateOfButtons();
-                }
-            });
-        });
-
-        // summarize menu
-        this.highighterDom = this.createHighlightTool().render(this.view).dom;
-        this.highlighterDropdownDom = this.createHighlightDropdown().render(this.view).dom;
-        this.tooltip.appendChild(this.highighterDom);
-        this.tooltip.appendChild(this.highlighterDropdownDom);
-
-        // color menu
-        this.colorDom = this.createColorTool().render(this.view).dom;
-        this.colorDropdownDom = this.createColorDropdown().render(this.view).dom;
-        this.tooltip.appendChild(this.colorDom);
-        this.tooltip.appendChild(this.colorDropdownDom);
-
-        // link menu
-        this.linkDom = this.createLinkTool().render(this.view).dom;
-        this.linkDropdownDom = this.createLinkDropdown("").render(this.view).dom;
-        this.tooltip.appendChild(this.linkDom);
-        this.tooltip.appendChild(this.linkDropdownDom);
-
-        // list of font styles
-        this.fontSizes.push(schema.marks.pFontSize.create({ fontSize: 7 }));
-        this.fontSizes.push(schema.marks.pFontSize.create({ fontSize: 8 }));
-        this.fontSizes.push(schema.marks.pFontSize.create({ fontSize: 9 }));
-        this.fontSizes.push(schema.marks.pFontSize.create({ fontSize: 10 }));
-        this.fontSizes.push(schema.marks.pFontSize.create({ fontSize: 12 }));
-        this.fontSizes.push(schema.marks.pFontSize.create({ fontSize: 14 }));
-        this.fontSizes.push(schema.marks.pFontSize.create({ fontSize: 16 }));
-        this.fontSizes.push(schema.marks.pFontSize.create({ fontSize: 18 }));
-        this.fontSizes.push(schema.marks.pFontSize.create({ fontSize: 20 }));
-        this.fontSizes.push(schema.marks.pFontSize.create({ fontSize: 24 }));
-        this.fontSizes.push(schema.marks.pFontSize.create({ fontSize: 32 }));
-        this.fontSizes.push(schema.marks.pFontSize.create({ fontSize: 48 }));
-        this.fontSizes.push(schema.marks.pFontSize.create({ fontSize: 72 }));
-
-        // font sizes
-        this.fontStyles.push(schema.marks.pFontFamily.create({ family: "Times New Roman" }));
-        this.fontStyles.push(schema.marks.pFontFamily.create({ family: "Arial" }));
-        this.fontStyles.push(schema.marks.pFontFamily.create({ family: "Georgia" }));
-        this.fontStyles.push(schema.marks.pFontFamily.create({ family: "Comic Sans MS" }));
-        this.fontStyles.push(schema.marks.pFontFamily.create({ family: "Tahoma" }));
-        this.fontStyles.push(schema.marks.pFontFamily.create({ family: "Impact" }));
-        this.fontStyles.push(schema.marks.pFontFamily.create({ family: "Crimson Text" }));
-
-
-        // init brush tool
-        this._brushdom = this.createBrushTool().render(this.view).dom;
-        this.tooltip.appendChild(this._brushdom);
-        this._brushDropdownDom = this.createBrushDropdown().render(this.view).dom;
-        this.tooltip.appendChild(this._brushDropdownDom);
-
-        // summarizer tool
-        const summarizer = new MenuItem({
-            title: "Summarize",
-            label: "Summarize",
-            icon: icons.join,
-            css: "fill:white;",
-            class: "menuicon",
-            execEvent: "",
-            run: (state, dispatch) => TooltipTextMenu.insertSummarizer(state, dispatch)
-        });
-        this.tooltip.appendChild(summarizer.render(this.view).dom);
-
-        // list types dropdown
-        const listDropdownTypes = [{ mapStyle: "bullet", label: ":" }, { mapStyle: "decimal", label: "1.1" }, { mapStyle: "multi", label: "A.1" }, { label: "X" }];
-        const listTypes = new Dropdown(listDropdownTypes.map(({ mapStyle, label }) =>
-            new MenuItem({
-                title: "Set Bullet Style",
-                label: label,
-                execEvent: "",
-                class: "dropdown-item",
-                css: "color: black; width: 40px;",
-                enable() { return true; },
-                run() {
-                    const marks = self.view.state.storedMarks || (view.state.selection.$to.parentOffset && view.state.selection.$from.marks());
-                    if (!wrapInList(schema.nodes.ordered_list)(view.state, (tx2: any) => {
-                        const tx3 = updateBullets(tx2, schema, mapStyle);
-                        marks && tx3.ensureMarks([...marks]);
-                        marks && tx3.setStoredMarks([...marks]);
-
-                        view.dispatch(tx2);
-                    })) {
-                        const tx2 = view.state.tr;
-                        const tx3 = updateBullets(tx2, schema, mapStyle);
-                        marks && tx3.ensureMarks([...marks]);
-                        marks && tx3.setStoredMarks([...marks]);
-
-                        view.dispatch(tx3);
-                    }
-                }
-            })), { label: ":", css: "color:black; width: 40px;" });
-        this.tooltip.appendChild(listTypes.render(this.view).dom);
-
-        await this.updateFromDash(view, undefined, undefined);
-
-        const draggerWrapper = TooltipTextMenu.createDiv("dragger-wrapper");
-        const dragger = TooltipTextMenu.createDiv("dragger");
-        dragger.appendChild(TooltipTextMenu.createSpan("dragger-line"));
-        dragger.appendChild(TooltipTextMenu.createSpan("dragger-line"));
-        dragger.appendChild(TooltipTextMenu.createSpan("dragger-line"));
-        draggerWrapper.appendChild(dragger);
-        this.wrapper.appendChild(draggerWrapper);
-        this.setupDragElementInteractions(draggerWrapper);
-    }
-
-    setupDragElementInteractions(elmnt: HTMLElement) {
-        var pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
-        if (elmnt) {
-            // if present, the header is where you move the DIV from:
-            elmnt.onpointerdown = dragPointerDown;
-            elmnt.ondblclick = onClick;
-        }
-        const self = this;
-
-        function dragPointerDown(e: PointerEvent) {
-            e = e || window.event;
-            e.preventDefault();
-            // get the mouse cursor position at startup:
-            pos3 = e.clientX;
-            pos4 = e.clientY;
-            document.onpointerup = closeDragElement;
-            // call a function whenever the cursor moves:
-            document.onpointermove = elementDrag;
-        }
-
-        function onClick(e: MouseEvent) {
-            self._collapsed = !self._collapsed;
-            const children = self.wrapper.childNodes;
-            if (self._collapsed && children.length > 0) {
-                self.wrapper.removeChild(self.tooltip);
-                self.basicTools && self.wrapper.prepend(self.basicTools);
-            }
-            else {
-                self.wrapper.prepend(self.tooltip);
-                self.basicTools && self.wrapper.removeChild(self.basicTools);
-            }
-        }
-
-        function elementDrag(e: PointerEvent) {
-            e = e || window.event;
-            //e.preventDefault();
-            // calculate the new cursor position:
-            pos1 = pos3 - e.clientX;
-            pos2 = pos4 - e.clientY;
-            pos3 = e.clientX;
-            pos4 = e.clientY;
-            // set the element's new position:
-            // elmnt.style.top = (elmnt.offsetTop - pos2) + "px";
-            // elmnt.style.left = (elmnt.offsetLeft - pos1) + "px";
-
-            self.wrapper.style.top = (self.wrapper.offsetTop - pos2) + "px";
-            self.wrapper.style.left = (self.wrapper.offsetLeft - pos1) + "px";
-        }
-
-        function closeDragElement() {
-            // stop moving when mouse button is released:
-            document.onpointerup = null;
-            document.onpointermove = null;
-        }
-    }
-
-    //label of dropdown will change to given label
-    updateFontSizeDropdown(label: string) {
-        //font SIZES
-        const fontSizeBtns: MenuItem[] = [];
-        const self = this;
-        this.fontSizes.forEach(mark =>
-            fontSizeBtns.push(new MenuItem({
-                title: "Set Font Size",
-                label: String(mark.attrs.fontSize),
-                execEvent: "",
-                class: "dropdown-item",
-                css: "color: black; width: 50px;",
-                enable() { return true; },
-                run() {
-                    const size = mark.attrs.fontSize;
-                    if (size) { self.updateFontSizeDropdown(String(size) + " pt"); }
-                    if (self.editorProps) {
-                        const ruleProvider = self.editorProps.ruleProvider;
-                        const heading = NumCast(self.editorProps.Document.heading);
-                        if (ruleProvider && heading) {
-                            ruleProvider["ruleSize_" + heading] = size;
-                        }
-                    }
-                    TooltipTextMenu.setMark(self.view.state.schema.marks.pFontSize.create({ fontSize: size }), self.view.state, self.view.dispatch);
-                }
-            })));
-
-        const newfontSizeDom = (new Dropdown(fontSizeBtns, { label: label, css: "color:black; min-width: 60px;" }) as MenuItem).render(this.view).dom;
-        if (this.fontSizeDom) {
-            this.tooltip.replaceChild(newfontSizeDom, this.fontSizeDom);
-        }
-        else {
-            this.tooltip.appendChild(newfontSizeDom);
-        }
-        this.fontSizeDom = newfontSizeDom;
-    }
-
-    //label of dropdown will change to given label
-    updateFontStyleDropdown(label: string) {
-        //font STYLES
-        const fontBtns: MenuItem[] = [];
-        const self = this;
-        this.fontStyles.forEach(mark =>
-            fontBtns.push(new MenuItem({
-                title: "Set Font Family",
-                label: mark.attrs.family,
-                execEvent: "",
-                class: "dropdown-item",
-                css: "color: black; font-family: " + mark.attrs.family + ", sans-serif; width: 125px;",
-                enable() { return true; },
-                run() {
-                    const fontName = mark.attrs.family;
-                    if (fontName) { self.updateFontStyleDropdown(fontName); }
-                    if (self.editorProps) {
-                        const ruleProvider = self.editorProps.ruleProvider;
-                        const heading = NumCast(self.editorProps.Document.heading);
-                        if (ruleProvider && heading) {
-                            ruleProvider["ruleFont_" + heading] = fontName;
-                        }
-                    }
-                    TooltipTextMenu.setMark(self.view.state.schema.marks.pFontFamily.create({ family: fontName }), self.view.state, self.view.dispatch);
-                }
-            })));
-
-        const newfontStyleDom = (new Dropdown(fontBtns, { label: label, css: "color:black; width: 125px;" }) as MenuItem).render(this.view).dom;
-        if (this.fontStyleDom) {
-            this.tooltip.replaceChild(newfontStyleDom, this.fontStyleDom);
-        }
-        else {
-            this.tooltip.appendChild(newfontStyleDom);
-        }
-        this.fontStyleDom = newfontStyleDom;
-    }
-    async getTextLinkTargetTitle() {
-        const node = this.view.state.selection.$from.nodeAfter;
-        const link = node && node.marks.find(m => m.type.name === "link");
-        if (link) {
-            const href = link.attrs.href;
-            if (href) {
-                if (href.indexOf(Utils.prepend("/doc/")) === 0) {
-                    const linkclicked = href.replace(Utils.prepend("/doc/"), "").split("?")[0];
-                    if (linkclicked) {
-                        const linkDoc = await DocServer.GetRefField(linkclicked);
-                        if (linkDoc instanceof Doc) {
-                            const anchor1 = await Cast(linkDoc.anchor1, Doc);
-                            const anchor2 = await Cast(linkDoc.anchor2, Doc);
-                            const currentDoc = SelectionManager.SelectedDocuments().length && SelectionManager.SelectedDocuments()[0].props.Document;
-                            if (currentDoc && anchor1 && anchor2) {
-                                if (Doc.AreProtosEqual(currentDoc, anchor1)) {
-                                    return StrCast(anchor2.title);
-                                }
-                                if (Doc.AreProtosEqual(currentDoc, anchor2)) {
-                                    return StrCast(anchor1.title);
-                                }
-                            }
-                        }
-                    }
-                } else {
-                    return href;
-                }
-            } else {
-                return link.attrs.title;
-            }
-        }
-    }
-
-    // LINK TOOL
-    createLinkTool(active: boolean = false) {
-        return new MenuItem({
-            title: "Link tool",
-            label: "Link tool",
-            icon: icons.link,
-            css: "fill:white;",
-            class: active ? "menuicon-active" : "menuicon",
-            execEvent: "",
-            run: async (state, dispatch) => { },
-            active: (state) => true
-        });
-    }
-
-    createLinkDropdown(targetTitle: string) {
-        const input = document.createElement("input");
-
-        // menu item for input for hyperlink url 
-        // TODO: integrate search to allow users to search for a doc to link to
-        const linkInfo = new MenuItem({
-            title: "",
-            execEvent: "",
-            class: "button-setting-disabled",
-            css: "",
-            render() {
-                const p = document.createElement("p");
-                p.textContent = "Linked to:";
-
-                input.type = "text";
-                input.placeholder = "Enter URL";
-                if (targetTitle) input.value = targetTitle;
-                input.onclick = (e: MouseEvent) => {
-                    input.select();
-                    input.focus();
-                };
-
-                const div = document.createElement("div");
-                div.appendChild(p);
-                div.appendChild(input);
-                return div;
-            },
-            enable() { return false; },
-            run(p1, p2, p3, event) { event.stopPropagation(); }
-        });
-
-        // menu item to update/apply the hyperlink to the selected text
-        const linkApply = new MenuItem({
-            title: "",
-            execEvent: "",
-            class: "",
-            css: "",
-            render() {
-                const button = document.createElement("button");
-                button.className = "link-url-button";
-                button.textContent = "Apply hyperlink";
-                return button;
-            },
-            enable() { return false; },
-            run: async (state, dispatch, view, event) => {
-                event.stopPropagation();
-                let node = this.view.state.selection.$from.nodeAfter;
-                let link = this.view.state.schema.mark(this.view.state.schema.marks.link, { href: input.value, location: "onRight" });
-                this.view.dispatch(this.view.state.tr.removeMark(this.view.state.selection.from, this.view.state.selection.to, this.view.state.schema.marks.link));
-                this.view.dispatch(this.view.state.tr.addMark(this.view.state.selection.from, this.view.state.selection.to, link));
-                node = this.view.state.selection.$from.nodeAfter;
-                link = node && node.marks.find(m => m.type.name === "link");
-
-                // update link menu
-                const linkDom = self.createLinkTool(true).render(self.view).dom;
-                const linkDropdownDom = self.createLinkDropdown(await self.getTextLinkTargetTitle()).render(self.view).dom;
-                self.linkDom && self.tooltip.replaceChild(linkDom, self.linkDom);
-                self.linkDropdownDom && self.tooltip.replaceChild(linkDropdownDom, self.linkDropdownDom);
-                self.linkDom = linkDom;
-                self.linkDropdownDom = linkDropdownDom;
-            }
-        });
-
-        // menu item to remove the link
-        // TODO: allow this to be undoable
-        const self = this;
-        const deleteLink = new MenuItem({
-            title: "Delete link",
-            execEvent: "",
-            class: "separated-button",
-            css: "",
-            render() {
-                const button = document.createElement("button");
-                button.textContent = "Remove link";
-
-                const wrapper = document.createElement("div");
-                wrapper.appendChild(button);
-                return wrapper;
-            },
-            enable() { return true; },
-            async run() {
-                // delete the link
-                const node = self.view.state.selection.$from.nodeAfter;
-                const link = node && node.marks.find(m => m.type === self.view.state.schema.marks.link);
-                const href = link!.attrs.href;
-                if (href ?.indexOf(Utils.prepend("/doc/")) === 0) {
-                    const linkclicked = href.replace(Utils.prepend("/doc/"), "").split("?")[0];
-                    linkclicked && DocServer.GetRefField(linkclicked).then(async linkDoc => {
-                        if (linkDoc instanceof Doc) {
-                            LinkManager.Instance.deleteLink(linkDoc);
-                            self.view.dispatch(self.view.state.tr.removeMark(self.view.state.selection.from, self.view.state.selection.to, self.view.state.schema.marks.link));
-                        }
-                    });
-                }
-                // update link menu
-                const linkDom = self.createLinkTool(false).render(self.view).dom;
-                const linkDropdownDom = self.createLinkDropdown("").render(self.view).dom;
-                self.linkDom && self.tooltip.replaceChild(linkDom, self.linkDom);
-                self.linkDropdownDom && self.tooltip.replaceChild(linkDropdownDom, self.linkDropdownDom);
-                self.linkDom = linkDom;
-                self.linkDropdownDom = linkDropdownDom;
-            }
-        });
-
-        return new Dropdown(targetTitle ? [linkInfo, linkApply, deleteLink] : [linkInfo, linkApply], { class: "buttonSettings-dropdown" }) as MenuItem;
-    }
-
-    public MakeLinkToSelection = (linkDocId: string, title: string, location: string, targetDocId: string): string => {
-        const link = this.view.state.schema.marks.link.create({ href: Utils.prepend("/doc/" + linkDocId), title: title, location: location, targetId: targetDocId });
-        this.view.dispatch(this.view.state.tr.removeMark(this.view.state.selection.from, this.view.state.selection.to, this.view.state.schema.marks.link).
-            addMark(this.view.state.selection.from, this.view.state.selection.to, link));
-        return this.view.state.selection.$from.nodeAfter ?.text || "";
-    }
-
-    // SUMMARIZER TOOL
-    static insertSummarizer(state: EditorState<any>, dispatch: any) {
-        if (!state.selection.empty) {
-            const mark = state.schema.marks.summarize.create();
-            const tr = state.tr.addMark(state.selection.from, state.selection.to, mark);
-            const content = tr.selection.content();
-            const newNode = state.schema.nodes.summary.create({ visibility: false, text: content, textslice: content.toJSON() });
-            dispatch ?.(tr.replaceSelectionWith(newNode).removeMark(tr.selection.from - 1, tr.selection.from, mark));
-        }
-    }
-
-    // HIGHLIGHTER TOOL
-    createHighlightTool() {
-        return new MenuItem({
-            title: "Highlight",
-            css: "fill:white;",
-            class: "menuicon",
-            execEvent: "",
-            render() {
-                const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
-                svg.setAttribute("viewBox", "-100 -100 650 650");
-                const path = document.createElementNS('http://www.w3.org/2000/svg', "path");
-                path.setAttributeNS(null, "d", "M0 479.98L99.92 512l35.45-35.45-67.04-67.04L0 479.98zm124.61-240.01a36.592 36.592 0 0 0-10.79 38.1l13.05 42.83-50.93 50.94 96.23 96.23 50.86-50.86 42.74 13.08c13.73 4.2 28.65-.01 38.15-10.78l35.55-41.64-173.34-173.34-41.52 35.44zm403.31-160.7l-63.2-63.2c-20.49-20.49-53.38-21.52-75.12-2.35L190.55 183.68l169.77 169.78L530.27 154.4c19.18-21.74 18.15-54.63-2.35-75.13z");
-                svg.appendChild(path);
-
-                const color = TooltipTextMenu.createDiv("buttonColor");
-                color.style.backgroundColor = TooltipTextMenuManager.Instance.highlighter.toString();
-
-                const wrapper = TooltipTextMenu.createDiv("colorPicker");
-                wrapper.appendChild(svg);
-                wrapper.appendChild(color);
-                return wrapper;
-            },
-            run: (state, dispatch) => TooltipTextMenu.insertHighlight(TooltipTextMenuManager.Instance.highlighter, state, dispatch)
-        });
-    }
-
-    static insertHighlight(color: String, state: EditorState<any>, dispatch: any) {
-        if (!state.selection.empty) {
-            toggleMark(state.schema.marks.marker, { highlight: color })(state, dispatch);
-        }
-    }
-
-    createHighlightDropdown() {
-        // menu item for color picker
-        const self = this;
-        const colors = new MenuItem({
-            title: "",
-            execEvent: "",
-            class: "button-setting-disabled",
-            css: "",
-            render() {
-                const p = document.createElement("p");
-                p.textContent = "Change highlight:";
-
-                const colorsWrapper = TooltipTextMenu.createDiv("colorPicker-wrapper");
-
-                const colors = [
-                    PastelSchemaPalette.get("pink2"),
-                    PastelSchemaPalette.get("purple4"),
-                    PastelSchemaPalette.get("bluegreen1"),
-                    PastelSchemaPalette.get("yellow4"),
-                    PastelSchemaPalette.get("red2"),
-                    PastelSchemaPalette.get("bluegreen7"),
-                    PastelSchemaPalette.get("bluegreen5"),
-                    PastelSchemaPalette.get("orange1"),
-                    "white",
-                    "transparent"
-                ];
-
-                colors.forEach(color => {
-                    const button = document.createElement("button");
-                    button.className = color === TooltipTextMenuManager.Instance.highlighter ? "colorPicker active" : "colorPicker";
-                    if (color) {
-                        button.style.backgroundColor = color;
-                        button.textContent = color === "transparent" ? "X" : "";
-                        button.onclick = e => {
-                            TooltipTextMenuManager.Instance.highlighter = color;
-
-                            TooltipTextMenu.insertHighlight(TooltipTextMenuManager.Instance.highlighter, self.view.state, self.view.dispatch);
-
-                            // update color menu
-                            const highlightDom = self.createHighlightTool().render(self.view).dom;
-                            const highlightDropdownDom = self.createHighlightDropdown().render(self.view).dom;
-                            self.highighterDom && self.tooltip.replaceChild(highlightDom, self.highighterDom);
-                            self.highlighterDropdownDom && self.tooltip.replaceChild(highlightDropdownDom, self.highlighterDropdownDom);
-                            self.highighterDom = highlightDom;
-                            self.highlighterDropdownDom = highlightDropdownDom;
-                        };
-                    }
-                    colorsWrapper.appendChild(button);
-                });
-
-                const div = document.createElement("div");
-                div.appendChild(p);
-                div.appendChild(colorsWrapper);
-                return div;
-            },
-            enable() { return false; },
-            run(p1, p2, p3, event) {
-                event.stopPropagation();
-            }
-        });
-
-        return new Dropdown([colors], { class: "buttonSettings-dropdown" }) as MenuItem;
-    }
-
-    // COLOR TOOL
-    createColorTool() {
-        return new MenuItem({
-            title: "Color",
-            css: "fill:white;",
-            class: "menuicon",
-            execEvent: "",
-            render() {
-                const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
-                svg.setAttribute("viewBox", "-100 -100 650 650");
-                const path = document.createElementNS('http://www.w3.org/2000/svg', "path");
-                path.setAttributeNS(null, "d", "M204.3 5C104.9 24.4 24.8 104.3 5.2 203.4c-37 187 131.7 326.4 258.8 306.7 41.2-6.4 61.4-54.6 42.5-91.7-23.1-45.4 9.9-98.4 60.9-98.4h79.7c35.8 0 64.8-29.6 64.9-65.3C511.5 97.1 368.1-26.9 204.3 5zM96 320c-17.7 0-32-14.3-32-32s14.3-32 32-32 32 14.3 32 32-14.3 32-32 32zm32-128c-17.7 0-32-14.3-32-32s14.3-32 32-32 32 14.3 32 32-14.3 32-32 32zm128-64c-17.7 0-32-14.3-32-32s14.3-32 32-32 32 14.3 32 32-14.3 32-32 32zm128 64c-17.7 0-32-14.3-32-32s14.3-32 32-32 32 14.3 32 32-14.3 32-32 32z");
-                svg.appendChild(path);
-
-                const color = TooltipTextMenu.createDiv("buttonColor");
-                color.style.backgroundColor = TooltipTextMenuManager.Instance.color.toString();
-
-                const wrapper = TooltipTextMenu.createDiv("colorPicker");
-                wrapper.appendChild(svg);
-                wrapper.appendChild(color);
-                return wrapper;
-            },
-            run: (state, dispatch) => TooltipTextMenu.insertColor(TooltipTextMenuManager.Instance.color, state, dispatch)
-        });
-    }
-
-    static insertColor(color: String, state: EditorState<any>, dispatch: any) {
-        const colorMark = state.schema.mark(state.schema.marks.pFontColor, { color: color });
-        if (state.selection.empty) {
-            dispatch(state.tr.addStoredMark(colorMark));
-        } else {
-            this.setMark(colorMark, state, dispatch);
-        }
-    }
-
-    createColorDropdown() {
-        // menu item for color picker
-        const self = this;
-        const colors = new MenuItem({
-            title: "",
-            execEvent: "",
-            class: "button-setting-disabled",
-            css: "",
-            render() {
-                const p = document.createElement("p");
-                p.textContent = "Change color:";
-
-                const colorsWrapper = TooltipTextMenu.createDiv("colorPicker-wrapper");
-
-                const colors = [
-                    DarkPastelSchemaPalette.get("pink2"),
-                    DarkPastelSchemaPalette.get("purple4"),
-                    DarkPastelSchemaPalette.get("bluegreen1"),
-                    DarkPastelSchemaPalette.get("yellow4"),
-                    DarkPastelSchemaPalette.get("red2"),
-                    DarkPastelSchemaPalette.get("bluegreen7"),
-                    DarkPastelSchemaPalette.get("bluegreen5"),
-                    DarkPastelSchemaPalette.get("orange1"),
-                    "#757472",
-                    "#000"
-                ];
-
-                colors.forEach(color => {
-                    const button = document.createElement("button");
-                    button.className = color === TooltipTextMenuManager.Instance.color ? "colorPicker active" : "colorPicker";
-                    if (color) {
-                        button.style.backgroundColor = color;
-                        button.onclick = e => {
-                            TooltipTextMenuManager.Instance.color = color;
-
-                            TooltipTextMenu.insertColor(TooltipTextMenuManager.Instance.color, self.view.state, self.view.dispatch);
-
-                            // update color menu
-                            const colorDom = self.createColorTool().render(self.view).dom;
-                            const colorDropdownDom = self.createColorDropdown().render(self.view).dom;
-                            self.colorDom && self.tooltip.replaceChild(colorDom, self.colorDom);
-                            self.colorDropdownDom && self.tooltip.replaceChild(colorDropdownDom, self.colorDropdownDom);
-                            self.colorDom = colorDom;
-                            self.colorDropdownDom = colorDropdownDom;
-                        };
-                    }
-                    colorsWrapper.appendChild(button);
-                });
-
-                const div = document.createElement("div");
-                div.appendChild(p);
-                div.appendChild(colorsWrapper);
-                return div;
-            },
-            enable() { return false; },
-            run(p1, p2, p3, event) { event.stopPropagation(); }
-        });
-
-        return new Dropdown([colors], { class: "buttonSettings-dropdown" }) as MenuItem;
-    }
-
-    // BRUSH TOOL
-    createBrushTool(active: boolean = false) {
-        const icon = {
-            height: 32, width: 32,
-            path: "M30.828 1.172c-1.562-1.562-4.095-1.562-5.657 0l-5.379 5.379-3.793-3.793-4.243 4.243 3.326 3.326-14.754 14.754c-0.252 0.252-0.358 0.592-0.322 0.921h-0.008v5c0 0.552 0.448 1 1 1h5c0 0 0.083 0 0.125 0 0.288 0 0.576-0.11 0.795-0.329l14.754-14.754 3.326 3.326 4.243-4.243-3.793-3.793 5.379-5.379c1.562-1.562 1.562-4.095 0-5.657zM5.409 30h-3.409v-3.409l14.674-14.674 3.409 3.409-14.674 14.674z"
-        };
-        const self = this;
-        return new MenuItem({
-            title: "Brush tool",
-            label: "Brush tool",
-            icon: icon,
-            css: "fill:white;",
-            class: active ? "menuicon-active" : "menuicon",
-            execEvent: "",
-            run: (state, dispatch) => {
-                this.brush_function(state, dispatch);
-
-                // update dropdown with marks
-                const newBrushDropdowndom = self.createBrushDropdown().render(self.view).dom;
-                self._brushDropdownDom && self.tooltip.replaceChild(newBrushDropdowndom, self._brushDropdownDom);
-                self._brushDropdownDom = newBrushDropdowndom;
-            },
-            active: (state) => true
-        });
-    }
-
-    brush_function(state: EditorState<any>, dispatch: any) {
-        if (TooltipTextMenuManager.Instance._brushIsEmpty) {
-            // get marks in the selection
-            const selected_marks = new Set<Mark>();
-            const { from, to } = state.selection as TextSelection;
-            state.doc.nodesBetween(from, to, (node) => node.marks ?.forEach(m => selected_marks.add(m)));
-
-            if (this._brushdom && selected_marks.size >= 0) {
-                TooltipTextMenuManager.Instance._brushMarks = selected_marks;
-                const newbrush = this.createBrushTool(true).render(this.view).dom;
-                this.tooltip.replaceChild(newbrush, this._brushdom);
-                this._brushdom = newbrush;
-                TooltipTextMenuManager.Instance._brushIsEmpty = !TooltipTextMenuManager.Instance._brushIsEmpty;
-            }
-        }
-        else {
-            const { from, to, $from } = this.view.state.selection;
-            if (this._brushdom) {
-                if (!this.view.state.selection.empty && $from && $from.nodeAfter) {
-                    if (TooltipTextMenuManager.Instance._brushMarks && to - from > 0) {
-                        this.view.dispatch(this.view.state.tr.removeMark(from, to));
-                        Array.from(TooltipTextMenuManager.Instance._brushMarks).filter(m => m.type !== schema.marks.user_mark).forEach((mark: Mark) => {
-                            TooltipTextMenu.setMark(mark, this.view.state, this.view.dispatch);
-                        });
-                    }
-                }
-                else {
-                    const newbrush = this.createBrushTool(false).render(this.view).dom;
-                    this.tooltip.replaceChild(newbrush, this._brushdom);
-                    this._brushdom = newbrush;
-                    TooltipTextMenuManager.Instance._brushIsEmpty = !TooltipTextMenuManager.Instance._brushIsEmpty;
-                }
-            }
-        }
-    }
-
-    createBrushDropdown(active: boolean = false) {
-        let label = "Stored marks: ";
-        if (TooltipTextMenuManager.Instance._brushMarks && TooltipTextMenuManager.Instance._brushMarks.size > 0) {
-            TooltipTextMenuManager.Instance._brushMarks.forEach((mark: Mark) => label += mark.type.name + ", ");
-            label = label.substring(0, label.length - 2);
-        } else {
-            label = "No marks are currently stored";
-        }
-
-        const brushInfo = new MenuItem({
-            title: "",
-            label: label,
-            execEvent: "",
-            class: "button-setting-disabled",
-            css: "",
-            enable() { return false; },
-            run(p1, p2, p3, event) { event.stopPropagation(); }
-        });
-
-        const self = this;
-        const input = document.createElement("input");
-        const clearBrush = new MenuItem({
-            title: "Clear brush",
-            execEvent: "",
-            class: "separated-button",
-            css: "",
-            render() {
-                const button = document.createElement("button");
-                button.textContent = "Clear brush";
-
-                input.textContent = "editme";
-                input.style.width = "75px";
-                input.style.height = "30px";
-                input.style.background = "white";
-                input.setAttribute("contenteditable", "true");
-                input.style.whiteSpace = "nowrap";
-                input.type = "text";
-                input.placeholder = "Enter URL";
-                input.onpointerdown = (e: PointerEvent) => {
-                    e.stopPropagation();
-                    e.preventDefault();
-                };
-                input.onclick = (e: MouseEvent) => {
-                    input.select();
-                    input.focus();
-                };
-                input.onkeypress = (e: KeyboardEvent) => {
-                    if (e.key === "Enter") {
-                        TooltipTextMenuManager.Instance._brushMarks && TooltipTextMenuManager.Instance._brushMap.set(input.value, TooltipTextMenuManager.Instance._brushMarks);
-                        input.style.background = "lightGray";
-                    }
-                };
-
-                const wrapper = document.createElement("div");
-                wrapper.appendChild(input);
-                wrapper.appendChild(button);
-                return wrapper;
-            },
-            enable() { return true; },
-            run() {
-                TooltipTextMenuManager.Instance._brushIsEmpty = true;
-                TooltipTextMenuManager.Instance._brushMarks = new Set();
-
-                // update brush tool
-                // TODO: this probably isn't very clean
-                const newBrushdom = self.createBrushTool().render(self.view).dom;
-                self._brushdom && self.tooltip.replaceChild(newBrushdom, self._brushdom);
-                self._brushdom = newBrushdom;
-                const newBrushDropdowndom = self.createBrushDropdown().render(self.view).dom;
-                self._brushDropdownDom && self.tooltip.replaceChild(newBrushDropdowndom, self._brushDropdownDom);
-                self._brushDropdownDom = newBrushDropdowndom;
-            }
-        });
-
-        const hasMarks = TooltipTextMenuManager.Instance._brushMarks && TooltipTextMenuManager.Instance._brushMarks.size > 0;
-        return new Dropdown(hasMarks ? [brushInfo, clearBrush] : [brushInfo], { class: "buttonSettings-dropdown" }) as MenuItem;
-    }
-
-    static setMark = (mark: Mark, state: EditorState<any>, dispatch: any) => {
-        if (mark) {
-            const node = (state.selection as NodeSelection).node;
-            if (node ?.type === schema.nodes.ordered_list) {
-                let attrs = node.attrs;
-                if (mark.type === schema.marks.pFontFamily) attrs = { ...attrs, setFontFamily: mark.attrs.family };
-                if (mark.type === schema.marks.pFontSize) attrs = { ...attrs, setFontSize: mark.attrs.fontSize };
-                if (mark.type === schema.marks.pFontColor) attrs = { ...attrs, setFontColor: mark.attrs.color };
-                const tr = updateBullets(state.tr.setNodeMarkup(state.selection.from, node.type, attrs), state.schema);
-                dispatch(tr.setSelection(new NodeSelection(tr.doc.resolve(state.selection.from))));
-            } else {
-                toggleMark(mark.type, mark.attrs)(state, (tx: any) => {
-                    const { from, $from, to, empty } = tx.selection;
-                    if (!tx.doc.rangeHasMark(from, to, mark.type)) {
-                        toggleMark(mark.type, mark.attrs)({ tr: tx, doc: tx.doc, selection: tx.selection, storedMarks: tx.storedMarks }, dispatch);
-                    } else dispatch(tx);
-                });
-            }
-        }
-    }
-
-    // called by Prosemirror
-    update(view: EditorView, lastState: EditorState | undefined) { this.updateFromDash(view, lastState, this.editorProps); }
-    //updates the tooltip menu when the selection changes
-    public async updateFromDash(view: EditorView, lastState: EditorState | undefined, props: any) {
-        if (!view) {
-            console.log("no editor?  why?");
-            return;
-        }
-        this.view = view;
-        DocumentDecorations.Instance.showTextBar();
-        props && (this.editorProps = props);
-
-        // Don't do anything if the document/selection didn't change
-        if (!lastState || !lastState.doc.eq(view.state.doc) || !lastState.selection.eq(view.state.selection)) {
-
-            // UPDATE LINK DROPDOWN
-            const linkTarget = await this.getTextLinkTargetTitle();
-            const linkDom = this.createLinkTool(linkTarget ? true : false).render(this.view).dom;
-            const linkDropdownDom = this.createLinkDropdown(linkTarget).render(this.view).dom;
-            this.linkDom && this.tooltip.replaceChild(linkDom, this.linkDom);
-            this.linkDropdownDom && this.tooltip.replaceChild(linkDropdownDom, this.linkDropdownDom);
-            this.linkDom = linkDom;
-            this.linkDropdownDom = linkDropdownDom;
-
-            //UPDATE FONT STYLE DROPDOWN
-            const activeStyles = this.activeFontFamilyOnSelection();
-            this.updateFontStyleDropdown(activeStyles.length === 1 ? activeStyles[0] : activeStyles.length ? "various" : "default");
-
-            //UPDATE FONT SIZE DROPDOWN
-            const activeSizes = this.activeFontSizeOnSelection();
-            this.updateFontSizeDropdown(activeSizes.length === 1 ? String(activeSizes[0]) + " pt" : activeSizes.length ? "various" : "default");
-
-            //UPDATE ALL OTHER BUTTONS
-            this.updateHighlightStateOfButtons();
-        }
-    }
-
-    updateHighlightStateOfButtons() {
-        Array.from(this._marksToDoms.values()).forEach(val => val.style.fill = "white");
-        this.activeMarksOnSelection().filter(mark => this._marksToDoms.has(mark)).forEach(mark =>
-            this._marksToDoms.get(mark)!.style.fill = "greenyellow");
-
-        // keeps brush tool highlighted if active when switching between textboxes
-        if (!TooltipTextMenuManager.Instance._brushIsEmpty && this._brushdom) {
-            const newbrush = this.createBrushTool(true).render(this.view).dom;
-            this.tooltip.replaceChild(newbrush, this._brushdom);
-            this._brushdom = newbrush;
-        }
-    }
-
-    //finds fontSize at start of selection
-    activeFontSizeOnSelection() {
-        //current selection
-        const state = this.view.state;
-        const activeSizes: number[] = [];
-        const pos = this.view.state.selection.$from;
-        const ref_node: ProsNode = this.reference_node(pos);
-        if (ref_node && ref_node !== this.view.state.doc && ref_node.isText) {
-            ref_node.marks.forEach(m => m.type === state.schema.marks.pFontSize && activeSizes.push(m.attrs.fontSize));
-        }
-        return activeSizes;
-    }
-    //finds fontSize at start of selection
-    activeFontFamilyOnSelection() {
-        //current selection
-        const state = this.view.state;
-        const activeFamilies: string[] = [];
-        const pos = this.view.state.selection.$from;
-        const ref_node: ProsNode = this.reference_node(pos);
-        if (ref_node && ref_node !== this.view.state.doc && ref_node.isText) {
-            ref_node.marks.forEach(m => m.type === state.schema.marks.pFontFamily && activeFamilies.push(m.attrs.family));
-        }
-        return activeFamilies;
-    }
-    //finds all active marks on selection in given group
-    activeMarksOnSelection() {
-        const markGroup = Array.from(this._marksToDoms.keys());
-        if (this.view.state.storedMarks) return this.view.state.storedMarks.map(mark => mark.type);
-        //current selection
-        const { empty, ranges, $to } = this.view.state.selection as TextSelection;
-        const state = this.view.state;
-        let activeMarks: MarkType[] = [];
-        if (!empty) {
-            activeMarks = markGroup.filter(mark => {
-                const has = false;
-                for (let i = 0; !has && i < ranges.length; i++) {
-                    return state.doc.rangeHasMark(ranges[i].$from.pos, ranges[i].$to.pos, mark);
-                }
-                return false;
-            });
-        }
-        else {
-            const pos = this.view.state.selection.$from;
-            const ref_node: ProsNode = this.reference_node(pos);
-            if (ref_node !== null && ref_node !== this.view.state.doc) {
-                if (ref_node.isText) {
-                }
-                else {
-                    return [];
-                }
-                activeMarks = markGroup.filter(mark_type => {
-                    if (mark_type === state.schema.marks.pFontSize) {
-                        return ref_node.marks.some(m => m.type.name === state.schema.marks.pFontSize.name);
-                    }
-                    const mark = state.schema.mark(mark_type);
-                    return ref_node.marks.includes(mark);
-                });
-            }
-        }
-        return activeMarks;
-    }
-
-    reference_node(pos: ResolvedPos<any>): ProsNode {
-        let ref_node: ProsNode = this.view.state.doc;
-        if (pos.nodeBefore !== null && pos.nodeBefore !== undefined) {
-            ref_node = pos.nodeBefore;
-        }
-        else if (pos.nodeAfter !== null && pos.nodeAfter !== undefined) {
-            ref_node = pos.nodeAfter;
-        }
-        else if (pos.pos > 0) {
-            let skip = false;
-            for (let i: number = pos.pos - 1; i > 0; i--) {
-                this.view.state.doc.nodesBetween(i, pos.pos, (node: ProsNode) => {
-                    if (node.isLeaf && !skip) {
-                        ref_node = node;
-                        skip = true;
-                    }
-
-                });
-            }
-        }
-        if (!ref_node.isLeaf && ref_node.childCount > 0) {
-            ref_node = ref_node.child(0);
-        }
-        return ref_node;
-    }
-
-    destroy() {
-        // this.wrapper.remove();
-    }
-}
-
-
-export class TooltipTextMenuManager {
-    private static _instance: TooltipTextMenuManager;
-    private _isPinned: boolean = false;
-
-    public pinnedX: number = 0;
-    public pinnedY: number = 0;
-    public unpinnedX: number = 0;
-    public unpinnedY: number = 0;
-
-    public _brushMarks: Set<Mark> | undefined;
-    public _brushMap: Map<string, Set<Mark>> = new Map();
-    public _brushIsEmpty: boolean = true;
-
-    public color: String = "#000";
-    public highlighter: String = "transparent";
-
-    public activeMenu: TooltipTextMenu | undefined;
-
-    static get Instance() {
-        if (!TooltipTextMenuManager._instance) {
-            TooltipTextMenuManager._instance = new TooltipTextMenuManager();
-        }
-        return TooltipTextMenuManager._instance;
-    }
-
-    public get isPinned() { return this._isPinned; }
-
-    public toggleIsPinned() { this._isPinned = !this._isPinned; }
-}
diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx
index 202bfe400..4441356dc 100644
--- a/src/client/views/DocumentButtonBar.tsx
+++ b/src/client/views/DocumentButtonBar.tsx
@@ -20,6 +20,7 @@ import React = require("react");
 import { DocumentView } from './nodes/DocumentView';
 import { ParentDocSelector } from './collections/ParentDocumentSelector';
 import { CollectionDockingView } from './collections/CollectionDockingView';
+import RichTextMenu from '../util/RichTextMenu';
 import { Id } from '../../new_fields/FieldSymbols';
 const higflyout = require("@hig/flyout");
 export const { anchorPoints } = higflyout;
@@ -112,14 +113,15 @@ export class DocumentButtonBar extends React.Component<{ views: (DocumentView |
             const linkDrag = UndoManager.StartBatch("Drag Link");
             this.view0 && DragManager.StartLinkDrag(this._linkButton.current, this.view0.props.Document, e.pageX, e.pageY, {
                 dragComplete: dropEv => {
-                    const linkDoc = dropEv.linkDragData?.linkDocument; // equivalent to !dropEve.aborted since linkDocument is only assigned on a completed drop
-                    if (this.view0 && linkDoc && FormattedTextBox.ToolTipTextMenu) {
+                    const linkDoc = dropEv.linkDragData?.linkDocument as Doc; // equivalent to !dropEve.aborted since linkDocument is only assigned on a completed drop
+                    if (this.view0 && linkDoc) {
                         const proto = Doc.GetProto(linkDoc);
                         proto.sourceContext = this.view0.props.ContainingCollectionDoc;
 
                         const anchor2Title = linkDoc.anchor2 instanceof Doc ? StrCast(linkDoc.anchor2.title) : "-untitled-";
+                        const anchor2Id = linkDoc.anchor2 instanceof Doc ? linkDoc.anchor2[Id] : "";
+                        const text = RichTextMenu.Instance.MakeLinkToSelection(linkDoc[Id], anchor2Title, e.ctrlKey ? "onRight" : "inTab", anchor2Id);
                         if (linkDoc.anchor2 instanceof Doc) {
-                            const text = FormattedTextBox.ToolTipTextMenu.MakeLinkToSelection(linkDoc[Id], anchor2Title, e.ctrlKey ? "onRight" : "inTab", linkDoc.anchor2[Id]);
                             proto.title = text === "" ? proto.title : text + " to " + linkDoc.anchor2.title; // TODO open to more descriptive descriptions of following in text link
                         }
                     }
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 799b3695c..32fea15fb 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -14,7 +14,6 @@ import { Docs, DocUtils } from "../documents/Documents";
 import { DocumentManager } from "../util/DocumentManager";
 import { DragManager } from "../util/DragManager";
 import { SelectionManager } from "../util/SelectionManager";
-import { TooltipTextMenu } from '../util/TooltipTextMenu';
 import { undoBatch, UndoManager } from "../util/UndoManager";
 import { MINIMIZED_ICON_SIZE } from "../views/globalCssVariables.scss";
 import { CollectionView } from "./collections/CollectionView";
@@ -26,8 +25,6 @@ import { IconBox } from "./nodes/IconBox";
 import React = require("react");
 import { DocumentType } from '../documents/DocumentTypes';
 import { ScriptField } from '../../new_fields/ScriptField';
-import { render } from 'react-dom';
-import RichTextMenu from '../util/RichTextMenu';
 const higflyout = require("@hig/flyout");
 export const { anchorPoints } = higflyout;
 export const Flyout = higflyout.default;
@@ -546,11 +543,6 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
             this.TextBar = ele;
         }
     }
-    public showTextBar = () => {
-        if (this.TextBar && TooltipTextMenu.Toolbar && Array.from(this.TextBar.childNodes).indexOf(TooltipTextMenu.Toolbar) === -1) {
-            this.TextBar.appendChild(TooltipTextMenu.Toolbar);
-        }
-    }
     render() {
         const bounds = this.Bounds;
         const seldoc = SelectionManager.SelectedDocuments().length ? SelectionManager.SelectedDocuments()[0] : undefined;
diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx
index 867be287f..b9f601a9a 100644
--- a/src/client/views/nodes/DocumentContentsView.tsx
+++ b/src/client/views/nodes/DocumentContentsView.tsx
@@ -61,7 +61,7 @@ export class DocumentContentsView extends React.Component<DocumentViewProps & {
     @computed get layout(): string {
         TraceMobx();
         if (!this.layoutDoc) return "<p>awaiting layout</p>";
-        const layout = Cast(this.layoutDoc[StrCast(this.layoutDoc.layoutKey, "layout")], "string");
+        const layout = Cast(this.layoutDoc[StrCast(this.layoutDoc.layoutKey, this.layoutDoc === this.props.Document ? this.props.layoutKey : "layout")], "string");
         if (layout === undefined) {
             return this.props.Document.data ?
                 "<FieldView {...props} fieldKey='data' />" :
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index 60842bcb0..1cd5cdcea 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -29,8 +29,6 @@ import buildKeymap from "../../util/ProsemirrorExampleTransfer";
 import { inpRules } from "../../util/RichTextRules";
 import { DashDocCommentView, FootnoteView, ImageResizeView, DashDocView, OrderedListView, schema, SummaryView } from "../../util/RichTextSchema";
 import { SelectionManager } from "../../util/SelectionManager";
-import { TooltipLinkingMenu } from "../../util/TooltipLinkingMenu";
-import { TooltipTextMenu } from "../../util/TooltipTextMenu";
 import { undoBatch, UndoManager } from "../../util/UndoManager";
 import { DocAnnotatableComponent } from "../DocComponent";
 import { DocumentButtonBar } from '../DocumentButtonBar';
@@ -77,7 +75,6 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps &
     public static LayoutString(fieldStr: string) { return FieldView.LayoutString(FormattedTextBox, fieldStr); }
     public static blankState = () => EditorState.create(FormattedTextBox.Instance.config);
     public static Instance: FormattedTextBox;
-    public static ToolTipTextMenu: TooltipTextMenu | undefined = undefined;
     public ProseRef?: HTMLDivElement;
     private _ref: React.RefObject<HTMLDivElement> = React.createRef();
     private _scrollRef: React.RefObject<HTMLDivElement> = React.createRef();
@@ -127,10 +124,6 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps &
         return "";
     }
 
-    public static getToolTip(ev: EditorView) {
-        return this.ToolTipTextMenu ? this.ToolTipTextMenu : this.ToolTipTextMenu = new TooltipTextMenu(ev);
-    }
-
     @undoBatch
     public setFontColor(color: string) {
         const view = this._editorView!;
@@ -485,11 +478,10 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps &
             schema,
             plugins: [
                 inputRules(inpRules),
-                this.tooltipTextMenuPlugin(),
+                this.richTextMenuPlugin(),
                 history(),
                 keymap(this._keymap),
                 keymap(baseKeymap),
-                // this.tooltipLinkingMenuPlugin(),
                 new Plugin({
                     props: {
                         attributes: { class: "ProseMirror-example-setup-style" }
@@ -1038,25 +1030,16 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps &
         }
     }
 
-    tooltipTextMenuPlugin() {
+    richTextMenuPlugin() {
         const self = FormattedTextBox;
         return new Plugin({
             view(newView) {
-                // return self.ToolTipTextMenu = FormattedTextBox.getToolTip(newView);
                 RichTextMenu.Instance.changeView(newView);
                 return RichTextMenu.Instance;
             }
         });
     }
 
-    tooltipLinkingMenuPlugin() {
-        const myprops = this.props;
-        return new Plugin({
-            view(_editorView) {
-                return new TooltipLinkingMenu(_editorView, myprops);
-            }
-        });
-    }
     onBlur = (e: any) => {
         //DictationManager.Controls.stop(false);
         if (this._undoTyping) {
@@ -1138,7 +1121,6 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps &
         if (this.props.isSelected()) {
             // TODO: ftong --> update from dash in richtextmenu
             RichTextMenu.Instance.updateFromDash(this._editorView!, undefined, this.props);
-            // FormattedTextBox.ToolTipTextMenu!.updateFromDash(this._editorView!, undefined, this.props);
         } else if (FormattedTextBoxComment.textBox === this) {
             FormattedTextBoxComment.Hide();
         }
diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts
index 5375c8ac8..e502a06b8 100644
--- a/src/server/authentication/models/current_user_utils.ts
+++ b/src/server/authentication/models/current_user_utils.ts
@@ -151,14 +151,14 @@ export class CurrentUserUtils {
         });
         // setup a color picker
         const color = Docs.Create.ColorDocument({
-            title: "color picker", width: 400, dropAction: "alias", forceActive: true, removeDropProperties: new List<string>(["dropAction", "forceActive"])
+            title: "color picker", width: 300, dropAction: "alias", forceActive: true, removeDropProperties: new List<string>(["dropAction", "forceActive"])
         });
 
         return Docs.Create.ButtonDocument({
             width: 35, height: 25, backgroundColor: "lightgrey", color: "rgb(34, 34, 34)", title: "Tools", fontSize: 10, targetContainer: sidebarContainer,
             letterSpacing: "0px", textTransform: "unset", borderRounding: "5px 5px 0px 0px", boxShadow: "3px 3px 0px rgb(34, 34, 34)",
             sourcePanel: Docs.Create.StackingDocument([dragCreators, color], {
-                width: 500, height: 800, lockedPosition: true, chromeStatus: "disabled", title: "tools stack"
+                width: 500, lockedPosition: true, chromeStatus: "disabled", title: "tools stack"
             }),
             onClick: ScriptField.MakeScript("this.targetContainer.proto = this.sourcePanel"),
         });
-- 
cgit v1.2.3-70-g09d2

