From 50876028b994044f2a9426a4efb85a363f0d7168 Mon Sep 17 00:00:00 2001
From: srichman333 <sarah_n_richman@brown.edu>
Date: Thu, 4 May 2023 10:46:20 -0400
Subject: properties view + sharing manager are consistent, and all text
 updates properly

---
 src/client/views/Main.tsx | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'src/client/views/Main.tsx')

diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index 6b18caed0..7da9dc603 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -26,7 +26,7 @@ FieldLoader.ServerLoadStatus = { requested: 0, retrieved: 0 }; // bcz: not sure
     root.render(<FieldLoader />);
     window.location.search.includes('safe') && CollectionView.SetSafeMode(true);
     const info = await CurrentUserUtils.loadCurrentUser();
-    if (info.email === 'guest') DocServer.Control.makeReadOnly();
+    // if (info.email === 'guest') DocServer.Control.makeReadOnly();
     await CurrentUserUtils.loadUserDocument(info.id);
     setTimeout(() => {
         document.getElementById('root')!.addEventListener(
-- 
cgit v1.2.3-70-g09d2


From 241332557f10fa97718200821374755b68e4fe10 Mon Sep 17 00:00:00 2001
From: Geireann Lindfield Roberts <60007097+geireann@users.noreply.github.com>
Date: Tue, 11 Jul 2023 23:42:29 -0400
Subject: updated settings manager

- fixed some things with top toolbar and refactored files
- removed FontIconBadge
---
 .vscode/launch.json                                |  10 +
 package-lock.json                                  |  36 +-
 package.json                                       |   2 +-
 src/client/util/CaptureManager.scss                |  18 -
 src/client/util/CurrentUserUtils.ts                |  14 +-
 src/client/util/GroupManager.scss                  |   6 +-
 src/client/util/SettingsManager.scss               |  72 +-
 src/client/util/SettingsManager.tsx                | 338 ++++++----
 src/client/util/SharingManager.scss                |   6 +-
 src/client/views/DashboardView.tsx                 |   1 +
 src/client/views/Main.tsx                          |   1 +
 src/client/views/global/globalScripts.ts           | 407 +++++++++++
 src/client/views/nodes/button/ButtonInterface.ts   |  12 -
 src/client/views/nodes/button/FontIconBadge.scss   |  11 -
 src/client/views/nodes/button/FontIconBadge.tsx    |  37 -
 src/client/views/nodes/button/FontIconBox.tsx      | 751 +++------------------
 .../views/nodes/button/textButton/TextButton.tsx   |  30 -
 src/client/views/nodes/button/textButton/index.ts  |   1 -
 .../nodes/button/toggleButton/ToggleButton.tsx     |  34 -
 .../views/nodes/button/toggleButton/index.ts       |   1 -
 src/client/views/nodes/trails/PresBox.tsx          |   2 +-
 21 files changed, 748 insertions(+), 1042 deletions(-)
 create mode 100644 src/client/views/global/globalScripts.ts
 delete mode 100644 src/client/views/nodes/button/ButtonInterface.ts
 delete mode 100644 src/client/views/nodes/button/FontIconBadge.scss
 delete mode 100644 src/client/views/nodes/button/FontIconBadge.tsx
 delete mode 100644 src/client/views/nodes/button/textButton/TextButton.tsx
 delete mode 100644 src/client/views/nodes/button/textButton/index.ts
 delete mode 100644 src/client/views/nodes/button/toggleButton/ToggleButton.tsx
 delete mode 100644 src/client/views/nodes/button/toggleButton/index.ts

(limited to 'src/client/views/Main.tsx')

diff --git a/.vscode/launch.json b/.vscode/launch.json
index ce9f50f67..9ba624af9 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -14,6 +14,16 @@
             "webRoot": "${workspaceFolder}",
             "runtimeArgs": ["--experimental-modules"]
         },
+        {
+            "type": "chrome",
+            "request": "launch",
+            "name": "Launch Brave against localhost",
+            "sourceMaps": true,
+            "url": "http://localhost:1050/home",
+            "runtimeExecutable": "/Applications/Brave Browser.app/Contents/MacOS/Brave Browser",
+            "webRoot": "${workspaceFolder}",
+            "runtimeArgs": ["--experimental-modules"]
+        },
         {
             "type": "chrome",
             "request": "launch",
diff --git a/package-lock.json b/package-lock.json
index bae345949..84c1e6219 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -6195,9 +6195,9 @@
             }
         },
         "browndash-components": {
-            "version": "0.0.54",
-            "resolved": "https://registry.npmjs.org/browndash-components/-/browndash-components-0.0.54.tgz",
-            "integrity": "sha512-cwwghwtCtdgbU1eWDH/Ptq03CsQObIjRfK5gcQJsQFS4MrY68ldvTQJnonsuFWJUBXuCIW8I/mBRE92yikYdng==",
+            "version": "0.0.62",
+            "resolved": "https://registry.npmjs.org/browndash-components/-/browndash-components-0.0.62.tgz",
+            "integrity": "sha512-lhIuqOylZF7y4ZQXOdTim2r8Et61AaUROl5UYaooCObHvjJb7WIGpFv9B1RQjlbg8vUJ4jeM3e3qb++Cf6ajPg==",
             "requires": {
                 "@emotion/react": "^11.11.1",
                 "@emotion/styled": "^11.11.0",
@@ -6314,9 +6314,9 @@
                     "integrity": "sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww=="
                 },
                 "@mui/base": {
-                    "version": "5.0.0-beta.6",
-                    "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-beta.6.tgz",
-                    "integrity": "sha512-jcHy6HwOX7KzRhRtL8nvIvUlxvLx2Fl6NMRCyUSQSvMTyfou9kndekz0H4HJaXvG1Y4WEifk23RYedOlrD1kEQ==",
+                    "version": "5.0.0-beta.7",
+                    "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-beta.7.tgz",
+                    "integrity": "sha512-Pjbwm6gjiS96kOMF7E5fjEJsenc0tZBesrLQ4rrdi3eT/c/yhSWnPbCUkHSz8bnS0l3/VQ8bA+oERSGSV2PK6A==",
                     "requires": {
                         "@babel/runtime": "^7.22.5",
                         "@emotion/is-prop-valid": "^1.2.1",
@@ -6339,19 +6339,19 @@
                     }
                 },
                 "@mui/core-downloads-tracker": {
-                    "version": "5.13.7",
-                    "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.13.7.tgz",
-                    "integrity": "sha512-/suIo4WoeL/OyO3KUsFVpdOmKiSAr6NpWXmQ4WLSxwKrTiha1FJxM6vwAki5W/5kR9WnVLw5E8JC4oHHsutT8w=="
+                    "version": "5.14.0",
+                    "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.14.0.tgz",
+                    "integrity": "sha512-SYBOVCatVDUf/lbrLGah09bHhX5WfUXg7kSskfLILr6SvKRni0NLp0aonxQ0SMALVVK3Qwa6cW4CdWuwS0gC1w=="
                 },
                 "@mui/material": {
-                    "version": "5.13.7",
-                    "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.13.7.tgz",
-                    "integrity": "sha512-+n453jDDm88zZM3b5YK29nZ7gXY+s+rryH9ovDbhmfSkOlFtp+KSqbXy5cTaC/UlDqDM7sYYJGq8BmJov3v9Tg==",
+                    "version": "5.14.0",
+                    "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.14.0.tgz",
+                    "integrity": "sha512-HP7CP71NhMkui2HUIEKl2/JfuHMuoarSUWAKlNw6s17bl/Num9rN61EM6uUzc2A2zHjj/00A66GnvDnmixEJEw==",
                     "requires": {
                         "@babel/runtime": "^7.22.5",
-                        "@mui/base": "5.0.0-beta.6",
-                        "@mui/core-downloads-tracker": "^5.13.7",
-                        "@mui/system": "^5.13.7",
+                        "@mui/base": "5.0.0-beta.7",
+                        "@mui/core-downloads-tracker": "^5.14.0",
+                        "@mui/system": "^5.14.0",
                         "@mui/types": "^7.2.4",
                         "@mui/utils": "^5.13.7",
                         "@types/react-transition-group": "^4.4.6",
@@ -6414,9 +6414,9 @@
                     }
                 },
                 "@mui/system": {
-                    "version": "5.13.7",
-                    "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.13.7.tgz",
-                    "integrity": "sha512-7R2KdI6vr8KtnauEfg9e9xQmPk6Gg/1vGNiALYyhSI+cYztxN6WmlSqGX4bjWn/Sygp1TUE1jhFEgs7MWruhkQ==",
+                    "version": "5.14.0",
+                    "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.14.0.tgz",
+                    "integrity": "sha512-0HZGkX8miJbiNw+rjlZ9l0Cfkz1bSqfSHQH0EH9J+nx0aAm5cBleg9piOlLdCNIWGgecCqsw4x62erGrGjjcJg==",
                     "requires": {
                         "@babel/runtime": "^7.22.5",
                         "@mui/private-theming": "^5.13.7",
diff --git a/package.json b/package.json
index 8ad11054c..b137ddd67 100644
--- a/package.json
+++ b/package.json
@@ -177,7 +177,7 @@
         "body-parser": "^1.19.2",
         "bootstrap": "^4.6.1",
         "brotli": "^1.3.3",
-        "browndash-components": "0.0.54",
+        "browndash-components": "0.0.62",
         "browser-assert": "^1.2.1",
         "bson": "^4.6.1",
         "canvas": "^2.9.3",
diff --git a/src/client/util/CaptureManager.scss b/src/client/util/CaptureManager.scss
index a5024247e..11e31fe2e 100644
--- a/src/client/util/CaptureManager.scss
+++ b/src/client/util/CaptureManager.scss
@@ -155,21 +155,3 @@
     }
 }
 
-.close-button {
-    position: absolute;
-    top: 10;
-    right: 10;
-    background:transparent;
-    border-radius:100%;
-    width: 25px;
-    height: 25px;
-    display: flex;
-    align-items: center;
-    justify-content: center;
-    transition: 0.2s;
-}
-
-.close-button:hover {
-    background: rgba(0,0,0,0.1);
-}
-
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 736aeceae..32229f22f 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -523,7 +523,7 @@ export class CurrentUserUtils {
         const newFolder = `TreeView_addNewFolder()`;
         const newFolderOpts: DocumentOptions = {
             _forceActive: true, _dragOnlyWithinContainer: true, _layout_hideContextMenu: true, _width: 30, _height: 30, undoIgnoreFields:new List<string>(['treeViewSortCriterion']),
-            title: "New folder", btnType: ButtonType.ClickButton, toolTip: "Create new folder", buttonText: "New folder", icon: "folder-plus", isSystem: true
+            title: "New folder", color: Colors.BLACK, btnType: ButtonType.ClickButton, toolTip: "Create new folder", buttonText: "New folder", icon: "folder-plus", isSystem: true
         };
         const newFolderScript = { onClick: newFolder};
         const newFolderButton = DocUtils.AssignScripts(DocUtils.AssignOpts(DocCast(myFilesystem?.layout_headerButton), newFolderOpts) ?? Docs.Create.FontIconDocument(newFolderOpts), newFolderScript);
@@ -557,7 +557,7 @@ export class CurrentUserUtils {
 
         const clearAll = (target:string) => `getProto(${target}).data = new List([])`;
         const clearBtnsOpts:DocumentOptions = { _width: 30, _height: 30, _forceActive: true, _dragOnlyWithinContainer: true, _layout_hideContextMenu: true, 
-            title: "Empty", target: recentlyClosed, btnType: ButtonType.ClickButton,  buttonText: "Empty", icon: "trash", isSystem: true,
+            title: "Empty", target: recentlyClosed, btnType: ButtonType.ClickButton, color: Colors.BLACK, buttonText: "Empty", icon: "trash", isSystem: true,
             toolTip: "Empty recently closed",};
         DocUtils.AssignDocField(recentlyClosed, "layout_headerButton", (opts) => Docs.Create.FontIconDocument(opts), clearBtnsOpts, undefined, {onClick: clearAll("self.target")});
 
@@ -611,8 +611,8 @@ export class CurrentUserUtils {
             title: "docked buttons", _height: 40, flexGap: 0, layout_boxShadow: "standard", childDragAction: 'move',
             childDontRegisterViews: true, linearView_IsExpanded: true, linearView_Expandable: true, ignoreClick: true
         };
-        reaction(() => UndoManager.redoStack.slice(), () => Doc.GetProto(btns.find(btn => btn.title === "redo")!).opacity = UndoManager.CanRedo() ? 1 : 0.4, { fireImmediately: true });
-        reaction(() => UndoManager.undoStack.slice(), () => Doc.GetProto(btns.find(btn => btn.title === "undo")!).opacity = UndoManager.CanUndo() ? 1 : 0.4, { fireImmediately: true });
+        reaction(() => UndoManager.redoStack.slice(), () => Doc.GetProto(btns.find(btn => btn.title === "Redo")!).opacity = UndoManager.CanRedo() ? 1 : 0.4, { fireImmediately: true });
+        reaction(() => UndoManager.undoStack.slice(), () => Doc.GetProto(btns.find(btn => btn.title === "Undo")!).opacity = UndoManager.CanUndo() ? 1 : 0.4, { fireImmediately: true });
         return DocUtils.AssignDocField(doc, field, (opts, items) => this.linearButtonList(opts, items??[]), dockBtnsReqdOpts, btns);
     }
 
@@ -637,7 +637,7 @@ export class CurrentUserUtils {
         return [
             { title: "Font",     toolTip: "Font", width: 100,     btnType: ButtonType.DropdownList,                      toolType:"font",     ignoreClick: true,   scripts: {script:  '{ return setFontAttr(self.toolType, value, _readOnly_);}'},
               btnList: new List<string>(["Roboto", "Roboto Mono", "Nunito", "Times New Roman", "Arial", "Georgia", "Comic Sans MS", "Tahoma", "Impact", "Crimson Text"]) },
-            { title: "Font Size",toolTip: "Font size (%size)",    btnType: ButtonType.NumberDropdownButton, width: 75,           toolType:"fontSize", ignoreClick: true,   scripts: {script:  '{ return setFontAttr(self.toolType, value, _readOnly_);}'}, numBtnMax: 200, numBtnMin: 0 },
+            { title: "Font Size",toolTip: "Font size (%size)",    btnType: ButtonType.NumberDropdownButton,              toolType:"fontSize", ignoreClick: true,   scripts: {script:  '{ return setFontAttr(self.toolType, value, _readOnly_);}'}, numBtnMax: 200, numBtnMin: 6 },
             { title: "Color",    toolTip: "Font color (%color)",  btnType: ButtonType.ColorButton,  icon: "font",        toolType:"fontColor",ignoreClick: true,   scripts: {script:  '{ return setFontAttr(self.toolType, value, _readOnly_);}'}},
             { title: "Highlight",toolTip:"Font highlight",        btnType: ButtonType.ColorButton,  icon: "highlighter", toolType:"highlight",ignoreClick: true,   scripts: {script:  '{ return setFontAttr(self.toolType, value, _readOnly_);}'},funcs: {hidden: "IsNoviceMode()"} },
             { title: "Bold",     toolTip: "Bold (Ctrl+B)",        btnType: ButtonType.ToggleButton, icon: "bold",        toolType:"bold",                          scripts: {onClick: '{ return toggleCharStyle(self.toolType, _readOnly_);}'} },
@@ -698,7 +698,7 @@ export class CurrentUserUtils {
             { title: "Header",  icon: "heading",       toolTip: "Header Color",         btnType: ButtonType.ColorButton,         expertMode: false,                                                                                                          ignoreClick: true,             scripts: { script:  'return setHeaderColor(value, _readOnly_)'}},
             { title: "Overlay", icon: "layer-group",   toolTip: "Overlay",              btnType: ButtonType.ToggleButton,        expertMode: false, toolType:CollectionViewType.Freeform, funcs: {hidden: '!SelectionManager_selectedDocType(self.toolType, self.expertMode, true)'},       scripts: { onClick: 'toggleOverlay(_readOnly_)'}}, // Only when floating document is selected in freeform
             { title: "Back",    icon: "chevron-left",  toolTip: "Prev Animation Frame", btnType: ButtonType.ClickButton,         expertMode: true,  toolType:CollectionViewType.Freeform, funcs: {hidden: '!SelectionManager_selectedDocType(self.toolType, self.expertMode)'}, width: 30,  scripts: { onClick: 'prevKeyFrame(_readOnly_)'}},
-            { title: "Num",     icon:"",                toolTip: "Frame Number (click to toggle edit mode)",    btnType: ButtonType.TextButton,          expertMode: true,  toolType:CollectionViewType.Freeform, funcs: {hidden: '!SelectionManager_selectedDocType(self.toolType, self.expertMode)', buttonText: 'selectedDocs()?.lastElement()?.currentFrame?.toString()'}, width: 20, scripts: { onClick: '{ return curKeyFrame(_readOnly_);}'}},
+            { title: "Num",     icon:"",               toolTip: "Frame Number (click to toggle edit mode)",    btnType: ButtonType.TextButton,          expertMode: true,  toolType:CollectionViewType.Freeform, funcs: {hidden: '!SelectionManager_selectedDocType(self.toolType, self.expertMode)', buttonText: 'selectedDocs()?.lastElement()?.currentFrame?.toString()'}, width: 20, scripts: { onClick: '{ return curKeyFrame(_readOnly_);}'}},
             { title: "Fwd",     icon: "chevron-right", toolTip: "Next Animation Frame", btnType: ButtonType.ClickButton,         expertMode: true,  toolType:CollectionViewType.Freeform, funcs: {hidden: '!SelectionManager_selectedDocType(self.toolType, self.expertMode)'}, width: 30,  scripts: { onClick: 'nextKeyFrame(_readOnly_)'}},
             { title: "Text",    icon: "Text",          toolTip: "Text functions",       subMenu: CurrentUserUtils.textTools(),   expertMode: false, toolType:DocumentType.RTF,            funcs: {                                                                             linearView_IsExpanded: `SelectionManager_selectedDocType(self.toolType, self.expertMode)`} }, // Always available
             { title: "Ink",     icon: "Ink",           toolTip: "Ink functions",        subMenu: CurrentUserUtils.inkTools(),    expertMode: false, toolType:DocumentType.INK,            funcs: {                                                                             linearView_IsExpanded: `SelectionManager_selectedDocType(self.toolType, self.expertMode)`}, scripts: { onClick: 'setInkToolDefaults()'} }, // Always available
@@ -809,7 +809,7 @@ export class CurrentUserUtils {
         const myImports = DocUtils.AssignDocField(doc, field, (opts) => Docs.Create.StackingDocument([], opts), reqdOpts);
     
         const reqdBtnOpts:DocumentOptions = { _forceActive: true, toolTip: "Import from computer",
-            _width: 30, _height: 30, _dragOnlyWithinContainer: true, _layout_hideContextMenu: true, title: "Import", btnType: ButtonType.ClickButton, 
+            _width: 30, _height: 30, color: Colors.BLACK, _dragOnlyWithinContainer: true, _layout_hideContextMenu: true, title: "Import", btnType: ButtonType.ClickButton, 
             buttonText: "Import", icon: "upload", isSystem: true };
         DocUtils.AssignDocField(myImports, "layout_headerButton", (opts) => Docs.Create.FontIconDocument(opts), reqdBtnOpts, undefined, { onClick: "importDocument()" });
         return myImports;
diff --git a/src/client/util/GroupManager.scss b/src/client/util/GroupManager.scss
index 9438bdd72..70fa88f6d 100644
--- a/src/client/util/GroupManager.scss
+++ b/src/client/util/GroupManager.scss
@@ -66,10 +66,8 @@
 
     .close-button {
         position: absolute;
-        right: 1em;
-        top: 1em;
-        cursor: pointer;
-        z-index: 999;
+        right: 2px;
+        top: 2px;
     }
 
     .group-heading {
diff --git a/src/client/util/SettingsManager.scss b/src/client/util/SettingsManager.scss
index 1289ca2b4..c41adfdd7 100644
--- a/src/client/util/SettingsManager.scss
+++ b/src/client/util/SettingsManager.scss
@@ -62,26 +62,31 @@
 .password-content {
     display: flex;
     flex-direction: column;
+    align-items: flex-start;
 
     .password-content-inputs {
-        width: 100;
-        // margin-bottom: 10px;
+        display: flex;
+        flex-direction: column;
+        width: 100%;
         font-size: 10px;
+        align-items: flex-start;
 
         .password-inputs {
             border: 1px solid rgb(160, 160, 160);
-            margin-bottom: 8px;
+            margin-bottom: 15px;
             width: 130;
-            color: black;
+            color: $medium-gray;
             border-radius: 5px;
             padding: 7px;
         }
     }
 
     .password-content-buttons {
-        //margin-left: 84px;
-        //width: 100;
-        padding: 7px;
+        display: flex;
+        gap: 5px;
+        justify-content: center;
+        align-items: flex-start;
+        flex-direction: column;
 
         .password-submit {
             //margin-left: 85px;
@@ -103,7 +108,6 @@
 
 .modes-content {
     display: flex;
-    margin-left: 10px;
     font-size: 12px;
 
     .modes-select {
@@ -172,12 +176,12 @@
 
 .appearances-content {
     display: flex;
-    margin-top: 4px;
     color: black;
     font-size: 10px;
 
     .preferences-color {
         display: flex;
+        align-items: center;
         margin-top: 2px;
 
         .preferences-color-text {
@@ -252,40 +256,18 @@
     display: flex;
     flex-direction: column;
 
-    button {
-        width: auto;
-        align-self: center;
-        background: #252b33;
-        margin-right: 15px;
-
-        //margin-top: 4px;
-
-        &:hover {
-            background: $medium-gray;
-        }
-    }
-
-    // .delete-button {
-    //     background: rgb(227, 86, 86);
-    // }
 
     .close-button {
         position: absolute;
-        right: 1em;
-        top: 1em;
-        cursor: pointer;
+        right: 2px;
+        top: 2px;
     }
 
-    // .logout-button {
-    //     right: 355;
-    //     position: absolute;
-    // }
 
     .settings-content {
         background: #e4e4e4;
-        //border-radius: 6px;
         padding: 10px;
-        //width: 560px;
+        width: 500px;
         flex: 1 1 auto;
     }
 
@@ -296,11 +278,8 @@
 
     .error-text {
         color: #c40233;
-        width: 300;
-        margin-left: -20;
         font-size: 10;
         margin-bottom: 4;
-        margin-top: -3;
     }
 
     .success-text {
@@ -370,8 +349,11 @@
 
     .settings-user {
         position: absolute;
+        display: flex;
+        justify-content: center;
+        align-items: center;
+        flex-direction: column;
         bottom: 10px;
-        text-align: center;
         left: 0;
         right: 0;
 
@@ -419,17 +401,25 @@
 
     .tab-column {
         flex: 0 0 50%;
+        flex-direction: column;
+        display: flex;
+        justify-content: flex-start;
+        align-items: flex-start;
 
         .tab-column-title {
-            color: black;
+            color: $dark-gray;
             font-size: 16px;
             font-weight: bold;
-            margin-bottom: 16px;
+            margin-bottom: 10px;
         }
 
         .tab-column-title,
         .tab-column-content {
-            padding-left: 16px;
+            display: flex;
+            justify-content: center;
+            align-items: flex-start;
+            flex-direction: column;
+            gap: 10px;
         }
     }
 }
diff --git a/src/client/util/SettingsManager.tsx b/src/client/util/SettingsManager.tsx
index f886ce2ca..09d6d034f 100644
--- a/src/client/util/SettingsManager.tsx
+++ b/src/client/util/SettingsManager.tsx
@@ -16,6 +16,9 @@ import { DragManager } from './DragManager';
 import { GroupManager } from './GroupManager';
 import './SettingsManager.scss';
 import { undoBatch } from './UndoManager';
+import { Button, ColorPicker, Dropdown, DropdownType, Group, Size, Toggle, ToggleType, Type } from 'browndash-components';
+import { BsGoogle } from 'react-icons/bs'
+import { FaFillDrip, FaPalette } from 'react-icons/fa'
 const higflyout = require('@hig/flyout');
 export const { anchorPoints } = higflyout;
 export const Flyout = higflyout.default;
@@ -73,14 +76,14 @@ export class SettingsManager extends React.Component<{}> {
         }
     };
 
-    @undoBatch selectUserMode = action((e: React.ChangeEvent) => (Doc.noviceMode = (e.currentTarget as any)?.value === 'Novice'));
+    @undoBatch selectUserMode = action((mode: string) => (Doc.noviceMode = mode === 'Novice'));
     @undoBatch changelayout_showTitle = action((e: React.ChangeEvent) => (Doc.UserDoc().layout_showTitle = (e.currentTarget as any).value ? 'title' : undefined));
-    @undoBatch changeFontFamily = action((e: React.ChangeEvent) => (Doc.UserDoc().fontFamily = (e.currentTarget as any).value));
-    @undoBatch changeFontSize = action((e: React.ChangeEvent) => (Doc.UserDoc().fontSize = (e.currentTarget as any).value));
-    @undoBatch switchActiveBackgroundColor = action((color: ColorState) => (Doc.UserDoc().activeCollectionBackground = String(color.hex)));
-    @undoBatch switchUserColor = action((color: ColorState) => {
+    @undoBatch changeFontFamily = action((font: string) => (Doc.UserDoc().fontFamily = font));
+    @undoBatch changeFontSize = action((val: number) => (Doc.UserDoc().fontSize = val));
+    @undoBatch switchActiveBackgroundColor = action((color: string) => (Doc.UserDoc().activeCollectionBackground = color));
+    @undoBatch switchUserColor = action((color: string) => {
         Doc.SharingDoc().userColor = undefined;
-        Doc.GetProto(Doc.SharingDoc()).userColor = String(color.hex);
+        Doc.GetProto(Doc.SharingDoc()).userColor = color;
     });
     @undoBatch playgroundModeToggle = action(() => {
         this.playgroundMode = !this.playgroundMode;
@@ -92,13 +95,12 @@ export class SettingsManager extends React.Component<{}> {
 
     @undoBatch
     @action
-    changeColorScheme = action((e: React.ChangeEvent) => {
+    changeColorScheme = action((scheme: string) => {
         const activeDashboard = Doc.ActiveDashboard;
         if (!activeDashboard) return;
-        const scheme: ColorScheme = (e.currentTarget as any).value;
         switch (scheme) {
             case ColorScheme.Light:
-                activeDashboard.colorScheme = undefined; // undefined means ColorScheme.Light until all CSS is updated with values for each color scheme (e.g., see MainView.scss, DocumentDecorations.scss)
+                activeDashboard.colorScheme = ColorScheme.Light
                 addStyleSheetRule(SettingsManager._settingsStyle, 'lm_header', { background: '#d3d3d3 !important' });
                 break;
             case ColorScheme.Dark:
@@ -107,67 +109,39 @@ export class SettingsManager extends React.Component<{}> {
                 break;
             case ColorScheme.System:
             default:
+                activeDashboard.colorScheme = ColorScheme.System;
                 window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', e => {
-                    activeDashboard.colorScheme = e.matches ? ColorScheme.Dark : undefined; // undefined means ColorScheme.Light until all CSS is updated with values for each color scheme (e.g., see MainView.scss, DocumentDecorations.scss)
+                    activeDashboard.colorScheme = e.matches ? ColorScheme.Dark : ColorScheme.Light; // undefined means ColorScheme.Light until all CSS is updated with values for each color scheme (e.g., see MainView.scss, DocumentDecorations.scss)
                 });
                 break;
         }
     });
 
     @computed get colorsContent() {
-        const colorBox = (func: (color: ColorState) => void) => (
-            <SketchPicker
-                onChange={func}
-                color={StrCast(this.backgroundColor)}
-                presetColors={['#D0021B', '#F5A623', '#F8E71C', '#8B572A', '#7ED321', '#417505', '#9013FE', '#4A90E2', '#50E3C2', '#B8E986', '#000000', '#4A4A4A', '#9B9B9B', '#FFFFFF', '#f1efeb', 'transparent']}
-            />
-        );
 
-        const colorFlyout = (
-            <div className="colorFlyout">
-                <Flyout anchorPoint={anchorPoints.LEFT_TOP} content={colorBox(this.switchActiveBackgroundColor)}>
-                    <div className="colorFlyout-button" style={{ backgroundColor: StrCast(this.backgroundColor) }} onPointerDown={e => e.stopPropagation()}>
-                        <FontAwesomeIcon icon="palette" size="sm" color={StrCast(this.backgroundColor)} />
-                    </div>
-                </Flyout>
-            </div>
-        );
-        const userColorFlyout = (
-            <div className="colorFlyout">
-                <Flyout anchorPoint={anchorPoints.LEFT_TOP} content={colorBox(this.switchUserColor)}>
-                    <div className="colorFlyout-button" style={{ backgroundColor: StrCast(this.backgroundColor) }} onPointerDown={e => e.stopPropagation()}>
-                        <FontAwesomeIcon icon="palette" size="sm" color={StrCast(this.backgroundColor)} />
-                    </div>
-                </Flyout>
-            </div>
-        );
 
         const colorSchemes = [ColorScheme.Light, ColorScheme.Dark, ColorScheme.System];
-        const schemeMap = ['Light', 'Dark', 'Match system'];
+        const schemeMap = ['Light', 'Dark', 'Match System'];
 
         return (
             <div className="colors-content">
-                <div className="preferences-color">
-                    <div className="preferences-color-text">Background Color</div>
-                    {colorFlyout}
-                </div>
-                <div className="preferences-color">
-                    <div className="preferences-color-text">Border/Header Color</div>
-                    {userColorFlyout}
-                </div>
-                <div className="preferences-colorScheme">
-                    <div className="preferences-color-text">Color Scheme</div>
-                    <div className="preferences-color-controls">
-                        <select className="scheme-select" onChange={this.changeColorScheme} defaultValue={StrCast(Doc.ActiveDashboard?.colorScheme)}>
-                            {colorSchemes.map((scheme, i) => (
-                                <option key={scheme} value={scheme}>
-                                    {' '}
-                                    {schemeMap[i]}{' '}
-                                </option>
-                            ))}
-                        </select>
-                    </div>
-                </div>
+                <ColorPicker formLabel='Background Color' icon={<FaFillDrip/>} selectedColor={StrCast(Doc.UserDoc().activeCollectionBackground)} setSelectedColor={this.switchActiveBackgroundColor}/>
+                <ColorPicker formLabel='User Color' icon={<FaPalette/>} selectedColor={StrCast(Doc.SharingDoc().userColor)} setSelectedColor={this.switchUserColor}/>
+                <Dropdown 
+                    formLabel='Theme'
+                    size={Size.SMALL}
+                    type={Type.TERT}
+                    selectedVal={StrCast(Doc.ActiveDashboard?.colorScheme)}
+                    setSelectedVal={(scheme) => this.changeColorScheme(scheme as string)}
+                    items={colorSchemes.map((scheme, i) => (
+                        {
+                            text: schemeMap[i],
+                            val: scheme
+                        }
+                    ))} 
+                    dropdownType={DropdownType.SELECT}
+                    color={StrCast(Doc.SharingDoc().userColor)}
+                />
             </div>
         );
     }
@@ -175,30 +149,65 @@ export class SettingsManager extends React.Component<{}> {
     @computed get formatsContent() {
         return (
             <div className="prefs-content">
-                <div>
-                    <input type="checkbox" onChange={e => (Doc.UserDoc().layout_showTitle = Doc.UserDoc().layout_showTitle ? undefined : 'author_date')} checked={Doc.UserDoc().layout_showTitle !== undefined} />
-                    <div className="preferences-check">Show doc header</div>
-                </div>
-                <div>
-                    <input type="checkbox" onChange={e => (Doc.UserDoc()['documentLinksButton-fullMenu'] = !Doc.UserDoc()['documentLinksButton-fullMenu'])} checked={BoolCast(Doc.UserDoc()['documentLinksButton-fullMenu'])} />
-                    <div className="preferences-check">Show full toolbar</div>
-                </div>
-                <div>
-                    <input type="checkbox" onChange={e => FontIconBox.SetShowLabels(!FontIconBox.GetShowLabels())} checked={FontIconBox.GetShowLabels()} />
-                    <div className="preferences-check">Show button labels</div>
-                </div>
-                <div>
-                    <input type="checkbox" onChange={e => FontIconBox.SetRecognizeGestures(!FontIconBox.GetRecognizeGestures())} checked={FontIconBox.GetRecognizeGestures()} />
-                    <div className="preferences-check">Recognize ink Gestures</div>
-                </div>
-                <div>
-                    <input type="checkbox" onChange={e => (Doc.UserDoc().activeInkHideTextLabels = !Doc.UserDoc().activeInkHideTextLabels)} checked={BoolCast(Doc.UserDoc().activeInkHideTextLabels)} />
-                    <div className="preferences-check">Hide Labels In Ink Shapes</div>
-                </div>
-                <div>
-                    <input type="checkbox" onChange={e => (Doc.UserDoc().openInkInLightbox = !Doc.UserDoc().openInkInLightbox)} checked={BoolCast(Doc.UserDoc().openInkInLightbox)} />
-                    <div className="preferences-check">Open Ink Docs in Lightbox</div>
-                </div>
+                <Toggle 
+                    formLabel={'Show document header'} 
+                    formLabelPlacement={'right'} 
+                    toggleType={ToggleType.SWITCH} 
+                    onClick={e => (Doc.UserDoc().layout_showTitle = Doc.UserDoc().layout_showTitle ? undefined : 'author_date')} 
+                    toggleStatus={Doc.UserDoc().layout_showTitle !== undefined} size={Size.XSMALL}
+                    color={StrCast(Doc.SharingDoc().userColor)}
+
+                />
+                <Toggle 
+                    formLabel={'Show Full Toolbar'} 
+                    formLabelPlacement={'right'} 
+                    toggleType={ToggleType.SWITCH} 
+                    onClick={e => (Doc.UserDoc()['documentLinksButton-fullMenu'] = !Doc.UserDoc()['documentLinksButton-fullMenu'])} 
+                    toggleStatus={BoolCast(Doc.UserDoc()['documentLinksButton-fullMenu'])} 
+                    size={Size.XSMALL}
+                    color={StrCast(Doc.SharingDoc().userColor)}
+
+                />
+                <Toggle 
+                    formLabel={'Show Button Labels'} 
+                    formLabelPlacement={'right'} 
+                    toggleType={ToggleType.SWITCH} 
+                    onClick={e => FontIconBox.SetShowLabels(!FontIconBox.GetShowLabels())} 
+                    toggleStatus={FontIconBox.GetShowLabels()} 
+                    size={Size.XSMALL}
+                    color={StrCast(Doc.SharingDoc().userColor)}
+
+                />
+                <Toggle 
+                    formLabel={'Recognize Ink Gestures'} 
+                    formLabelPlacement={'right'} 
+                    toggleType={ToggleType.SWITCH} 
+                    onClick={e => FontIconBox.SetRecognizeGestures(!FontIconBox.GetRecognizeGestures())} 
+                    toggleStatus={FontIconBox.GetRecognizeGestures()} 
+                    size={Size.XSMALL}
+                    color={StrCast(Doc.SharingDoc().userColor)}
+
+                />
+                <Toggle 
+                    formLabel={'Hide Labels In Ink Shapes'} 
+                    formLabelPlacement={'right'} 
+                    toggleType={ToggleType.SWITCH} 
+                    onClick={e => (Doc.UserDoc().activeInkHideTextLabels = !Doc.UserDoc().activeInkHideTextLabels)} 
+                    toggleStatus={BoolCast(Doc.UserDoc().activeInkHideTextLabels)} 
+                    size={Size.XSMALL}
+                    color={StrCast(Doc.SharingDoc().userColor)}
+
+                />
+                <Toggle 
+                    formLabel={'Open Ink Docs in Lightbox'} 
+                    formLabelPlacement={'right'} 
+                    toggleType={ToggleType.SWITCH} 
+                    onClick={e => (Doc.UserDoc().openInkInLightbox = !Doc.UserDoc().openInkInLightbox)} 
+                    toggleStatus={BoolCast(Doc.UserDoc().openInkInLightbox)} 
+                    size={Size.XSMALL}
+                    color={StrCast(Doc.SharingDoc().userColor)}
+
+                />
             </div>
         );
     }
@@ -224,25 +233,28 @@ export class SettingsManager extends React.Component<{}> {
 
         return (
             <div className="tab-content appearances-content">
-                <div className="preferences-font">
-                    <div className="preferences-font-text">Default Font</div>
-                    <div className="preferences-font-controls">
-                        <select className="size-select" onChange={this.changeFontSize} value={StrCast(Doc.UserDoc().fontSize, '7px')}>
-                            {fontSizes.map(size => (
-                                <option key={size} value={size} defaultValue={StrCast(Doc.UserDoc().fontSize)}>
-                                    {' '}
-                                    {size}{' '}
-                                </option>
-                            ))}
-                        </select>
-                        <select className="font-select" onChange={this.changeFontFamily} value={StrCast(Doc.UserDoc().fontFamily, 'Times New Roman')}>
-                            {fontFamilies.map(font => (
-                                <option key={font} value={font} defaultValue={StrCast(Doc.UserDoc().fontFamily)}>
-                                    {' '}
-                                    {font}{' '}
-                                </option>
-                            ))}
-                        </select>
+                <div className="tab-column">
+                    <div className="tab-column-title">Text</div>
+                    <div className="tab-column-content">
+                        {/* <NumberInput/> */}
+                        <Group formLabel={'Default Font'}>
+                            <Dropdown 
+                                items={fontFamilies.map((val) => {
+                                    return {
+                                        text: val,
+                                        val: val,
+                                        style: {
+                                            fontFamily: val
+                                        }
+                                    }
+                                })} 
+                                dropdownType={DropdownType.SELECT}
+                                type={Type.TERT}
+                                selectedVal={StrCast(Doc.UserDoc().fontFamily)}
+                                setSelectedVal={(val) => {this.changeFontFamily(val as string)}}
+                                color={StrCast(Doc.SharingDoc().userColor)}
+                            />
+                        </Group>
                     </div>
                 </div>
             </div>
@@ -275,12 +287,8 @@ export class SettingsManager extends React.Component<{}> {
                 </div>
                 <div className="password-content-buttons">
                     {!this.passwordResultText ? null : <div className={`${this.passwordResultText.startsWith('Error') ? 'error' : 'success'}-text`}>{this.passwordResultText}</div>}
-                    <a className="password-forgot" href="/forgotPassword">
-                        forgot password?
-                    </a>
-                    <button className="password-submit" onClick={this.changePassword}>
-                        submit
-                    </button>
+                    <Button type={Type.SEC} text={'Forgot Password'} color={StrCast(Doc.SharingDoc().userColor)}/>
+                    <Button type={Type.TERT} text={'Submit'} onClick={this.changePassword} color={StrCast(Doc.SharingDoc().userColor)}/>
                 </div>
             </div>
         );
@@ -289,9 +297,7 @@ export class SettingsManager extends React.Component<{}> {
     @computed get accountOthersContent() {
         return (
             <div className="account-others-content">
-                <button onClick={this.googleAuthorize} value="data">
-                    Authorize Google Acc
-                </button>
+                <Button type={Type.TERT} text={'Connect to Google'} iconPlacement='left' icon={<BsGoogle/>} onClick={() => this.googleAuthorize()}/>
             </div>
         );
     }
@@ -311,7 +317,7 @@ export class SettingsManager extends React.Component<{}> {
         );
     }
 
-    setFreeformScrollMode = (mode: freeformScrollMode) => {
+    setFreeformScrollMode = (mode: string) => {
         Doc.UserDoc().freeformScrollMode = mode;
     };
 
@@ -321,45 +327,77 @@ export class SettingsManager extends React.Component<{}> {
                 <div className="tab-column">
                     <div className="tab-column-title">Modes</div>
                     <div className="tab-column-content">
-                        <select className="modes-select" onChange={this.selectUserMode} defaultValue={Doc.noviceMode ? 'Novice' : 'Developer'}>
-                            <option key={'Novice'} value={'Novice'}>
-                                {' '}
-                                Novice{' '}
-                            </option>
-                            <option key={'Developer'} value={'Developer'}>
-                                {' '}
-                                Developer
-                            </option>
-                        </select>
-                        <div className="modes-playground">
-                            <input className="playground-check" type="checkbox" checked={this.playgroundMode} onChange={this.playgroundModeToggle} />
-                            <div className="playground-text">Playground Mode</div>
-                        </div>
+                        <Dropdown 
+                            formLabel={"Mode"}
+                            items={[
+                                {
+                                    text: 'Novice',
+                                    description: 'Novice mode is a user-friendly setting designed to cater to those who are new to Dash',
+                                    val: "Novice"
+                                },
+                                {
+                                    text: 'Developer',
+                                    description: 'Developer mode is an advanced setting that grants you greater control and access to the underlying mechanics and tools of a software or system. Developer mode is still under development as there are experimental features.',
+                                    val: "Developer"
+                                },
+                            ]} 
+                            selectedVal={Doc.noviceMode ? 'Novice' : 'Developer'}
+                            setSelectedVal={(val) => {this.selectUserMode(val as string)}}
+                            dropdownType={DropdownType.SELECT}
+                            type={Type.TERT}
+                            placement='bottom-start'
+                            color={StrCast(Doc.SharingDoc().userColor)}
+                        />
+                        <Toggle 
+                            formLabel={'Playground Mode'} 
+                            toggleType={ToggleType.SWITCH} 
+                            toggleStatus={this.playgroundMode} 
+                            onClick={this.playgroundModeToggle}
+                            color={StrCast(Doc.SharingDoc().userColor)}
+                        />
                     </div>
-                    <div className="tab-column-title" style={{ marginTop: 10, marginBottom: 0 }}>
-                        Freeform scrolling
+                    <div className="tab-column-title" style={{ marginTop: 20, marginBottom: 10 }}>
+                        Freeform Navigation
                     </div>
                     <div className="tab-column-content">
-                        <button style={{ backgroundColor: Doc.UserDoc().freeformScrollMode === freeformScrollMode.Pan ? 'blue' : '' }} onClick={() => this.setFreeformScrollMode(freeformScrollMode.Pan)}>
-                            Scroll to pan
-                        </button>
-                        <div>
-                            <div>Scrolling pans canvas, shift + scrolling zooms</div>
-                        </div>
-                        <button style={{ backgroundColor: Doc.UserDoc().freeformScrollMode === freeformScrollMode.Zoom ? 'blue' : '' }} onClick={() => this.setFreeformScrollMode(freeformScrollMode.Zoom)}>
-                            Scroll to zoom
-                        </button>
-                        <div>Scrolling zooms canvas</div>
+                        <Dropdown 
+                            formLabel={"Scroll Mode"}
+                            items={[
+                                {
+                                    text: 'Scroll to Pan',
+                                    description: 'Scrolling pans canvas, shift + scrolling zooms',
+                                    val: freeformScrollMode.Pan
+                                },
+                                {
+                                    text: 'Scroll to Zoom',
+                                    description: 'Scrolling zooms canvas',
+                                    val: freeformScrollMode.Zoom
+                                },
+                            ]} 
+                            selectedVal={StrCast(Doc.UserDoc().freeformScrollMode)}
+                            setSelectedVal={(val) => this.setFreeformScrollMode(val as string)}
+                            dropdownType={DropdownType.SELECT}
+                            type={Type.TERT}
+                            placement='bottom-start'
+                            color={StrCast(Doc.SharingDoc().userColor)}
+                        />
                     </div>
                 </div>
                 <div className="tab-column">
                     <div className="tab-column-title">Permissions</div>
                     <div className="tab-column-content">
-                        <button onClick={() => GroupManager.Instance?.open()}>Manage groups</button>
-                        <div className="default-acl">
-                            <input className="acl-check" type="checkbox" checked={BoolCast(Doc.defaultAclPrivate)} onChange={action(() => (Doc.defaultAclPrivate = !Doc.defaultAclPrivate))} />
-                            <div className="acl-text">Default access private</div>
-                        </div>
+                        <Button
+                            text={"Manage Groups"}
+                            type={Type.TERT}
+                            onClick={() => GroupManager.Instance?.open()}
+                            color={StrCast(Doc.SharingDoc().userColor)}
+                        />
+                        <Toggle 
+                            toggleType={ToggleType.SWITCH} 
+                            formLabel={"Default access private"}
+                            color={StrCast(Doc.SharingDoc().userColor)}
+                            toggleStatus={BoolCast(Doc.defaultAclPrivate)} 
+                            onClick={action(() => (Doc.defaultAclPrivate = !Doc.defaultAclPrivate))}/>
                     </div>
                 </div>
             </div>
@@ -390,14 +428,20 @@ export class SettingsManager extends React.Component<{}> {
 
                     <div className="settings-user">
                         <div className="settings-username">{Doc.CurrentUserEmail}</div>
-                        <button className="logout-button" onClick={() => window.location.assign(Utils.prepend('/logout'))}>
-                            {Doc.GuestDashboard ? 'Exit' : 'Log Out'}
-                        </button>
+                        <Button 
+                            text={Doc.GuestDashboard ? 'Exit' : 'Log Out'}
+                            type={Type.TERT}
+                            onClick={() => window.location.assign(Utils.prepend('/logout'))}
+                        />
                     </div>
                 </div>
 
-                <div className="close-button" onClick={this.close}>
-                    <FontAwesomeIcon icon={'times'} color="black" size={'lg'} />
+                            
+                <div className="close-button">
+                    <Button
+                        icon={<FontAwesomeIcon icon={'times'} color="black" size={'lg'} />}
+                        onClick={this.close}
+                    />
                 </div>
 
                 <div className="settings-content">
@@ -418,7 +462,7 @@ export class SettingsManager extends React.Component<{}> {
                 isDisplayed={this.isOpen}
                 interactive={true}
                 closeOnExternalClick={this.close}
-                dialogueBoxStyle={{ width: '500px', height: '300px', background: Cast(Doc.SharingDoc().userColor, 'string', null) }}
+                dialogueBoxStyle={{ width: 'fit-content', height: '300px', background: Cast(Doc.SharingDoc().userColor, 'string', null) }}
             />
         );
     }
diff --git a/src/client/util/SharingManager.scss b/src/client/util/SharingManager.scss
index 932e94664..1be27fa62 100644
--- a/src/client/util/SharingManager.scss
+++ b/src/client/util/SharingManager.scss
@@ -17,10 +17,8 @@
 
         .close-button {
             position: absolute;
-            right: 1em;
-            top: 1em;
-            cursor: pointer;
-            z-index: 999;
+            right: 2px;
+            top: 2px;
         }
 
         .share-container {
diff --git a/src/client/views/DashboardView.tsx b/src/client/views/DashboardView.tsx
index 1a7a4d342..3bd6ac61c 100644
--- a/src/client/views/DashboardView.tsx
+++ b/src/client/views/DashboardView.tsx
@@ -394,6 +394,7 @@ export class DashboardView extends React.Component {
             _layout_hideContextMenu: true,
             title: 'New trail',
             toolTip: 'Create new trail',
+            color: Colors.BLACK,
             btnType: ButtonType.ClickButton,
             buttonText: 'New trail',
             icon: 'plus',
diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index b0b757388..e84e2620f 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -16,6 +16,7 @@ import { CollectionView } from './collections/CollectionView';
 import { MainView } from './MainView';
 import * as dotenv from 'dotenv'; // see https://github.com/motdotla/dotenv#how-do-i-use-dotenv-with-import
 import { PingManager } from '../util/PingManager';
+import './global/globalScripts';
 dotenv.config();
 
 AssignAllExtensions();
diff --git a/src/client/views/global/globalScripts.ts b/src/client/views/global/globalScripts.ts
new file mode 100644
index 000000000..8f6d898fe
--- /dev/null
+++ b/src/client/views/global/globalScripts.ts
@@ -0,0 +1,407 @@
+import { Colors } from "browndash-components";
+import { runInAction, action } from "mobx";
+import { aggregateBounds } from "../../../Utils";
+import { Doc } from "../../../fields/Doc";
+import { Width, Height } from "../../../fields/DocSymbols";
+import { InkTool } from "../../../fields/InkField";
+import { Cast, StrCast, NumCast, BoolCast } from "../../../fields/Types";
+import { WebField } from "../../../fields/URLField";
+import { GestureUtils } from "../../../pen-gestures/GestureUtils";
+import { LinkManager } from "../../util/LinkManager";
+import { ScriptingGlobals } from "../../util/ScriptingGlobals";
+import { SelectionManager } from "../../util/SelectionManager";
+import { UndoManager } from "../../util/UndoManager";
+import { GestureOverlay } from "../GestureOverlay";
+import { InkTranscription } from "../InkTranscription";
+import { ActiveFillColor, SetActiveFillColor, ActiveIsInkMask, SetActiveIsInkMask, ActiveInkWidth, SetActiveInkWidth, ActiveInkColor, SetActiveInkColor } from "../InkingStroke";
+import { CollectionFreeFormView } from "../collections/collectionFreeForm";
+import { CollectionFreeFormDocumentView } from "../nodes/CollectionFreeFormDocumentView";
+import { WebBox } from "../nodes/WebBox";
+import { RichTextMenu } from "../nodes/formattedText/RichTextMenu";
+import { DocumentType } from "../../documents/DocumentTypes";
+
+// toggle: Set overlay status of selected document
+ScriptingGlobals.add(function setView(view: string) {
+    const selected = SelectionManager.Docs().lastElement();
+    selected ? (selected._type_collection = view) : console.log('[FontIconBox.tsx] changeView failed');
+});
+
+// toggle: Set overlay status of selected document
+ScriptingGlobals.add(function setBackgroundColor(color?: string, checkResult?: boolean) {
+    const selectedViews = SelectionManager.Views();
+    console.log(color, checkResult);
+    if (Doc.ActiveTool !== InkTool.None) {
+        if (checkResult) {
+            return ActiveFillColor();
+        }
+        SetActiveFillColor(color ?? 'transparent');
+    } else if (selectedViews.length) {
+        if (checkResult) {
+            const selView = selectedViews.lastElement();
+            const fieldKey = selView.rootDoc.type === DocumentType.INK ? 'fillColor' : 'backgroundColor';
+            const layoutFrameNumber = Cast(selView.props.docViewPath().lastElement()?.rootDoc?._currentFrame, 'number'); // frame number that container is at which determines layout frame values
+            const contentFrameNumber = Cast(selView.rootDoc?._currentFrame, 'number', layoutFrameNumber ?? null); // frame number that content is at which determines what content is displayed
+            return CollectionFreeFormDocumentView.getStringValues(selView?.rootDoc, contentFrameNumber)[fieldKey] ?? 'transparent';
+        }
+        selectedViews.forEach(dv => {
+            const fieldKey = dv.rootDoc.type === DocumentType.INK ? 'fillColor' : 'backgroundColor';
+            const layoutFrameNumber = Cast(dv.props.docViewPath().lastElement()?.rootDoc?._currentFrame, 'number'); // frame number that container is at which determines layout frame values
+            const contentFrameNumber = Cast(dv.rootDoc?._currentFrame, 'number', layoutFrameNumber ?? null); // frame number that content is at which determines what content is displayed
+            if (contentFrameNumber !== undefined) {
+                CollectionFreeFormDocumentView.setStringValues(contentFrameNumber, dv.rootDoc, { fieldKey: color });
+            } else {
+                console.log('setting color to: ', color)
+                dv.rootDoc['_' + fieldKey] = color;
+            }
+        });
+    } else {
+        const selected = SelectionManager.Docs().length ? SelectionManager.Docs() : LinkManager.currentLink ? [LinkManager.currentLink] : [];
+        if (checkResult) {
+            return selected.lastElement()?._backgroundColor ?? 'transparent';
+        }
+        selected.forEach(doc => (doc._backgroundColor = color));
+    }
+});
+
+// toggle: Set overlay status of selected document
+ScriptingGlobals.add(function setHeaderColor(color?: string, checkResult?: boolean) {
+    if (checkResult) {
+        return Doc.SharingDoc().userColor;
+    }
+    Doc.SharingDoc().userColor = undefined;
+    Doc.GetProto(Doc.SharingDoc()).userColor = color;
+    Doc.UserDoc().layout_showTitle = color === 'transparent' ? undefined : StrCast(Doc.UserDoc().layout_showTitle, 'author_date');
+});
+
+// toggle: Set overlay status of selected document
+ScriptingGlobals.add(function toggleOverlay(checkResult?: boolean) {
+    const selected = SelectionManager.Views().length ? SelectionManager.Views()[0] : undefined;
+    if (checkResult) {
+        if (NumCast(selected?.Document.z) >= 1) return Colors.MEDIUM_BLUE;
+        return 'transparent';
+    }
+    selected ? selected.props.CollectionFreeFormDocumentView?.().float() : console.log('[FontIconBox.tsx] toggleOverlay failed');
+});
+
+ScriptingGlobals.add(function showFreeform(attr: 'flashcards' | 'grid' | 'snaplines' | 'clusters' | 'arrange' | 'viewAll', checkResult?: boolean) {
+    const selected = SelectionManager.Docs().lastElement();
+    // prettier-ignore
+    const map: Map<'flashcards' | 'grid' | 'snaplines' | 'clusters' | 'arrange'| 'viewAll', { waitForRender?: boolean, checkResult: (doc:Doc) => any; setDoc: (doc:Doc) => void;}> = new Map([
+        ['grid', {
+            checkResult: (doc:Doc) => doc._freeform_backgroundGrid,
+            setDoc: (doc:Doc) => doc._freeform_backgroundGrid = !doc._freeform_backgroundGrid,
+        }],
+        ['snaplines', {
+            checkResult: (doc:Doc) => doc._freeform_snapLines,
+            setDoc: (doc:Doc) => doc._freeform_snapLines = !doc._freeform_snapLines,
+        }],
+        ['viewAll', {
+            checkResult: (doc:Doc) => doc._freeform_fitContentsToBox,
+            setDoc: (doc:Doc) => doc._freeform_fitContentsToBox = !doc._freeform_fitContentsToBox,
+        }],
+        ['clusters', {
+            waitForRender: true, // flags that undo batch should terminate after a re-render giving the script the chance to fire
+            checkResult: (doc:Doc) => doc._freeform_useClusters,
+            setDoc: (doc:Doc) => doc._freeform_useClusters = !doc._freeform_useClusters,
+        }],
+        ['arrange', {
+            waitForRender: true, // flags that undo batch should terminate after a re-render giving the script the chance to fire
+            checkResult: (doc:Doc) => doc._autoArrange,
+            setDoc: (doc:Doc) => doc._autoArrange = !doc._autoArrange,
+        }],
+        ['flashcards', {
+            checkResult: (doc:Doc) => Doc.UserDoc().defaultToFlashcards,
+            setDoc: (doc:Doc) => Doc.UserDoc().defaultToFlashcards = !Doc.UserDoc().defaultToFlashcards,
+        }],
+   ]);
+
+    if (checkResult) {
+        return map.get(attr)?.checkResult(selected) ? Colors.MEDIUM_BLUE : 'transparent';
+    }
+    const batch = map.get(attr)?.waitForRender ? UndoManager.StartBatch('set freeform attribute') : { end: () => {} };
+    SelectionManager.Docs().map(dv => map.get(attr)?.setDoc(dv));
+    setTimeout(() => batch.end(), 100);
+});
+ScriptingGlobals.add(function setFontAttr(attr: 'font' | 'fontColor' | 'highlight' | 'fontSize', value: any, checkResult?: boolean) {
+    const editorView = RichTextMenu.Instance?.TextView?.EditorView;
+    const selected = SelectionManager.Docs().lastElement();
+    // prettier-ignore
+    const map: Map<'font'|'fontColor'|'highlight'|'fontSize', { checkResult: () => any; setDoc: () => void;}> = new Map([
+        ['font', {
+            checkResult: () => RichTextMenu.Instance?.fontFamily,
+            setDoc: () => value && RichTextMenu.Instance.setFontFamily(value),
+        }],
+        ['highlight', {
+            checkResult: () =>(selected ?? Doc.UserDoc())._fontHighlight,
+            setDoc: () => value  && RichTextMenu.Instance.setHighlight(value),
+        }],
+        ['fontColor', {
+            checkResult: () => RichTextMenu.Instance?.fontColor,
+            setDoc: () => value && RichTextMenu.Instance.setColor(value),
+        }],
+        ['fontSize', {
+            checkResult: () => RichTextMenu.Instance?.fontSize.replace('px', ''),
+            setDoc: () => {
+                if (typeof value === 'number') value = value.toString();
+                if (value && Number(value).toString() === value) value += 'px';
+                RichTextMenu.Instance.setFontSize(value);
+            },
+        }],
+    ]);
+
+    if (checkResult) {
+        return map.get(attr)?.checkResult();
+    }
+    map.get(attr)?.setDoc?.();
+});
+
+type attrname = 'noAutoLink' | 'dictation' | 'bold' | 'italics' | 'underline' | 'left' | 'center' | 'right' | 'bullet' | 'decimal';
+type attrfuncs = [attrname, { checkResult: () => boolean; toggle: () => any }];
+ScriptingGlobals.add(function toggleCharStyle(charStyle: attrname, checkResult?: boolean) {
+    const textView = RichTextMenu.Instance?.TextView;
+    const editorView = textView?.EditorView;
+    // prettier-ignore
+    const alignments:attrfuncs[] = (['left','right','center'] as ("left"|"center"|"right")[]).map((where) =>
+        [ where, {      checkResult: () =>(editorView ? (RichTextMenu.Instance.textAlign ===where): (Doc.UserDoc().textAlign ===where) ? true:false),
+                        toggle: () => (editorView?.state ? RichTextMenu.Instance.align(editorView, editorView.dispatch, where):(Doc.UserDoc().textAlign = where))}]);
+    // prettier-ignore
+    const listings:attrfuncs[] = (['bullet','decimal'] as attrname[]).map(list =>
+        [ list, {       checkResult: () => (editorView ? RichTextMenu.Instance.getActiveListStyle() === list:false),
+                        toggle: () => editorView?.state && RichTextMenu.Instance.changeListType(list) }]);
+    // prettier-ignore
+    const attrs:attrfuncs[] = [
+        ['dictation', { checkResult: () => textView?._recording ? true:false,
+                        toggle: () => textView && runInAction(() => (textView._recording = !textView._recording)) }],
+        ['noAutoLink',{ checkResult: () => (editorView ? RichTextMenu.Instance.noAutoLink : false),
+                        toggle: () => editorView && RichTextMenu.Instance?.toggleNoAutoLinkAnchor()}],
+        ['bold',      { checkResult: () => (editorView ? RichTextMenu.Instance.bold : (Doc.UserDoc().fontWeight === 'bold') ? true:false),
+                        toggle: editorView ? RichTextMenu.Instance.toggleBold : () => (Doc.UserDoc().fontWeight = Doc.UserDoc().fontWeight === 'bold' ? undefined : 'bold')}],
+        ['italics',   { checkResult: () => (editorView ? RichTextMenu.Instance.italics : (Doc.UserDoc().fontStyle === 'italics') ? true:false),
+                        toggle: editorView ? RichTextMenu.Instance.toggleItalics : () => (Doc.UserDoc().fontStyle = Doc.UserDoc().fontStyle === 'italics' ? undefined : 'italics')}],
+        ['underline', { checkResult: () => (editorView ? RichTextMenu.Instance.underline : (Doc.UserDoc().textDecoration === 'underline') ? true:false),
+                        toggle: editorView ? RichTextMenu.Instance.toggleUnderline : () => (Doc.UserDoc().textDecoration = Doc.UserDoc().textDecoration === 'underline' ? undefined : 'underline') }]]
+
+    const map = new Map(attrs.concat(alignments).concat(listings));
+    if (checkResult) return map.get(charStyle)?.checkResult() ? Colors.MEDIUM_BLUE : 'transparent';
+    map.get(charStyle)?.toggle();
+});
+
+export function checkInksToGroup() {
+    // console.log("getting here to inks group");
+    if (Doc.ActiveTool === InkTool.Write) {
+        CollectionFreeFormView.collectionsWithUnprocessedInk.forEach(ffView => {
+            // TODO: nda - will probably want to go through ffView unprocessed docs and then see if any of the inksToGroup docs are in it and only use those
+            // find all inkDocs in ffView.unprocessedDocs that are within 200 pixels of each other
+            const inksToGroup = ffView.unprocessedDocs.filter(inkDoc => {
+                // console.log(inkDoc.x, inkDoc.y);
+            });
+        });
+    }
+}
+
+export function createInkGroup(inksToGroup?: Doc[], isSubGroup?: boolean) {
+    // TODO nda - if document being added to is a inkGrouping then we can just add to that group
+    if (Doc.ActiveTool === InkTool.Write) {
+        CollectionFreeFormView.collectionsWithUnprocessedInk.forEach(ffView => {
+            // TODO: nda - will probably want to go through ffView unprocessed docs and then see if any of the inksToGroup docs are in it and only use those
+            const selected = ffView.unprocessedDocs;
+            // loop through selected an get the bound
+            const bounds: { x: number; y: number; width?: number; height?: number }[] = [];
+
+            selected.map(
+                action(d => {
+                    const x = NumCast(d.x);
+                    const y = NumCast(d.y);
+                    const width = d[Width]();
+                    const height = d[Height]();
+                    bounds.push({ x, y, width, height });
+                })
+            );
+
+            const aggregBounds = aggregateBounds(bounds, 0, 0);
+            const marqViewRef = ffView._marqueeViewRef.current;
+
+            // set the vals for bounds in marqueeView
+            if (marqViewRef) {
+                marqViewRef._downX = aggregBounds.x;
+                marqViewRef._downY = aggregBounds.y;
+                marqViewRef._lastX = aggregBounds.r;
+                marqViewRef._lastY = aggregBounds.b;
+            }
+
+            selected.map(
+                action(d => {
+                    const dx = NumCast(d.x);
+                    const dy = NumCast(d.y);
+                    delete d.x;
+                    delete d.y;
+                    delete d.activeFrame;
+                    delete d._timecodeToShow; // bcz: this should be automatic somehow.. along with any other properties that were logically associated with the original collection
+                    delete d._timecodeToHide; // bcz: this should be automatic somehow.. along with any other properties that were logically associated with the original collection
+                    // calculate pos based on bounds
+                    if (marqViewRef?.Bounds) {
+                        d.x = dx - marqViewRef.Bounds.left - marqViewRef.Bounds.width / 2;
+                        d.y = dy - marqViewRef.Bounds.top - marqViewRef.Bounds.height / 2;
+                    }
+                    return d;
+                })
+            );
+            ffView.props.removeDocument?.(selected);
+            // TODO: nda - this is the code to actually get a new grouped collection
+            const newCollection = marqViewRef?.getCollection(selected, undefined, true);
+            if (newCollection) {
+                newCollection.height = newCollection[Height]();
+                newCollection.width = newCollection[Width]();
+            }
+
+            // nda - bug: when deleting a stroke before leaving writing mode, delete the stroke from unprocessed ink docs
+            newCollection && ffView.props.addDocument?.(newCollection);
+            // TODO: nda - will probably need to go through and only remove the unprocessed selected docs
+            ffView.unprocessedDocs = [];
+
+            InkTranscription.Instance.transcribeInk(newCollection, selected, false);
+        });
+    }
+    CollectionFreeFormView.collectionsWithUnprocessedInk.clear();
+}
+
+function setActiveTool(tool: InkTool | GestureUtils.Gestures, keepPrim: boolean, checkResult?: boolean) {
+    InkTranscription.Instance?.createInkGroup();
+    if (checkResult) {
+        return (Doc.ActiveTool === tool && !GestureOverlay.Instance?.InkShape) || GestureOverlay.Instance?.InkShape === tool
+            ? GestureOverlay.Instance?.KeepPrimitiveMode || ![GestureUtils.Gestures.Circle, GestureUtils.Gestures.Line, GestureUtils.Gestures.Rectangle].includes(tool as GestureUtils.Gestures)
+                ? Colors.MEDIUM_BLUE
+                : Colors.MEDIUM_BLUE_ALT
+            : 'transparent';
+    }
+    runInAction(() => {
+        if (GestureOverlay.Instance) {
+            GestureOverlay.Instance.KeepPrimitiveMode = keepPrim;
+        }
+        if (Object.values(GestureUtils.Gestures).includes(tool as any)) {
+            if (GestureOverlay.Instance.InkShape === tool && !keepPrim) {
+                Doc.ActiveTool = InkTool.None;
+                GestureOverlay.Instance.InkShape = undefined;
+            } else {
+                Doc.ActiveTool = InkTool.Pen;
+                GestureOverlay.Instance.InkShape = tool as GestureUtils.Gestures;
+            }
+        } else if (tool) {
+            // pen or eraser
+            if (Doc.ActiveTool === tool && !GestureOverlay.Instance.InkShape && !keepPrim) {
+                Doc.ActiveTool = InkTool.None;
+            } else {
+                Doc.ActiveTool = tool as any;
+                GestureOverlay.Instance.InkShape = undefined;
+            }
+        } else {
+            Doc.ActiveTool = InkTool.None;
+        }
+    });
+}
+
+ScriptingGlobals.add(setActiveTool, 'sets the active ink tool mode');
+
+// toggle: Set overlay status of selected document
+ScriptingGlobals.add(function setInkProperty(option: 'inkMask' | 'fillColor' | 'strokeWidth' | 'strokeColor', value: any, checkResult?: boolean) {
+    const selected = SelectionManager.Docs().lastElement();
+    // prettier-ignore
+    const map: Map<'inkMask' | 'fillColor' | 'strokeWidth' | 'strokeColor', { checkResult: () => any; setInk: (doc: Doc) => void; setMode: () => void }> = new Map([
+        ['inkMask', {
+            checkResult: () => ((selected?.type === DocumentType.INK ? BoolCast(selected.stroke_isInkMask) : ActiveIsInkMask()) ? Colors.MEDIUM_BLUE : 'transparent'),
+            setInk: (doc: Doc) => (doc.stroke_isInkMask = !doc.stroke_isInkMask),
+            setMode: () => selected?.type !== DocumentType.INK && SetActiveIsInkMask(!ActiveIsInkMask()),
+        }],
+        ['fillColor', {
+            checkResult: () => (selected?.type === DocumentType.INK ? StrCast(selected.fillColor) : ActiveFillColor() ?? "transparent"),
+            setInk: (doc: Doc) => (doc.fillColor = StrCast(value)),
+            setMode: () => SetActiveFillColor(StrCast(value)),
+        }],
+        [ 'strokeWidth', {
+            checkResult: () => (selected?.type === DocumentType.INK ? NumCast(selected.stroke_width) : ActiveInkWidth()),
+            setInk: (doc: Doc) => (doc.stroke_width = NumCast(value)),
+            setMode: () => SetActiveInkWidth(value.toString()),
+        }],
+        ['strokeColor', {
+            checkResult: () => (selected?.type === DocumentType.INK ? StrCast(selected.color) : ActiveInkColor()),
+            setInk: (doc: Doc) => (doc.color = String(value)),
+            setMode: () => SetActiveInkColor(StrCast(value)),
+        }],
+    ]);
+
+    if (checkResult) {
+        return map.get(option)?.checkResult();
+    }
+    map.get(option)?.setMode();
+    SelectionManager.Docs()
+        .filter(doc => doc.type === DocumentType.INK)
+        .map(doc => map.get(option)?.setInk(doc));
+});
+
+/** WEB
+ *      webSetURL
+ **/
+ScriptingGlobals.add(function webSetURL(url: string, checkResult?: boolean) {
+    const selected = SelectionManager.Views().lastElement();
+    if (selected?.rootDoc.type === DocumentType.WEB) {
+        if (checkResult) {
+            return StrCast(selected.rootDoc.data, Cast(selected.rootDoc.data, WebField, null)?.url?.href);
+        }
+        selected.ComponentView?.setData?.(url);
+        //selected.rootDoc.data = new WebField(url);
+    }
+});
+ScriptingGlobals.add(function webForward(checkResult?: boolean) {
+    const selected = SelectionManager.Views().lastElement()?.ComponentView as WebBox;
+    if (checkResult) {
+        return selected?.forward(checkResult) ? undefined : 'lightGray';
+    }
+    selected?.forward();
+});
+ScriptingGlobals.add(function webBack(checkResult?: boolean) {
+    const selected = SelectionManager.Views().lastElement()?.ComponentView as WebBox;
+    if (checkResult) {
+        return selected?.back(checkResult) ? undefined : 'lightGray';
+    }
+    selected?.back();
+});
+
+/** Schema
+ *      toggleSchemaPreview
+ **/
+ScriptingGlobals.add(function toggleSchemaPreview(checkResult?: boolean) {
+    const selected = SelectionManager.Docs().lastElement();
+    if (checkResult && selected) {
+        const result: boolean = NumCast(selected.schema_previewWidth) > 0;
+        if (result) return Colors.MEDIUM_BLUE;
+        else return 'transparent';
+    } else if (selected) {
+        if (NumCast(selected.schema_previewWidth) > 0) {
+            selected.schema_previewWidth = 0;
+        } else {
+            selected.schema_previewWidth = 200;
+        }
+    }
+});
+ScriptingGlobals.add(function toggleSingleLineSchema(checkResult?: boolean) {
+    const selected = SelectionManager.Docs().lastElement();
+    if (checkResult && selected) {
+        return NumCast(selected._schema_singleLine) > 0 ? Colors.MEDIUM_BLUE : 'transparent';
+    }
+    if (selected) {
+        selected._schema_singleLine = !selected._schema_singleLine;
+    }
+});
+
+/** STACK
+ *      groupBy
+ */
+ScriptingGlobals.add(function setGroupBy(key: string, checkResult?: boolean) {
+    SelectionManager.Docs().map(doc => (doc._text_fontFamily = key));
+    const editorView = RichTextMenu.Instance.TextView?.EditorView;
+    if (checkResult) {
+        return StrCast((editorView ? RichTextMenu.Instance : Doc.UserDoc()).fontFamily);
+    }
+    if (editorView) RichTextMenu.Instance.setFontFamily(key);
+    else Doc.UserDoc().fontFamily = key;
+});
diff --git a/src/client/views/nodes/button/ButtonInterface.ts b/src/client/views/nodes/button/ButtonInterface.ts
deleted file mode 100644
index 0aa2ac8e1..000000000
--- a/src/client/views/nodes/button/ButtonInterface.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-import { Doc } from "../../../../fields/Doc";
-import { IconProp } from "@fortawesome/fontawesome-svg-core";
-import { ButtonType } from "./FontIconBox";
-
-export interface IButtonProps {
-    type: string | ButtonType;
-    rootDoc: Doc;
-    label: any;
-    icon: IconProp;
-    color: string;
-    backgroundColor: string;
-}
\ No newline at end of file
diff --git a/src/client/views/nodes/button/FontIconBadge.scss b/src/client/views/nodes/button/FontIconBadge.scss
deleted file mode 100644
index 78f506e57..000000000
--- a/src/client/views/nodes/button/FontIconBadge.scss
+++ /dev/null
@@ -1,11 +0,0 @@
-.fontIconBadge {
-    background: red;
-    width: 15px;
-    height: 15px;
-    top: 8px;
-    display: block;
-    position: absolute;
-    right: 5;
-    border-radius: 50%;
-    text-align: center;
-}
\ No newline at end of file
diff --git a/src/client/views/nodes/button/FontIconBadge.tsx b/src/client/views/nodes/button/FontIconBadge.tsx
deleted file mode 100644
index b50588ce2..000000000
--- a/src/client/views/nodes/button/FontIconBadge.tsx
+++ /dev/null
@@ -1,37 +0,0 @@
-import { observer } from 'mobx-react';
-import * as React from 'react';
-import './FontIconBadge.scss';
-
-interface FontIconBadgeProps {
-    value: string | undefined;
-}
-
-@observer
-export class FontIconBadge extends React.Component<FontIconBadgeProps> {
-    _notifsRef = React.createRef<HTMLDivElement>();
-
-    // onPointerDown = (e: React.PointerEvent) => {
-    //     setupMoveUpEvents(this, e,
-    //         (e: PointerEvent) => {
-    //             const dragData = new DragManager.DocumentDragData([this.props.collection!]);
-    //             DragManager.StartDocumentDrag([this._notifsRef.current!], dragData, e.x, e.y);
-    //             return true;
-    //         },
-    //         returnFalse, emptyFunction, false);
-    // }
-
-    render() {
-        if (this.props.value === undefined) return null;
-        return (
-            <div className="fontIconBadge-container" ref={this._notifsRef}>
-                <div
-                    className="fontIconBadge"
-                    style={{ display: 'initial' }}
-                    // onPointerDown={this.onPointerDown}
-                >
-                    {this.props.value}
-                </div>
-            </div>
-        );
-    }
-}
diff --git a/src/client/views/nodes/button/FontIconBox.tsx b/src/client/views/nodes/button/FontIconBox.tsx
index d181de8d0..e31407f4b 100644
--- a/src/client/views/nodes/button/FontIconBox.tsx
+++ b/src/client/views/nodes/button/FontIconBox.tsx
@@ -1,39 +1,23 @@
 import { IconProp } from '@fortawesome/fontawesome-svg-core';
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { Tooltip } from '@material-ui/core';
-import { ColorPicker, Dropdown, DropdownType, IconButton, IListItemProps, Size, Toggle, ToggleType, Type } from 'browndash-components';
-import { action, computed, observable, runInAction } from 'mobx';
+import { Button, ColorPicker, Dropdown, DropdownType, EditableText, IconButton, IListItemProps, NumberDropdown, NumberDropdownType, Size, Toggle, ToggleType, Type } from 'browndash-components';
+import { action, computed, observable } from 'mobx';
 import { observer } from 'mobx-react';
 import * as React from 'react';
-import { ColorState, SketchPicker } from 'react-color';
-import * as fa from 'react-icons/fa';
 import { Doc, StrListCast } from '../../../../fields/Doc';
-import { Height, Width } from '../../../../fields/DocSymbols';
-import { InkTool } from '../../../../fields/InkField';
 import { ScriptField } from '../../../../fields/ScriptField';
 import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from '../../../../fields/Types';
-import { WebField } from '../../../../fields/URLField';
-import { GestureUtils } from '../../../../pen-gestures/GestureUtils';
-import { aggregateBounds, Utils } from '../../../../Utils';
 import { CollectionViewType, DocumentType } from '../../../documents/DocumentTypes';
-import { LinkManager } from '../../../util/LinkManager';
-import { ScriptingGlobals } from '../../../util/ScriptingGlobals';
 import { SelectionManager } from '../../../util/SelectionManager';
-import { undoable, undoBatch, UndoManager } from '../../../util/UndoManager';
-import { CollectionFreeFormView } from '../../collections/collectionFreeForm';
+import { undoable, UndoManager } from '../../../util/UndoManager';
 import { ContextMenu } from '../../ContextMenu';
 import { DocComponent } from '../../DocComponent';
 import { EditableView } from '../../EditableView';
-import { GestureOverlay } from '../../GestureOverlay';
 import { Colors } from '../../global/globalEnums';
-import { ActiveFillColor, ActiveInkColor, ActiveInkWidth, ActiveIsInkMask, SetActiveFillColor, SetActiveInkColor, SetActiveInkWidth, SetActiveIsInkMask } from '../../InkingStroke';
-import { InkTranscription } from '../../InkTranscription';
 import { StyleProp } from '../../StyleProvider';
 import { FieldView, FieldViewProps } from '.././FieldView';
-import { CollectionFreeFormDocumentView } from '../CollectionFreeFormDocumentView';
 import { OpenWhere } from '../DocumentView';
 import { RichTextMenu } from '../formattedText/RichTextMenu';
-import { WebBox } from '../WebBox';
 import './FontIconBox.scss';
 
 export enum ButtonType {
@@ -136,116 +120,35 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
     /**
      * Number button
      */
-    @computed get numberSliderButton() {
+    @computed get numberDropdown() {
+        let type: NumberDropdownType;
+        switch(this.type) {
+            case ButtonType.NumberDropdownButton: 
+                type = 'dropdown'
+                break;
+            case ButtonType.NumberInlineButton:
+                type = 'input'
+                break;
+            case ButtonType.NumberSliderButton:
+            default:
+                type = 'slider'
+                break;
+        }
         const numScript = (value?: number) => ScriptCast(this.rootDoc.script).script.run({ self: this.rootDoc, value, _readOnly_: value === undefined });
+        const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color);
         // Script for checking the outcome of the toggle
-        const checkResult = Number(numScript().result ?? 0).toPrecision(NumCast(this.dataDoc.numPrecision, 3));
+        const checkResult = Number(Number(numScript().result ?? 0).toPrecision(NumCast(this.dataDoc.numPrecision, 3)));
         const label = !FontIconBox.GetShowLabels() ? null : <div className="fontIconBox-label">{this.label}</div>;
 
-        const dropdown = (
-            <div className="menuButton-dropdownBox" onPointerDown={e => e.stopPropagation()}>
-                <input
-                    className="menu-slider"
-                    type="range"
-                    step="1"
-                    min={NumCast(this.rootDoc.numBtnMin, 0)}
-                    max={NumCast(this.rootDoc.numBtnMax, 100)}
-                    //readOnly={true}
-                    value={checkResult}
-                    onPointerDown={() => (this._batch = UndoManager.StartBatch('num slider changing'))}
-                    onPointerUp={() => this._batch?.end()}
-                    onChange={undoable(e => {
-                        e.stopPropagation();
-                        numScript(Number(e.target.value));
-                    }, 'set num value')}
-                />
-            </div>
-        );
-        return (
-            <div
-                className="menuButton numBtn slider"
-                onPointerDown={e => e.stopPropagation()}
-                onClick={action(() => {
-                    this.rootDoc.dropDownOpen = !this.rootDoc.dropDownOpen;
-                    this.noTooltip = this.rootDoc.dropDownOpen;
-                    Doc.UnBrushAllDocs();
-                })}>
-                {checkResult}
-                {label}
-                {this.rootDoc.dropDownOpen ? dropdown : null}
-            </div>
-        );
-    }
-    /**
-     * Number button
-     */
-    @computed get numberDropdownButton() {
-        const numScript = (value?: number) => ScriptCast(this.rootDoc.script)?.script.run({ self: this.rootDoc, value, _readOnly_: value === undefined });
-
-        const checkResult = Number(numScript().result ?? 0).toPrecision(NumCast(this.dataDoc.numPrecision, 3));
-
-        const items: number[] = [];
-        for (let i = 0; i < 100; i += 2) items.push(i);
-
-        const list = items.map(value => {
-            return (
-                <div
-                    className="list-item"
-                    key={`${value}`}
-                    style={{
-                        backgroundColor: value.toString() === checkResult ? Colors.LIGHT_BLUE : undefined,
-                    }}
-                    onClick={undoable(value => numScript(value), `${this.rootDoc.title} button set from list`)}>
-                    {value}
-                </div>
-            );
-        });
-        return (
-            <div className="menuButton numBtn list">
-                <div className="button" onClick={undoable(e => numScript(Number(checkResult) - 1), `${this.rootDoc.title} decrement value`)}>
-                    <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon="minus" />
-                </div>
-                <div
-                    className={`button ${'number'}`}
-                    onPointerDown={e => {
-                        e.stopPropagation();
-                        e.preventDefault();
-                    }}
-                    onClick={action(() => {
-                        this.rootDoc.dropDownOpen = !this.rootDoc.dropDownOpen;
-                        this.noTooltip = this.rootDoc.dropDownOpen;
-                        Doc.UnBrushAllDocs();
-                    })}>
-                    <input style={{ width: 30 }} className="button-input" type="number" value={checkResult} readOnly={true} onChange={undoable(e => numScript(Number(e.target.value)), `${this.rootDoc.title} button set value`)} />
-                </div>
-                <div className={`button`} onClick={undoable(e => numScript(Number(checkResult) + 1), `${this.rootDoc.title} increment value`)}>
-                    <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={'plus'} />
-                </div>
-
-                {this.rootDoc.dropDownOpen ? (
-                    <div>
-                        <div className="menuButton-dropdownList" style={{ left: '25%' }}>
-                            {list}
-                        </div>
-                        <div
-                            className="dropbox-background"
-                            onClick={action(e => {
-                                e.stopPropagation();
-                                this.rootDoc.dropDownOpen = false;
-                                this.noTooltip = false;
-                                Doc.UnBrushAllDocs();
-                            })}
-                        />
-                    </div>
-                ) : null}
-            </div>
-        );
-    }
-    /**
-     * Number button
-     */
-    @computed get numberInlineButton() {
-        return <div />;
+        return <NumberDropdown 
+            color={color} 
+            numberDropdownType={type} 
+            showPlusMinus={false} 
+            min={NumCast(this.rootDoc.numBtnMin, 0)}
+            max={NumCast(this.rootDoc.numBtnMax, 100)}
+            number={checkResult} 
+            setNumber={undoable(value => numScript(value), `${this.rootDoc.title} button set from list`)}
+        />
     }
 
     /**
@@ -296,18 +199,22 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
         try {
             if (script?.script.originalScript.startsWith('setView')) {
                 const selected = SelectionManager.Docs().lastElement();
+                console.log('selected')
                 if (selected) {
                     if (StrCast(selected.type) === DocumentType.COL) {
                         text = StrCast(selected._type_collection);
                     } else {
+                        console.log("doc selected", selected.title)
                         dropdown = false;
                         text = selected.type === DocumentType.RTF ? 'Text' : StrCast(selected.type);
                         icon = Doc.toIcon(selected);
+                        return <div>Hi!</div>
                     }
                 } else {
                     dropdown = false;
                     icon = 'globe-asia';
                     text = 'User Default';
+                    return <div>Hi!</div>
                 }
                 noviceList = [CollectionViewType.Freeform, CollectionViewType.Schema, CollectionViewType.Stacking, CollectionViewType.NoteTaking];
             } else text = StrCast((RichTextMenu.Instance?.TextView?.EditorView ? RichTextMenu.Instance : Doc.UserDoc()).fontFamily);
@@ -323,79 +230,32 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
             .map(value => (
                 {
                     text: value,
+                    val: value,
                     style: { fontFamily: value },
                     onClick: undoable(() => script.script.run({ self: this.rootDoc, value }), value)
                     // shortcut: '#',
                 }
             ));
 
-        const label =
-            !this.label || !FontIconBox.GetShowLabels() ? null : (
-                <div className="fontIconBox-label" style={{ bottom: 0, position: 'absolute', color: color, backgroundColor: backgroundColor }}>
-                    {this.label}
-                </div>
-            );
 
         return (
-            <Dropdown selected={{text: text}} color={Colors.WHITE} type={Type.PRIM} dropdownType={DropdownType.SELECT} items={list}/>
+            <Dropdown 
+                selectedVal={text}
+                setSelectedVal={undoable((val) => script.script.run({ self: this.rootDoc, val }), `dropdown select ${this.label}`)}
+                color={Colors.WHITE} 
+                type={Type.PRIM} 
+                dropdownType={DropdownType.SELECT} 
+                items={list}
+                tooltip={this.label}
+            />
         )
-
-        return (
-            <div
-                className={`menuButton ${this.type} ${active}`}
-                style={{ backgroundColor: this.rootDoc.dropDownOpen ? Colors.MEDIUM_BLUE : backgroundColor, color: color, display: dropdown ? undefined : 'flex' }}
-                onClick={
-                    dropdown
-                        ? action(() => {
-                              this.rootDoc.dropDownOpen = !this.rootDoc.dropDownOpen;
-                              this.noTooltip = this.rootDoc.dropDownOpen;
-                              Doc.UnBrushAllDocs();
-                          })
-                        : undefined
-                }>
-                {dropdown ? null : <FontAwesomeIcon style={{ marginLeft: 5 }} className={`fontIconBox-icon-${this.type}`} icon={icon} color={color} />}
-                <div className="menuButton-dropdown-header">{text && text[0].toUpperCase() + text.slice(1)}</div>
-                {label}
-                {!dropdown ? null : (
-                    <div className="menuButton-dropDown">
-                        <FontAwesomeIcon icon={icon} color={color} size="sm" />
-                    </div>
-                )}
-                {this.rootDoc.dropDownOpen ? (
-                    <div>
-                        <div className="menuButton-dropdownList" style={{ left: 0 }}>
-                            {list}
-                        </div>
-                        <div
-                            className="dropbox-background"
-                            onClick={action(e => {
-                                e.stopPropagation();
-                                this.rootDoc.dropDownOpen = false;
-                                this.noTooltip = false;
-                                Doc.UnBrushAllDocs();
-                            })}
-                        />
-                    </div>
-                ) : null}
-            </div>
-        );
     }
 
-    @observable colorPickerClosed: boolean = true;
+
     @computed get colorScript() {
         return ScriptCast(this.rootDoc.script);
     }
 
-    colorPicker = (curColor: string) => {
-        const change = (value: ColorState, ev: MouseEvent) => {
-            ev.preventDefault();
-            ev.stopPropagation();
-            const s = this.colorScript;
-            s && undoBatch(() => s.script.run({ self: this.rootDoc, value: Utils.colorString(value), _readOnly_: false }).result)();
-        };
-        const presets = ['#D0021B', '#F5A623', '#F8E71C', '#8B572A', '#7ED321', '#417505', '#9013FE', '#4A90E2', '#50E3C2', '#B8E986', '#000000', '#4A4A4A', '#9B9B9B', '#FFFFFF', '#f1efeb', 'transparent'];
-        return <SketchPicker onChange={change as any /* SketchPicker passes the mouse event to the callback, but the type system doesn't know that */} color={curColor} presetColors={presets} />;
-    };
     /**
      * Color button
      */
@@ -405,61 +265,20 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
         const curColor = this.colorScript?.script.run({ self: this.rootDoc, value: undefined, _readOnly_: true }).result ?? 'transparent';
         const tooltip: string = StrCast(this.rootDoc.toolTip);
 
-        const label =
-            !this.label || !FontIconBox.GetShowLabels() ? null : (
-                <div className="fontIconBox-label" style={{ color, backgroundColor }}>
-                    {this.label}
-                </div>
-            );
-        
         return (
             <ColorPicker 
-                onChange={(e) => {
-                    this.colorPickerClosed = !this.colorPickerClosed;
-                    setTimeout(() => Doc.UnBrushAllDocs());
-                    e.stopPropagation();
+                setSelectedColor={(value) => {
+                    const s = this.colorScript;
+                    s && undoable(() => s.script.run({ self: this.rootDoc, value: value, _readOnly_: false }).result, `Set ${tooltip} to ${value}`)();
                 }}
-                color={color}
+                selectedColor={curColor}
                 type={Type.PRIM}
+                color={color}
                 icon={this.Icon(color)!}
                 tooltip={tooltip}
+                label={this.label}
             />
         )
-
-        return (
-            <div
-                className={`menuButton ${this.type + (FontIconBox.GetShowLabels() ? 'Label' : '')} ${this.colorPickerClosed}`}
-                style={{ color: color, borderBottomLeftRadius: this.dropdown ? 0 : undefined }}
-                onClick={action(e => {
-                    this.colorPickerClosed = !this.colorPickerClosed;
-                    this.noTooltip = !this.colorPickerClosed;
-                    setTimeout(() => Doc.UnBrushAllDocs());
-                    e.stopPropagation();
-                })}
-                onPointerDown={e => e.stopPropagation()}>
-                {this.Icon(color)}
-                <div className="colorButton-color" style={{ backgroundColor: curColor }} />
-                {label}
-                {/* {dropdownCaret} */}
-                {this.colorPickerClosed ? null : (
-                    <div>
-                        <div className="menuButton-dropdownBox" onPointerDown={e => e.stopPropagation()} onPointerUp={e => e.stopPropagation()} onClick={e => e.stopPropagation()}>
-                            {this.colorPicker(curColor)}
-                        </div>
-                        <div
-                            className="dropbox-background"
-                            onPointerDown={action(e => {
-                                e.preventDefault();
-                                e.stopPropagation();
-                                this.colorPickerClosed = true;
-                                this.noTooltip = false;
-                                Doc.UnBrushAllDocs();
-                            })}
-                        />
-                    </div>
-                )}
-            </div>
-        );
     }
 
     @computed get toggleButton() {
@@ -498,6 +317,11 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
         const checkResult = script?.script.run({ value: '', _readOnly_: true }).result;
 
         const setValue = (value: string, shiftDown?: boolean): boolean => script?.script.run({ value, _readOnly_: false }).result;
+        
+        return <EditableText 
+            editing={false} onEdit={() => {}} setEditing={(editing: boolean) => {}}            
+        />
+        
         return (
             <div className="menuButton editableText">
                 <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={'lock'} />
@@ -514,78 +338,39 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
         const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor);
         const tooltip: string = StrCast(this.rootDoc.toolTip);
 
-        const label = (noBackground: boolean = false) =>
-            !this.label || !FontIconBox.GetShowLabels() ? null : (
-                <div className="fontIconBox-label" style={{ color, backgroundColor: noBackground ? 'transparent' : backgroundColor }}>
-                    {this.label}
-                </div>
-            );
         // TODO:glr Add label of button type
         let button: JSX.Element = this.defaultButton;
-
         // prettier-ignore
         switch (this.type) {
-            case ButtonType.EditableText: return this.editableText;
+            case ButtonType.EditableText: 
+                button = this.editableText;
+                break;
             case ButtonType.DropdownList:
-                let script = ScriptCast(this.rootDoc.script);
-                let noviceList: string[] = [];
-                let text: string | undefined;
-                let dropdown = true;
-                let icon: IconProp = 'caret-down';
-                try {
-                    if (script?.script.originalScript.startsWith('setView')) {
-                        const selected = SelectionManager.Docs().lastElement();
-                        if (selected) {
-                            if (StrCast(selected.type) === DocumentType.COL) {
-                                text = StrCast(selected._type_collection);
-                            } else {
-                                dropdown = false;
-                                text = selected.type === DocumentType.RTF ? 'Text' : StrCast(selected.type);
-                                icon = Doc.toIcon(selected);
-                            }
-                        } else {
-                            dropdown = false;
-                            icon = 'globe-asia';
-                            text = 'User Default';
-                        }
-                        noviceList = [CollectionViewType.Freeform, CollectionViewType.Schema, CollectionViewType.Stacking, CollectionViewType.NoteTaking];
-                    } else text = StrCast((RichTextMenu.Instance?.TextView?.EditorView ? RichTextMenu.Instance : Doc.UserDoc()).fontFamily);
-                } catch (e) {
-                    console.log(e);
-                } 
-                // Get items to place into the list
-                const list: IListItemProps[] = this.buttonList
-                .filter(value => !Doc.noviceMode || !noviceList.length || noviceList.includes(value))
-                .map(value => (
-                    {
-                        text: value,
-                        style: { fontFamily: value },
-                        onClick: undoable(() => script.script.run({ self: this.rootDoc, value }), value)
-                        // shortcut: '#',
-                    }
-                ));
-                button = <Dropdown selected={{text: text}} color={Colors.WHITE} type={Type.PRIM} dropdownType={DropdownType.SELECT} items={list}/>
+                button = this.dropdownListButton;
+                break;
+            case ButtonType.ColorButton: 
+                button = this.colorButton; 
+                break;
+            case ButtonType.NumberDropdownButton: 
+            case ButtonType.NumberInlineButton:
+            case ButtonType.NumberSliderButton: 
+                button = this.numberDropdown; 
+                break;
+            case ButtonType.DropdownButton: 
+                button = this.dropdownButton; 
                 break;
-            case ButtonType.ColorButton: button = this.colorButton; break;
-            case ButtonType.NumberDropdownButton: button = this.numberDropdownButton; break;
-            case ButtonType.NumberInlineButton: button = this.numberInlineButton; break;
-            case ButtonType.NumberSliderButton: button = this.numberSliderButton; break;
-            case ButtonType.DropdownButton: button = this.dropdownButton; break;
             case ButtonType.ToggleButton: button = this.toggleButton; break;
             case ButtonType.TextButton: 
-                    // Script for checking the outcome of the toggle
-                    script = ScriptCast(this.rootDoc.script);
-                    const checkResult = script?.script.run({ _readOnly_: true }).result;
-                    button = (
-                    <div className={`menuButton ${this.type}`} style={{ color, backgroundColor:checkResult ?? backgroundColor, opacity: 1, gridAutoColumns: `${NumCast(this.rootDoc._height)} auto` }}>
-                        {this.Icon(color)}
-                        {StrCast(this.rootDoc.buttonText) ? <div className="button-text">{StrCast(this.rootDoc.buttonText)}</div> : null}
-                        {label()}
-                    </div>
+                // Script for checking the outcome of the toggle
+                const script = ScriptCast(this.rootDoc.script);
+                const checkResult = script?.script.run({ _readOnly_: true }).result;
+                button = (
+                    <Button tooltip={tooltip} color={checkResult ?? backgroundColor} icon={this.Icon(color)!} text={StrCast(this.rootDoc.buttonText)} label={this.label}/>
                 );
                 break;
             case ButtonType.ClickButton:
-            case ButtonType.ToolButton: button = (
+            case ButtonType.ToolButton: 
+                button = (
                     <IconButton tooltip={tooltip} color={color} icon={this.Icon(color)!} label={this.label}/>
                 );
                 break;
@@ -598,387 +383,3 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
         return button;
     }
 }
-
-// toggle: Set overlay status of selected document
-ScriptingGlobals.add(function setView(view: string) {
-    const selected = SelectionManager.Docs().lastElement();
-    selected ? (selected._type_collection = view) : console.log('[FontIconBox.tsx] changeView failed');
-});
-
-// toggle: Set overlay status of selected document
-ScriptingGlobals.add(function setBackgroundColor(color?: string, checkResult?: boolean) {
-    const selectedViews = SelectionManager.Views();
-    if (Doc.ActiveTool !== InkTool.None) {
-        if (checkResult) {
-            return ActiveFillColor();
-        }
-        SetActiveFillColor(color ?? 'transparent');
-    } else if (selectedViews.length) {
-        if (checkResult) {
-            const selView = selectedViews.lastElement();
-            const fieldKey = selView.rootDoc.type === DocumentType.INK ? 'fillColor' : 'backgroundColor';
-            const layoutFrameNumber = Cast(selView.props.docViewPath().lastElement()?.rootDoc?._currentFrame, 'number'); // frame number that container is at which determines layout frame values
-            const contentFrameNumber = Cast(selView.rootDoc?._currentFrame, 'number', layoutFrameNumber ?? null); // frame number that content is at which determines what content is displayed
-            return CollectionFreeFormDocumentView.getStringValues(selView?.rootDoc, contentFrameNumber)[fieldKey] ?? 'transparent';
-        }
-        selectedViews.forEach(dv => {
-            const fieldKey = dv.rootDoc.type === DocumentType.INK ? 'fillColor' : 'backgroundColor';
-            const layoutFrameNumber = Cast(dv.props.docViewPath().lastElement()?.rootDoc?._currentFrame, 'number'); // frame number that container is at which determines layout frame values
-            const contentFrameNumber = Cast(dv.rootDoc?._currentFrame, 'number', layoutFrameNumber ?? null); // frame number that content is at which determines what content is displayed
-            if (contentFrameNumber !== undefined) {
-                CollectionFreeFormDocumentView.setStringValues(contentFrameNumber, dv.rootDoc, { fieldKey: color });
-            } else {
-                dv.rootDoc['_' + fieldKey] = color;
-            }
-        });
-    } else {
-        const selected = SelectionManager.Docs().length ? SelectionManager.Docs() : LinkManager.currentLink ? [LinkManager.currentLink] : [];
-        if (checkResult) {
-            return selected.lastElement()?._backgroundColor ?? 'transparent';
-        }
-        selected.forEach(doc => (doc._backgroundColor = color));
-    }
-});
-
-// toggle: Set overlay status of selected document
-ScriptingGlobals.add(function setHeaderColor(color?: string, checkResult?: boolean) {
-    if (checkResult) {
-        return Doc.SharingDoc().userColor;
-    }
-    Doc.SharingDoc().userColor = undefined;
-    Doc.GetProto(Doc.SharingDoc()).userColor = color;
-    Doc.UserDoc().layout_showTitle = color === 'transparent' ? undefined : StrCast(Doc.UserDoc().layout_showTitle, 'author_date');
-});
-
-// toggle: Set overlay status of selected document
-ScriptingGlobals.add(function toggleOverlay(checkResult?: boolean) {
-    const selected = SelectionManager.Views().length ? SelectionManager.Views()[0] : undefined;
-    if (checkResult) {
-        if (NumCast(selected?.Document.z) >= 1) return Colors.MEDIUM_BLUE;
-        return 'transparent';
-    }
-    selected ? selected.props.CollectionFreeFormDocumentView?.().float() : console.log('[FontIconBox.tsx] toggleOverlay failed');
-});
-
-ScriptingGlobals.add(function showFreeform(attr: 'flashcards' | 'grid' | 'snaplines' | 'clusters' | 'arrange' | 'viewAll', checkResult?: boolean) {
-    const selected = SelectionManager.Docs().lastElement();
-    // prettier-ignore
-    const map: Map<'flashcards' | 'grid' | 'snaplines' | 'clusters' | 'arrange'| 'viewAll', { waitForRender?: boolean, checkResult: (doc:Doc) => any; setDoc: (doc:Doc) => void;}> = new Map([
-        ['grid', {
-            checkResult: (doc:Doc) => doc._freeform_backgroundGrid,
-            setDoc: (doc:Doc) => doc._freeform_backgroundGrid = !doc._freeform_backgroundGrid,
-        }],
-        ['snaplines', {
-            checkResult: (doc:Doc) => doc._freeform_snapLines,
-            setDoc: (doc:Doc) => doc._freeform_snapLines = !doc._freeform_snapLines,
-        }],
-        ['viewAll', {
-            checkResult: (doc:Doc) => doc._freeform_fitContentsToBox,
-            setDoc: (doc:Doc) => doc._freeform_fitContentsToBox = !doc._freeform_fitContentsToBox,
-        }],
-        ['clusters', {
-            waitForRender: true, // flags that undo batch should terminate after a re-render giving the script the chance to fire
-            checkResult: (doc:Doc) => doc._freeform_useClusters,
-            setDoc: (doc:Doc) => doc._freeform_useClusters = !doc._freeform_useClusters,
-        }],
-        ['arrange', {
-            waitForRender: true, // flags that undo batch should terminate after a re-render giving the script the chance to fire
-            checkResult: (doc:Doc) => doc._autoArrange,
-            setDoc: (doc:Doc) => doc._autoArrange = !doc._autoArrange,
-        }],
-        ['flashcards', {
-            checkResult: (doc:Doc) => Doc.UserDoc().defaultToFlashcards,
-            setDoc: (doc:Doc) => Doc.UserDoc().defaultToFlashcards = !Doc.UserDoc().defaultToFlashcards,
-        }],
-   ]);
-
-    if (checkResult) {
-        return map.get(attr)?.checkResult(selected) ? Colors.MEDIUM_BLUE : 'transparent';
-    }
-    const batch = map.get(attr)?.waitForRender ? UndoManager.StartBatch('set freeform attribute') : { end: () => {} };
-    SelectionManager.Docs().map(dv => map.get(attr)?.setDoc(dv));
-    setTimeout(() => batch.end(), 100);
-});
-ScriptingGlobals.add(function setFontAttr(attr: 'font' | 'fontColor' | 'highlight' | 'fontSize', value: any, checkResult?: boolean) {
-    const editorView = RichTextMenu.Instance?.TextView?.EditorView;
-    const selected = SelectionManager.Docs().lastElement();
-    // prettier-ignore
-    const map: Map<'font'|'fontColor'|'highlight'|'fontSize', { checkResult: () => any; setDoc: () => void;}> = new Map([
-        ['font', {
-            checkResult: () => RichTextMenu.Instance?.fontFamily,
-            setDoc: () => value && RichTextMenu.Instance.setFontFamily(value),
-        }],
-        ['highlight', {
-            checkResult: () =>(selected ?? Doc.UserDoc())._fontHighlight,
-            setDoc: () => value  && RichTextMenu.Instance.setHighlight(value),
-        }],
-        ['fontColor', {
-            checkResult: () => RichTextMenu.Instance?.fontColor,
-            setDoc: () => value && RichTextMenu.Instance.setColor(value),
-        }],
-        ['fontSize', {
-            checkResult: () => RichTextMenu.Instance?.fontSize.replace('px', ''),
-            setDoc: () => {
-                if (typeof value === 'number') value = value.toString();
-                if (value && Number(value).toString() === value) value += 'px';
-                RichTextMenu.Instance.setFontSize(value);
-            },
-        }],
-    ]);
-
-    if (checkResult) {
-        return map.get(attr)?.checkResult();
-    }
-    map.get(attr)?.setDoc?.();
-});
-
-type attrname = 'noAutoLink' | 'dictation' | 'bold' | 'italics' | 'underline' | 'left' | 'center' | 'right' | 'bullet' | 'decimal';
-type attrfuncs = [attrname, { checkResult: () => boolean; toggle: () => any }];
-ScriptingGlobals.add(function toggleCharStyle(charStyle: attrname, checkResult?: boolean) {
-    const textView = RichTextMenu.Instance?.TextView;
-    const editorView = textView?.EditorView;
-    // prettier-ignore
-    const alignments:attrfuncs[] = (['left','right','center'] as ("left"|"center"|"right")[]).map((where) =>
-        [ where, {      checkResult: () =>(editorView ? (RichTextMenu.Instance.textAlign ===where): (Doc.UserDoc().textAlign ===where) ? true:false),
-                        toggle: () => (editorView?.state ? RichTextMenu.Instance.align(editorView, editorView.dispatch, where):(Doc.UserDoc().textAlign = where))}]);
-    // prettier-ignore
-    const listings:attrfuncs[] = (['bullet','decimal'] as attrname[]).map(list =>
-        [ list, {       checkResult: () => (editorView ? RichTextMenu.Instance.getActiveListStyle() === list:false),
-                        toggle: () => editorView?.state && RichTextMenu.Instance.changeListType(list) }]);
-    // prettier-ignore
-    const attrs:attrfuncs[] = [
-        ['dictation', { checkResult: () => textView?._recording ? true:false,
-                        toggle: () => textView && runInAction(() => (textView._recording = !textView._recording)) }],
-        ['noAutoLink',{ checkResult: () => (editorView ? RichTextMenu.Instance.noAutoLink : false),
-                        toggle: () => editorView && RichTextMenu.Instance?.toggleNoAutoLinkAnchor()}],
-        ['bold',      { checkResult: () => (editorView ? RichTextMenu.Instance.bold : (Doc.UserDoc().fontWeight === 'bold') ? true:false),
-                        toggle: editorView ? RichTextMenu.Instance.toggleBold : () => (Doc.UserDoc().fontWeight = Doc.UserDoc().fontWeight === 'bold' ? undefined : 'bold')}],
-        ['italics',   { checkResult: () => (editorView ? RichTextMenu.Instance.italics : (Doc.UserDoc().fontStyle === 'italics') ? true:false),
-                        toggle: editorView ? RichTextMenu.Instance.toggleItalics : () => (Doc.UserDoc().fontStyle = Doc.UserDoc().fontStyle === 'italics' ? undefined : 'italics')}],
-        ['underline', { checkResult: () => (editorView ? RichTextMenu.Instance.underline : (Doc.UserDoc().textDecoration === 'underline') ? true:false),
-                        toggle: editorView ? RichTextMenu.Instance.toggleUnderline : () => (Doc.UserDoc().textDecoration = Doc.UserDoc().textDecoration === 'underline' ? undefined : 'underline') }]]
-
-    const map = new Map(attrs.concat(alignments).concat(listings));
-    if (checkResult) return map.get(charStyle)?.checkResult() ? Colors.MEDIUM_BLUE : 'transparent';
-    map.get(charStyle)?.toggle();
-});
-
-export function checkInksToGroup() {
-    // console.log("getting here to inks group");
-    if (Doc.ActiveTool === InkTool.Write) {
-        CollectionFreeFormView.collectionsWithUnprocessedInk.forEach(ffView => {
-            // TODO: nda - will probably want to go through ffView unprocessed docs and then see if any of the inksToGroup docs are in it and only use those
-            // find all inkDocs in ffView.unprocessedDocs that are within 200 pixels of each other
-            const inksToGroup = ffView.unprocessedDocs.filter(inkDoc => {
-                // console.log(inkDoc.x, inkDoc.y);
-            });
-        });
-    }
-}
-
-export function createInkGroup(inksToGroup?: Doc[], isSubGroup?: boolean) {
-    // TODO nda - if document being added to is a inkGrouping then we can just add to that group
-    if (Doc.ActiveTool === InkTool.Write) {
-        CollectionFreeFormView.collectionsWithUnprocessedInk.forEach(ffView => {
-            // TODO: nda - will probably want to go through ffView unprocessed docs and then see if any of the inksToGroup docs are in it and only use those
-            const selected = ffView.unprocessedDocs;
-            // loop through selected an get the bound
-            const bounds: { x: number; y: number; width?: number; height?: number }[] = [];
-
-            selected.map(
-                action(d => {
-                    const x = NumCast(d.x);
-                    const y = NumCast(d.y);
-                    const width = d[Width]();
-                    const height = d[Height]();
-                    bounds.push({ x, y, width, height });
-                })
-            );
-
-            const aggregBounds = aggregateBounds(bounds, 0, 0);
-            const marqViewRef = ffView._marqueeViewRef.current;
-
-            // set the vals for bounds in marqueeView
-            if (marqViewRef) {
-                marqViewRef._downX = aggregBounds.x;
-                marqViewRef._downY = aggregBounds.y;
-                marqViewRef._lastX = aggregBounds.r;
-                marqViewRef._lastY = aggregBounds.b;
-            }
-
-            selected.map(
-                action(d => {
-                    const dx = NumCast(d.x);
-                    const dy = NumCast(d.y);
-                    delete d.x;
-                    delete d.y;
-                    delete d.activeFrame;
-                    delete d._timecodeToShow; // bcz: this should be automatic somehow.. along with any other properties that were logically associated with the original collection
-                    delete d._timecodeToHide; // bcz: this should be automatic somehow.. along with any other properties that were logically associated with the original collection
-                    // calculate pos based on bounds
-                    if (marqViewRef?.Bounds) {
-                        d.x = dx - marqViewRef.Bounds.left - marqViewRef.Bounds.width / 2;
-                        d.y = dy - marqViewRef.Bounds.top - marqViewRef.Bounds.height / 2;
-                    }
-                    return d;
-                })
-            );
-            ffView.props.removeDocument?.(selected);
-            // TODO: nda - this is the code to actually get a new grouped collection
-            const newCollection = marqViewRef?.getCollection(selected, undefined, true);
-            if (newCollection) {
-                newCollection.height = newCollection[Height]();
-                newCollection.width = newCollection[Width]();
-            }
-
-            // nda - bug: when deleting a stroke before leaving writing mode, delete the stroke from unprocessed ink docs
-            newCollection && ffView.props.addDocument?.(newCollection);
-            // TODO: nda - will probably need to go through and only remove the unprocessed selected docs
-            ffView.unprocessedDocs = [];
-
-            InkTranscription.Instance.transcribeInk(newCollection, selected, false);
-        });
-    }
-    CollectionFreeFormView.collectionsWithUnprocessedInk.clear();
-}
-
-function setActiveTool(tool: InkTool | GestureUtils.Gestures, keepPrim: boolean, checkResult?: boolean) {
-    InkTranscription.Instance?.createInkGroup();
-    if (checkResult) {
-        return (Doc.ActiveTool === tool && !GestureOverlay.Instance?.InkShape) || GestureOverlay.Instance?.InkShape === tool
-            ? GestureOverlay.Instance?.KeepPrimitiveMode || ![GestureUtils.Gestures.Circle, GestureUtils.Gestures.Line, GestureUtils.Gestures.Rectangle].includes(tool as GestureUtils.Gestures)
-                ? Colors.MEDIUM_BLUE
-                : Colors.MEDIUM_BLUE_ALT
-            : 'transparent';
-    }
-    runInAction(() => {
-        if (GestureOverlay.Instance) {
-            GestureOverlay.Instance.KeepPrimitiveMode = keepPrim;
-        }
-        if (Object.values(GestureUtils.Gestures).includes(tool as any)) {
-            if (GestureOverlay.Instance.InkShape === tool && !keepPrim) {
-                Doc.ActiveTool = InkTool.None;
-                GestureOverlay.Instance.InkShape = undefined;
-            } else {
-                Doc.ActiveTool = InkTool.Pen;
-                GestureOverlay.Instance.InkShape = tool as GestureUtils.Gestures;
-            }
-        } else if (tool) {
-            // pen or eraser
-            if (Doc.ActiveTool === tool && !GestureOverlay.Instance.InkShape && !keepPrim) {
-                Doc.ActiveTool = InkTool.None;
-            } else {
-                Doc.ActiveTool = tool as any;
-                GestureOverlay.Instance.InkShape = undefined;
-            }
-        } else {
-            Doc.ActiveTool = InkTool.None;
-        }
-    });
-}
-
-ScriptingGlobals.add(setActiveTool, 'sets the active ink tool mode');
-
-// toggle: Set overlay status of selected document
-ScriptingGlobals.add(function setInkProperty(option: 'inkMask' | 'fillColor' | 'strokeWidth' | 'strokeColor', value: any, checkResult?: boolean) {
-    const selected = SelectionManager.Docs().lastElement();
-    // prettier-ignore
-    const map: Map<'inkMask' | 'fillColor' | 'strokeWidth' | 'strokeColor', { checkResult: () => any; setInk: (doc: Doc) => void; setMode: () => void }> = new Map([
-        ['inkMask', {
-            checkResult: () => ((selected?.type === DocumentType.INK ? BoolCast(selected.stroke_isInkMask) : ActiveIsInkMask()) ? Colors.MEDIUM_BLUE : 'transparent'),
-            setInk: (doc: Doc) => (doc.stroke_isInkMask = !doc.stroke_isInkMask),
-            setMode: () => selected?.type !== DocumentType.INK && SetActiveIsInkMask(!ActiveIsInkMask()),
-        }],
-        ['fillColor', {
-            checkResult: () => (selected?.type === DocumentType.INK ? StrCast(selected.fillColor) : ActiveFillColor() ?? "transparent"),
-            setInk: (doc: Doc) => (doc.fillColor = StrCast(value)),
-            setMode: () => SetActiveFillColor(StrCast(value)),
-        }],
-        [ 'strokeWidth', {
-            checkResult: () => (selected?.type === DocumentType.INK ? NumCast(selected.stroke_width) : ActiveInkWidth()),
-            setInk: (doc: Doc) => (doc.stroke_width = NumCast(value)),
-            setMode: () => SetActiveInkWidth(value.toString()),
-        }],
-        ['strokeColor', {
-            checkResult: () => (selected?.type === DocumentType.INK ? StrCast(selected.color) : ActiveInkColor()),
-            setInk: (doc: Doc) => (doc.color = String(value)),
-            setMode: () => SetActiveInkColor(StrCast(value)),
-        }],
-    ]);
-
-    if (checkResult) {
-        return map.get(option)?.checkResult();
-    }
-    map.get(option)?.setMode();
-    SelectionManager.Docs()
-        .filter(doc => doc.type === DocumentType.INK)
-        .map(doc => map.get(option)?.setInk(doc));
-});
-
-/** WEB
- *      webSetURL
- **/
-ScriptingGlobals.add(function webSetURL(url: string, checkResult?: boolean) {
-    const selected = SelectionManager.Views().lastElement();
-    if (selected?.rootDoc.type === DocumentType.WEB) {
-        if (checkResult) {
-            return StrCast(selected.rootDoc.data, Cast(selected.rootDoc.data, WebField, null)?.url?.href);
-        }
-        selected.ComponentView?.setData?.(url);
-        //selected.rootDoc.data = new WebField(url);
-    }
-});
-ScriptingGlobals.add(function webForward(checkResult?: boolean) {
-    const selected = SelectionManager.Views().lastElement()?.ComponentView as WebBox;
-    if (checkResult) {
-        return selected?.forward(checkResult) ? undefined : 'lightGray';
-    }
-    selected?.forward();
-});
-ScriptingGlobals.add(function webBack(checkResult?: boolean) {
-    const selected = SelectionManager.Views().lastElement()?.ComponentView as WebBox;
-    if (checkResult) {
-        return selected?.back(checkResult) ? undefined : 'lightGray';
-    }
-    selected?.back();
-});
-
-/** Schema
- *      toggleSchemaPreview
- **/
-ScriptingGlobals.add(function toggleSchemaPreview(checkResult?: boolean) {
-    const selected = SelectionManager.Docs().lastElement();
-    if (checkResult && selected) {
-        const result: boolean = NumCast(selected.schema_previewWidth) > 0;
-        if (result) return Colors.MEDIUM_BLUE;
-        else return 'transparent';
-    } else if (selected) {
-        if (NumCast(selected.schema_previewWidth) > 0) {
-            selected.schema_previewWidth = 0;
-        } else {
-            selected.schema_previewWidth = 200;
-        }
-    }
-});
-ScriptingGlobals.add(function toggleSingleLineSchema(checkResult?: boolean) {
-    const selected = SelectionManager.Docs().lastElement();
-    if (checkResult && selected) {
-        return NumCast(selected._schema_singleLine) > 0 ? Colors.MEDIUM_BLUE : 'transparent';
-    }
-    if (selected) {
-        selected._schema_singleLine = !selected._schema_singleLine;
-    }
-});
-
-/** STACK
- *      groupBy
- */
-ScriptingGlobals.add(function setGroupBy(key: string, checkResult?: boolean) {
-    SelectionManager.Docs().map(doc => (doc._text_fontFamily = key));
-    const editorView = RichTextMenu.Instance.TextView?.EditorView;
-    if (checkResult) {
-        return StrCast((editorView ? RichTextMenu.Instance : Doc.UserDoc()).fontFamily);
-    }
-    if (editorView) RichTextMenu.Instance.setFontFamily(key);
-    else Doc.UserDoc().fontFamily = key;
-});
diff --git a/src/client/views/nodes/button/textButton/TextButton.tsx b/src/client/views/nodes/button/textButton/TextButton.tsx
deleted file mode 100644
index 5d7d55863..000000000
--- a/src/client/views/nodes/button/textButton/TextButton.tsx
+++ /dev/null
@@ -1,30 +0,0 @@
-import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import React, { Component } from 'react';
-import { BoolCast } from '../../../../../fields/Types';
-import { IButtonProps } from '../ButtonInterface';
-
-export class TextButton extends Component<IButtonProps> {
-    render() {
-        const type = this.props.type;
-        // Determine the type of toggle button
-        const buttonText: boolean = BoolCast(this.props.rootDoc.switchToggle);
-
-        return (
-            <div
-                className={`menuButton ${this.props.type}`}
-                style={{
-                    opacity: 1,
-                    backgroundColor: this.props.backgroundColor,
-                    color: this.props.color,
-                }}
-            >
-                <FontAwesomeIcon
-                    className={`fontIconBox-icon-${this.props.type}`}
-                    icon={this.props.icon}
-                    color={this.props.color}
-                />
-                {this.props.label}
-            </div>
-        );
-    }
-}
diff --git a/src/client/views/nodes/button/textButton/index.ts b/src/client/views/nodes/button/textButton/index.ts
deleted file mode 100644
index 01d62eb7e..000000000
--- a/src/client/views/nodes/button/textButton/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export * from './TextButton';
\ No newline at end of file
diff --git a/src/client/views/nodes/button/toggleButton/ToggleButton.tsx b/src/client/views/nodes/button/toggleButton/ToggleButton.tsx
deleted file mode 100644
index dca6487d8..000000000
--- a/src/client/views/nodes/button/toggleButton/ToggleButton.tsx
+++ /dev/null
@@ -1,34 +0,0 @@
-import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import React, { Component } from 'react';
-import { BoolCast } from '../../../../../fields/Types';
-import { Colors } from '../../../global/globalEnums';
-import { IButtonProps } from '../ButtonInterface';
-
-export class ToggleButton extends Component<IButtonProps> {
-    render() {
-        const type = this.props.type;
-        // Determine the type of toggle button
-        const switchToggle: boolean = BoolCast(this.props.rootDoc.switchToggle);
-
-        if (switchToggle) {
-            return (
-                <div className={`menuButton ${type} ${'switch'}`}>
-                    <label className="switch">
-                        <input type="checkbox"
-                            checked={this.props.backgroundColor === Colors.MEDIUM_BLUE}
-                        />
-                        <span className="slider round"></span>
-                    </label>
-                </div>
-            );
-        } else {
-            return (
-                <div className={`menuButton ${type}`}
-                    style={{ opacity: 1, backgroundColor: this.props.backgroundColor, color: this.props.color }}>
-                    <FontAwesomeIcon className={`fontIconBox-icon-${type}`} icon={this.props.icon} color={this.props.color} />
-                    {this.props.label}
-                </div>
-            );
-        }
-    }
-}
\ No newline at end of file
diff --git a/src/client/views/nodes/button/toggleButton/index.ts b/src/client/views/nodes/button/toggleButton/index.ts
deleted file mode 100644
index cdb9c527c..000000000
--- a/src/client/views/nodes/button/toggleButton/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export * from './ToggleButton';
\ No newline at end of file
diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx
index ef1c3911c..56af67802 100644
--- a/src/client/views/nodes/trails/PresBox.tsx
+++ b/src/client/views/nodes/trails/PresBox.tsx
@@ -1025,7 +1025,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
         });
         return true;
     };
-    childLayoutTemplate = () => (!this.isTreeOrStack ? undefined : DocCast(Doc.UserDoc().presElement));
+    childLayoutTemplate = () => (!this.isTreeOrStack ? DocCast(Doc.UserDoc().presElement) : DocCast(Doc.UserDoc().presElement));
     removeDocument = (doc: Doc) => Doc.RemoveDocFromList(this.rootDoc, this.fieldKey, doc);
     getTransform = () => this.props.ScreenToLocalTransform().translate(-5, -65); // listBox padding-left and pres-box-cont minHeight
     panelHeight = () => this.props.PanelHeight() - 40;
-- 
cgit v1.2.3-70-g09d2


From 9e5d835bf7d3415ec24fa8e79c18a2fece6a6ba7 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Wed, 12 Jul 2023 00:10:38 -0400
Subject: from last

---
 src/client/views/Main.tsx | 1 -
 1 file changed, 1 deletion(-)

(limited to 'src/client/views/Main.tsx')

diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index ed39cde13..d4db5e3e8 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -46,7 +46,6 @@ FieldLoader.ServerLoadStatus = { requested: 0, retrieved: 0 }; // bcz: not sure
         d.setTime(d.getTime() + 100 * 24 * 60 * 60 * 1000);
         const expires = 'expires=' + d.toUTCString();
         document.cookie = `loadtime=${loading};${expires};path=/`;
-        new LinkManager();
         new TrackMovements();
         new ReplayMovements();
         new PingManager();
-- 
cgit v1.2.3-70-g09d2

