From 08f125f5880247280c02633feeb31a8df1912b97 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Mon, 31 Jul 2023 00:06:16 -0400
Subject: fixed dictation into text boxes to stop when component unmounts.  
 fixed some icons.  fixed multiToggle for alignments.  added link docs to user
 cache.  fixed background color for tab stack buttons.    added a bunch of
 @computeds to try to help performacne with lots of docs.  chnaged text boxes
 to no expand/contract padding when selected.

---
 src/client/views/nodes/FontIconBox/FontIconBox.tsx | 72 ++++++++++++----------
 1 file changed, 41 insertions(+), 31 deletions(-)

(limited to 'src/client/views/nodes/FontIconBox/FontIconBox.tsx')

diff --git a/src/client/views/nodes/FontIconBox/FontIconBox.tsx b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
index da1b89200..ad3532502 100644
--- a/src/client/views/nodes/FontIconBox/FontIconBox.tsx
+++ b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
@@ -1,6 +1,6 @@
 import { IconProp } from '@fortawesome/fontawesome-svg-core';
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { Button, ColorPicker, Dropdown, DropdownType, EditableText, IconButton, IListItemProps, NumberDropdown, NumberDropdownType, Popup, Size, Toggle, ToggleType, Type } from 'browndash-components';
+import { Button, MultiToggle, ColorPicker, Dropdown, DropdownType, EditableText, IconButton, IListItemProps, NumberDropdown, NumberDropdownType, Popup, Size, Toggle, ToggleType, Type } from 'browndash-components';
 import { action, computed, observable } from 'mobx';
 import { observer } from 'mobx-react';
 import * as React from 'react';
@@ -21,6 +21,7 @@ import { RichTextMenu } from '../formattedText/RichTextMenu';
 import './FontIconBox.scss';
 import { SelectedDocView } from '../../selectedDoc';
 import { Utils } from '../../../../Utils';
+import { FaAlignCenter, FaAlignJustify, FaAlignLeft, FaAlignRight } from 'react-icons/fa';
 
 export enum ButtonType {
     TextButton = 'textBtn',
@@ -209,13 +210,10 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
             if (isViewDropdown) {
                 const selectedDocs: Doc[] = SelectionManager.Docs();
                 const selected = SelectionManager.Docs().lastElement();
-                console.log('selected');
                 if (selected) {
                     if (StrCast(selected.type) === DocumentType.COL) {
                         text = StrCast(selected._type_collection);
-                        console.log('collection selected', text);
                     } else {
-                        console.log('doc selected', selected.title);
                         dropdown = false;
                         if (selectedDocs.length > 1) {
                             text = selectedDocs.length + ' selected';
@@ -240,8 +238,6 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
             console.log(e);
         }
 
-        console.log('current item: ', text);
-
         // Get items to place into the list
         const list: IListItemProps[] = this.buttonList
             .filter(value => !Doc.noviceMode || !noviceList.length || noviceList.includes(value))
@@ -295,6 +291,34 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
             />
         );
     }
+    @computed get multiToggleButton() {
+        // Determine the type of toggle button
+        const tooltip: string = StrCast(this.rootDoc.toolTip);
+
+        const script = ScriptCast(this.rootDoc.onClick);
+        const toggleStatus = script ? script.script.run({ this: this.layoutDoc, self: this.rootDoc, value: undefined, _readOnly_: true }).result : false;
+        // Colors
+        const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color);
+        const items = DocListCast(this.rootDoc.data);
+        return (
+            <MultiToggle
+                tooltip={`Toggle ${tooltip}`}
+                type={Type.PRIM}
+                color={color}
+                label={this.label}
+                items={DocListCast(this.rootDoc.data).map(item => ({
+                    icon: <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={StrCast(item.icon) as any} color={color} />,
+                    tooltip: StrCast(item.toolTip),
+                    val: StrCast(item.toolType),
+                }))}
+                selectedVal={StrCast(items.find(itemDoc => ScriptCast(itemDoc.onClick).script.run({ this: itemDoc, self: itemDoc, value: undefined, _readOnly_: true }).result)?.toolType)}
+                setSelectedVal={(val: string | number) => {
+                    const itemDoc = items.find(item => item.toolType === val);
+                    itemDoc && ScriptCast(itemDoc.onClick).script.run({ this: itemDoc, self: itemDoc, value: val, _readOnly_: false });
+                }}
+            />
+        );
+    }
 
     @computed get toggleButton() {
         // Determine the type of toggle button
@@ -356,48 +380,34 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
     render() {
         // determine dash button metadata
         const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color);
-        const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor);
         const tooltip: string = StrCast(this.rootDoc.toolTip);
         const onClickScript = ScriptCast(this.rootDoc.onClick);
-        const script = ScriptCast(this.rootDoc.script);
         // TODO:glr Add label of button type
         let button: JSX.Element = this.defaultButton;
         // prettier-ignore
         switch (this.type) {
             case ButtonType.EditableText: 
-                button = this.editableText;
-                break;
+                button = this.editableText; break;
             case ButtonType.DropdownList:
-                button = this.dropdownListButton;
-                break;
+                button = this.dropdownListButton; break;
             case ButtonType.ColorButton: 
-                button = this.colorButton; 
-                break;
+                button = this.colorButton;  break;
             case ButtonType.NumberDropdownButton: 
             case ButtonType.NumberInlineButton:
             case ButtonType.NumberSliderButton: 
-                button = this.numberDropdown; 
-                break;
+                button = this.numberDropdown;  break;
             case ButtonType.DropdownButton: 
-                button = this.dropdownButton; 
-                break;
+                button = this.dropdownButton;  break;
+            case ButtonType.MultiToggleButton: 
+                button = this.multiToggleButton; break; 
             case ButtonType.ToggleButton: button = this.toggleButton; break;
             case ButtonType.ClickButton:
             case ButtonType.ToolButton: 
-                button = (
-                    <IconButton tooltip={tooltip} 
-                    color={color} icon={this.Icon(color)!} label={this.label}/>
-                );
-                break;
+                button = <IconButton tooltip={tooltip} color={color} icon={this.Icon(color)!} label={this.label}/>; break;
             case ButtonType.TextButton: 
-                button = (
-                    <Button tooltip={tooltip} icon={this.Icon(color)!} text={StrCast(this.rootDoc.buttonText)} label={this.label}/>
-                );
-                break;
-            case ButtonType.MenuButton: button = (
-                    <IconButton tooltip={tooltip} onPointerDown={() => onClickScript?.script.run({ this: this.layoutDoc, self: this.rootDoc, _readOnly_: false })} tooltipPlacement='right' size={Size.LARGE} color={color} icon={this.Icon(color)!} label={this.label}/>
-                );
-                break;
+                button = <Button tooltip={tooltip} icon={this.Icon(color)!} text={StrCast(this.rootDoc.buttonText)} label={this.label}/>; break;
+            case ButtonType.MenuButton: 
+                button = <IconButton tooltip={tooltip} onPointerDown={() => onClickScript?.script.run({ this: this.layoutDoc, self: this.rootDoc, _readOnly_: false })} tooltipPlacement='right' size={Size.LARGE} color={color} icon={this.Icon(color)!} label={this.label}/>; break;
         }
 
         return button;
-- 
cgit v1.2.3-70-g09d2


From 27bb82ad35e94c0d7bc6fa9af9ad04122be3d571 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Wed, 9 Aug 2023 21:42:10 -0400
Subject: fixed resizing from bottomleft. turned on Tools in novice mode.  
 fixed aborting editing of tree view titles with escape or click outside.  got
 rid of scrollbar in Tools panel by fixing height of masonry panel.  updated
 browndash-components to fix problem of tooltips getting in away of click
 events on Tool items.

---
 package-lock.json                                  | 1295 +++++++++++---------
 package.json                                       |    2 +-
 src/client/util/CurrentUserUtils.ts                |   19 +-
 src/client/views/DocumentDecorations.tsx           |    6 +-
 src/client/views/EditableView.tsx                  |    3 +-
 .../collections/CollectionMasonryViewFieldRow.tsx  |    1 -
 .../views/collections/CollectionStackingView.tsx   |    2 +-
 src/client/views/collections/TreeView.tsx          |    1 +
 src/client/views/nodes/EquationBox.scss            |    9 +-
 src/client/views/nodes/FontIconBox/FontIconBox.tsx |   40 +-
 10 files changed, 726 insertions(+), 652 deletions(-)

(limited to 'src/client/views/nodes/FontIconBox/FontIconBox.tsx')

diff --git a/package-lock.json b/package-lock.json
index 39a85cc9d..a62b3306c 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -142,20 +142,20 @@
             "integrity": "sha512-5UamI7xkUcJ3i9qVDS+KFDEK8/7oJ55/sJMB1Ge7IEapr7KfdfV/HErR+koZwOfd+SgtFKOKRhRakdg++DcJpQ=="
         },
         "@babel/core": {
-            "version": "7.22.9",
-            "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.9.tgz",
-            "integrity": "sha512-G2EgeufBcYw27U4hhoIwFcgc1XU7TlXJ3mv04oOv1WCuo900U/anZSPzEqNjwdjgffkk2Gs0AN0dW1CKVLcG7w==",
+            "version": "7.22.10",
+            "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.10.tgz",
+            "integrity": "sha512-fTmqbbUBAwCcre6zPzNngvsI0aNrPZe77AeqvDxWM9Nm+04RrJ3CAmGHA9f7lJQY6ZMhRztNemy4uslDxTX4Qw==",
             "requires": {
                 "@ampproject/remapping": "^2.2.0",
-                "@babel/code-frame": "^7.22.5",
-                "@babel/generator": "^7.22.9",
-                "@babel/helper-compilation-targets": "^7.22.9",
+                "@babel/code-frame": "^7.22.10",
+                "@babel/generator": "^7.22.10",
+                "@babel/helper-compilation-targets": "^7.22.10",
                 "@babel/helper-module-transforms": "^7.22.9",
-                "@babel/helpers": "^7.22.6",
-                "@babel/parser": "^7.22.7",
+                "@babel/helpers": "^7.22.10",
+                "@babel/parser": "^7.22.10",
                 "@babel/template": "^7.22.5",
-                "@babel/traverse": "^7.22.8",
-                "@babel/types": "^7.22.5",
+                "@babel/traverse": "^7.22.10",
+                "@babel/types": "^7.22.10",
                 "convert-source-map": "^1.7.0",
                 "debug": "^4.1.0",
                 "gensync": "^1.0.0-beta.2",
@@ -163,17 +163,68 @@
                 "semver": "^6.3.1"
             },
             "dependencies": {
+                "@babel/code-frame": {
+                    "version": "7.22.10",
+                    "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.10.tgz",
+                    "integrity": "sha512-/KKIMG4UEL35WmI9OlvMhurwtytjvXoFcGNrOvyG9zIzA8YmPjVtIZUf7b05+TPO7G7/GEmLHDaoCgACHl9hhA==",
+                    "requires": {
+                        "@babel/highlight": "^7.22.10",
+                        "chalk": "^2.4.2"
+                    }
+                },
                 "@babel/generator": {
-                    "version": "7.22.9",
-                    "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.9.tgz",
-                    "integrity": "sha512-KtLMbmicyuK2Ak/FTCJVbDnkN1SlT8/kceFTiuDiiRUUSMnHMidxSCdG4ndkTOHHpoomWe/4xkvHkEOncwjYIw==",
+                    "version": "7.22.10",
+                    "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.10.tgz",
+                    "integrity": "sha512-79KIf7YiWjjdZ81JnLujDRApWtl7BxTqWD88+FFdQEIOG8LJ0etDOM7CXuIgGJa55sGOwZVwuEsaLEm0PJ5/+A==",
                     "requires": {
-                        "@babel/types": "^7.22.5",
+                        "@babel/types": "^7.22.10",
                         "@jridgewell/gen-mapping": "^0.3.2",
                         "@jridgewell/trace-mapping": "^0.3.17",
                         "jsesc": "^2.5.1"
                     }
                 },
+                "@babel/highlight": {
+                    "version": "7.22.10",
+                    "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.10.tgz",
+                    "integrity": "sha512-78aUtVcT7MUscr0K5mIEnkwxPE0MaxkR5RxRwuHaQ+JuU5AmTPhY+do2mdzVTnIJJpyBglql2pehuBIWHug+WQ==",
+                    "requires": {
+                        "@babel/helper-validator-identifier": "^7.22.5",
+                        "chalk": "^2.4.2",
+                        "js-tokens": "^4.0.0"
+                    }
+                },
+                "@babel/parser": {
+                    "version": "7.22.10",
+                    "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.10.tgz",
+                    "integrity": "sha512-lNbdGsQb9ekfsnjFGhEiF4hfFqGgfOP3H3d27re3n+CGhNuTSUEQdfWk556sTLNTloczcdM5TYF2LhzmDQKyvQ=="
+                },
+                "@babel/traverse": {
+                    "version": "7.22.10",
+                    "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.10.tgz",
+                    "integrity": "sha512-Q/urqV4pRByiNNpb/f5OSv28ZlGJiFiiTh+GAHktbIrkPhPbl90+uW6SmpoLyZqutrg9AEaEf3Q/ZBRHBXgxig==",
+                    "requires": {
+                        "@babel/code-frame": "^7.22.10",
+                        "@babel/generator": "^7.22.10",
+                        "@babel/helper-environment-visitor": "^7.22.5",
+                        "@babel/helper-function-name": "^7.22.5",
+                        "@babel/helper-hoist-variables": "^7.22.5",
+                        "@babel/helper-split-export-declaration": "^7.22.6",
+                        "@babel/parser": "^7.22.10",
+                        "@babel/types": "^7.22.10",
+                        "debug": "^4.1.0",
+                        "globals": "^11.1.0"
+                    }
+                },
+                "@babel/types": {
+                    "version": "7.22.10",
+                    "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.10.tgz",
+                    "integrity": "sha512-obaoigiLrlDZ7TUQln/8m4mSqIW2QFeOrCQc9r+xsaHGNoplVNYlRVpsfE8Vj35GEm2ZH4ZhrNYogs/3fj85kg==",
+                    "requires": {
+                        "@babel/helper-string-parser": "^7.22.5",
+                        "@babel/helper-validator-identifier": "^7.22.5",
+                        "to-fast-properties": "^2.0.0"
+                    }
+                },
                 "debug": {
                     "version": "4.3.4",
                     "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
@@ -219,17 +270,29 @@
             }
         },
         "@babel/helper-builder-binary-assignment-operator-visitor": {
-            "version": "7.22.5",
-            "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.22.5.tgz",
-            "integrity": "sha512-m1EP3lVOPptR+2DwD125gziZNcmoNSHGmJROKoy87loWUQyJaVXDgpmruWqDARZSmtYQ+Dl25okU8+qhVzuykw==",
+            "version": "7.22.10",
+            "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.22.10.tgz",
+            "integrity": "sha512-Av0qubwDQxC56DoUReVDeLfMEjYYSN1nZrTUrWkXd7hpU73ymRANkbuDm3yni9npkn+RXy9nNbEJZEzXr7xrfQ==",
             "requires": {
-                "@babel/types": "^7.22.5"
+                "@babel/types": "^7.22.10"
+            },
+            "dependencies": {
+                "@babel/types": {
+                    "version": "7.22.10",
+                    "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.10.tgz",
+                    "integrity": "sha512-obaoigiLrlDZ7TUQln/8m4mSqIW2QFeOrCQc9r+xsaHGNoplVNYlRVpsfE8Vj35GEm2ZH4ZhrNYogs/3fj85kg==",
+                    "requires": {
+                        "@babel/helper-string-parser": "^7.22.5",
+                        "@babel/helper-validator-identifier": "^7.22.5",
+                        "to-fast-properties": "^2.0.0"
+                    }
+                }
             }
         },
         "@babel/helper-compilation-targets": {
-            "version": "7.22.9",
-            "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.9.tgz",
-            "integrity": "sha512-7qYrNM6HjpnPHJbopxmb8hSPoZ0gsX8IvUS32JGVoy+pU9e5N0nLr1VjJoR6kA4d9dmGLxNYOjeB8sUDal2WMw==",
+            "version": "7.22.10",
+            "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.10.tgz",
+            "integrity": "sha512-JMSwHD4J7SLod0idLq5PKgI+6g/hLD/iuWBq08ZX49xE14VpVEojJ5rHWptpirV2j020MvypRLAXAO50igCJ5Q==",
             "requires": {
                 "@babel/compat-data": "^7.22.9",
                 "@babel/helper-validator-option": "^7.22.5",
@@ -259,9 +322,9 @@
             }
         },
         "@babel/helper-create-class-features-plugin": {
-            "version": "7.22.9",
-            "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.22.9.tgz",
-            "integrity": "sha512-Pwyi89uO4YrGKxL/eNJ8lfEH55DnRloGPOseaA8NFNL6jAUnn+KccaISiFazCj5IolPPDjGSdzQzXVzODVRqUQ==",
+            "version": "7.22.10",
+            "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.22.10.tgz",
+            "integrity": "sha512-5IBb77txKYQPpOEdUdIhBx8VrZyDCQ+H82H0+5dX1TmuscP5vJKEE3cKurjtIw/vFwzbVH48VweE78kVDBrqjA==",
             "requires": {
                 "@babel/helper-annotate-as-pure": "^7.22.5",
                 "@babel/helper-environment-visitor": "^7.22.5",
@@ -484,23 +547,112 @@
             "integrity": "sha512-R3oB6xlIVKUnxNUxbmgq7pKjxpru24zlimpE8WK47fACIlM0II/Hm1RS8IaOI7NgCr6LNS+jl5l75m20npAziw=="
         },
         "@babel/helper-wrap-function": {
-            "version": "7.22.9",
-            "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.22.9.tgz",
-            "integrity": "sha512-sZ+QzfauuUEfxSEjKFmi3qDSHgLsTPK/pEpoD/qonZKOtTPTLbf59oabPQ4rKekt9lFcj/hTZaOhWwFYrgjk+Q==",
+            "version": "7.22.10",
+            "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.22.10.tgz",
+            "integrity": "sha512-OnMhjWjuGYtdoO3FmsEFWvBStBAe2QOgwOLsLNDjN+aaiMD8InJk1/O3HSD8lkqTjCgg5YI34Tz15KNNA3p+nQ==",
             "requires": {
                 "@babel/helper-function-name": "^7.22.5",
                 "@babel/template": "^7.22.5",
-                "@babel/types": "^7.22.5"
+                "@babel/types": "^7.22.10"
+            },
+            "dependencies": {
+                "@babel/types": {
+                    "version": "7.22.10",
+                    "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.10.tgz",
+                    "integrity": "sha512-obaoigiLrlDZ7TUQln/8m4mSqIW2QFeOrCQc9r+xsaHGNoplVNYlRVpsfE8Vj35GEm2ZH4ZhrNYogs/3fj85kg==",
+                    "requires": {
+                        "@babel/helper-string-parser": "^7.22.5",
+                        "@babel/helper-validator-identifier": "^7.22.5",
+                        "to-fast-properties": "^2.0.0"
+                    }
+                }
             }
         },
         "@babel/helpers": {
-            "version": "7.22.6",
-            "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.6.tgz",
-            "integrity": "sha512-YjDs6y/fVOYFV8hAf1rxd1QvR9wJe1pDBZ2AREKq/SDayfPzgk0PBnVuTCE5X1acEpMMNOVUqoe+OwiZGJ+OaA==",
+            "version": "7.22.10",
+            "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.10.tgz",
+            "integrity": "sha512-a41J4NW8HyZa1I1vAndrraTlPZ/eZoga2ZgS7fEr0tZJGVU4xqdE80CEm0CcNjha5EZ8fTBYLKHF0kqDUuAwQw==",
             "requires": {
                 "@babel/template": "^7.22.5",
-                "@babel/traverse": "^7.22.6",
-                "@babel/types": "^7.22.5"
+                "@babel/traverse": "^7.22.10",
+                "@babel/types": "^7.22.10"
+            },
+            "dependencies": {
+                "@babel/code-frame": {
+                    "version": "7.22.10",
+                    "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.10.tgz",
+                    "integrity": "sha512-/KKIMG4UEL35WmI9OlvMhurwtytjvXoFcGNrOvyG9zIzA8YmPjVtIZUf7b05+TPO7G7/GEmLHDaoCgACHl9hhA==",
+                    "requires": {
+                        "@babel/highlight": "^7.22.10",
+                        "chalk": "^2.4.2"
+                    }
+                },
+                "@babel/generator": {
+                    "version": "7.22.10",
+                    "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.10.tgz",
+                    "integrity": "sha512-79KIf7YiWjjdZ81JnLujDRApWtl7BxTqWD88+FFdQEIOG8LJ0etDOM7CXuIgGJa55sGOwZVwuEsaLEm0PJ5/+A==",
+                    "requires": {
+                        "@babel/types": "^7.22.10",
+                        "@jridgewell/gen-mapping": "^0.3.2",
+                        "@jridgewell/trace-mapping": "^0.3.17",
+                        "jsesc": "^2.5.1"
+                    }
+                },
+                "@babel/highlight": {
+                    "version": "7.22.10",
+                    "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.10.tgz",
+                    "integrity": "sha512-78aUtVcT7MUscr0K5mIEnkwxPE0MaxkR5RxRwuHaQ+JuU5AmTPhY+do2mdzVTnIJJpyBglql2pehuBIWHug+WQ==",
+                    "requires": {
+                        "@babel/helper-validator-identifier": "^7.22.5",
+                        "chalk": "^2.4.2",
+                        "js-tokens": "^4.0.0"
+                    }
+                },
+                "@babel/parser": {
+                    "version": "7.22.10",
+                    "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.10.tgz",
+                    "integrity": "sha512-lNbdGsQb9ekfsnjFGhEiF4hfFqGgfOP3H3d27re3n+CGhNuTSUEQdfWk556sTLNTloczcdM5TYF2LhzmDQKyvQ=="
+                },
+                "@babel/traverse": {
+                    "version": "7.22.10",
+                    "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.10.tgz",
+                    "integrity": "sha512-Q/urqV4pRByiNNpb/f5OSv28ZlGJiFiiTh+GAHktbIrkPhPbl90+uW6SmpoLyZqutrg9AEaEf3Q/ZBRHBXgxig==",
+                    "requires": {
+                        "@babel/code-frame": "^7.22.10",
+                        "@babel/generator": "^7.22.10",
+                        "@babel/helper-environment-visitor": "^7.22.5",
+                        "@babel/helper-function-name": "^7.22.5",
+                        "@babel/helper-hoist-variables": "^7.22.5",
+                        "@babel/helper-split-export-declaration": "^7.22.6",
+                        "@babel/parser": "^7.22.10",
+                        "@babel/types": "^7.22.10",
+                        "debug": "^4.1.0",
+                        "globals": "^11.1.0"
+                    }
+                },
+                "@babel/types": {
+                    "version": "7.22.10",
+                    "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.10.tgz",
+                    "integrity": "sha512-obaoigiLrlDZ7TUQln/8m4mSqIW2QFeOrCQc9r+xsaHGNoplVNYlRVpsfE8Vj35GEm2ZH4ZhrNYogs/3fj85kg==",
+                    "requires": {
+                        "@babel/helper-string-parser": "^7.22.5",
+                        "@babel/helper-validator-identifier": "^7.22.5",
+                        "to-fast-properties": "^2.0.0"
+                    }
+                },
+                "debug": {
+                    "version": "4.3.4",
+                    "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+                    "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+                    "requires": {
+                        "ms": "2.1.2"
+                    }
+                },
+                "ms": {
+                    "version": "2.1.2",
+                    "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+                    "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
+                }
             }
         },
         "@babel/highlight": {
@@ -591,15 +743,6 @@
             "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz",
             "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w=="
         },
-        "@babel/plugin-proposal-unicode-property-regex": {
-            "version": "7.18.6",
-            "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.18.6.tgz",
-            "integrity": "sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w==",
-            "requires": {
-                "@babel/helper-create-regexp-features-plugin": "^7.18.6",
-                "@babel/helper-plugin-utils": "^7.18.6"
-            }
-        },
         "@babel/plugin-syntax-async-generators": {
             "version": "7.8.4",
             "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz",
@@ -798,13 +941,13 @@
             }
         },
         "@babel/plugin-transform-async-generator-functions": {
-            "version": "7.22.7",
-            "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.22.7.tgz",
-            "integrity": "sha512-7HmE7pk/Fmke45TODvxvkxRMV9RazV+ZZzhOL9AG8G29TLrr3jkjwF7uJfxZ30EoXpO+LJkq4oA8NjO2DTnEDg==",
+            "version": "7.22.10",
+            "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.22.10.tgz",
+            "integrity": "sha512-eueE8lvKVzq5wIObKK/7dvoeKJ+xc6TvRn6aysIjS6pSCeLy7S/eVi7pEQknZqyqvzaNKdDtem8nUNTBgDVR2g==",
             "requires": {
                 "@babel/helper-environment-visitor": "^7.22.5",
                 "@babel/helper-plugin-utils": "^7.22.5",
-                "@babel/helper-remap-async-to-generator": "^7.22.5",
+                "@babel/helper-remap-async-to-generator": "^7.22.9",
                 "@babel/plugin-syntax-async-generators": "^7.8.4"
             },
             "dependencies": {
@@ -848,9 +991,9 @@
             }
         },
         "@babel/plugin-transform-block-scoping": {
-            "version": "7.22.5",
-            "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.22.5.tgz",
-            "integrity": "sha512-EcACl1i5fSQ6bt+YGuU/XGCeZKStLmyVGytWkpyhCLeQVA0eu6Wtiw92V+I1T/hnezUv7j74dA/Ro69gWcU+hg==",
+            "version": "7.22.10",
+            "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.22.10.tgz",
+            "integrity": "sha512-1+kVpGAOOI1Albt6Vse7c8pHzcZQdQKW+wJH+g8mCaszOdDVwRXa/slHPqIw+oJAJANTKDMuM2cBdV0Dg618Vg==",
             "requires": {
                 "@babel/helper-plugin-utils": "^7.22.5"
             },
@@ -943,9 +1086,9 @@
             }
         },
         "@babel/plugin-transform-destructuring": {
-            "version": "7.22.5",
-            "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.22.5.tgz",
-            "integrity": "sha512-GfqcFuGW8vnEqTUBM7UtPd5A4q797LTvvwKxXTgRsFjoqaJiEg9deBG6kWeQYkVEL569NpnmpC0Pkr/8BLKGnQ==",
+            "version": "7.22.10",
+            "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.22.10.tgz",
+            "integrity": "sha512-dPJrL0VOyxqLM9sritNbMSGx/teueHF/htMKrPT7DNxccXxRDPYqlgPFFdr8u+F+qUZOkZoXue/6rL5O5GduEw==",
             "requires": {
                 "@babel/helper-plugin-utils": "^7.22.5"
             },
@@ -1312,9 +1455,9 @@
             }
         },
         "@babel/plugin-transform-optional-chaining": {
-            "version": "7.22.6",
-            "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.22.6.tgz",
-            "integrity": "sha512-Vd5HiWml0mDVtcLHIoEU5sw6HOUW/Zk0acLs/SAeuLzkGNOPc9DB4nkUajemhCmTIz3eiaKREZn2hQQqF79YTg==",
+            "version": "7.22.10",
+            "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.22.10.tgz",
+            "integrity": "sha512-MMkQqZAZ+MGj+jGTG3OTuhKeBpNcO+0oCEbrGNEaOmiEn+1MzRyQlYsruGiU8RTK3zV6XwrVJTmwiDOyYK6J9g==",
             "requires": {
                 "@babel/helper-plugin-utils": "^7.22.5",
                 "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5",
@@ -1483,12 +1626,12 @@
             }
         },
         "@babel/plugin-transform-regenerator": {
-            "version": "7.22.5",
-            "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.22.5.tgz",
-            "integrity": "sha512-rR7KePOE7gfEtNTh9Qw+iO3Q/e4DEsoQ+hdvM6QUDH7JRJ5qxq5AA52ZzBWbI5i9lfNuvySgOGP8ZN7LAmaiPw==",
+            "version": "7.22.10",
+            "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.22.10.tgz",
+            "integrity": "sha512-F28b1mDt8KcT5bUyJc/U9nwzw6cV+UmTeRlXYIl2TNqMMJif0Jeey9/RQ3C4NOd2zp0/TRsDns9ttj2L523rsw==",
             "requires": {
                 "@babel/helper-plugin-utils": "^7.22.5",
-                "regenerator-transform": "^0.15.1"
+                "regenerator-transform": "^0.15.2"
             },
             "dependencies": {
                 "@babel/helper-plugin-utils": {
@@ -1590,12 +1733,12 @@
             }
         },
         "@babel/plugin-transform-typescript": {
-            "version": "7.22.9",
-            "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.22.9.tgz",
-            "integrity": "sha512-BnVR1CpKiuD0iobHPaM1iLvcwPYN2uVFAqoLVSpEDKWuOikoCv5HbKLxclhKYUXlWkX86DoZGtqI4XhbOsyrMg==",
+            "version": "7.22.10",
+            "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.22.10.tgz",
+            "integrity": "sha512-7++c8I/ymsDo4QQBAgbraXLzIM6jmfao11KgIBEYZRReWzNWH9NtNgJcyrZiXsOPh523FQm6LfpLyy/U5fn46A==",
             "requires": {
                 "@babel/helper-annotate-as-pure": "^7.22.5",
-                "@babel/helper-create-class-features-plugin": "^7.22.9",
+                "@babel/helper-create-class-features-plugin": "^7.22.10",
                 "@babel/helper-plugin-utils": "^7.22.5",
                 "@babel/plugin-syntax-typescript": "^7.22.5"
             },
@@ -1616,9 +1759,9 @@
             }
         },
         "@babel/plugin-transform-unicode-escapes": {
-            "version": "7.22.5",
-            "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.22.5.tgz",
-            "integrity": "sha512-biEmVg1IYB/raUO5wT1tgfacCef15Fbzhkx493D3urBI++6hpJ+RFG4SrWMn0NEZLfvilqKf3QDrRVZHo08FYg==",
+            "version": "7.22.10",
+            "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.22.10.tgz",
+            "integrity": "sha512-lRfaRKGZCBqDlRU3UIFovdp9c9mEvlylmpod0/OatICsSfuQ9YFthRo1tpTkGsklEefZdqlEFdY4A2dwTb6ohg==",
             "requires": {
                 "@babel/helper-plugin-utils": "^7.22.5"
             },
@@ -1679,12 +1822,12 @@
             }
         },
         "@babel/preset-env": {
-            "version": "7.22.9",
-            "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.22.9.tgz",
-            "integrity": "sha512-wNi5H/Emkhll/bqPjsjQorSykrlfY5OWakd6AulLvMEytpKasMVUpVy8RL4qBIBs5Ac6/5i0/Rv0b/Fg6Eag/g==",
+            "version": "7.22.10",
+            "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.22.10.tgz",
+            "integrity": "sha512-riHpLb1drNkpLlocmSyEg4oYJIQFeXAK/d7rI6mbD0XsvoTOOweXDmQPG/ErxsEhWk3rl3Q/3F6RFQlVFS8m0A==",
             "requires": {
                 "@babel/compat-data": "^7.22.9",
-                "@babel/helper-compilation-targets": "^7.22.9",
+                "@babel/helper-compilation-targets": "^7.22.10",
                 "@babel/helper-plugin-utils": "^7.22.5",
                 "@babel/helper-validator-option": "^7.22.5",
                 "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.22.5",
@@ -1709,15 +1852,15 @@
                 "@babel/plugin-syntax-top-level-await": "^7.14.5",
                 "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6",
                 "@babel/plugin-transform-arrow-functions": "^7.22.5",
-                "@babel/plugin-transform-async-generator-functions": "^7.22.7",
+                "@babel/plugin-transform-async-generator-functions": "^7.22.10",
                 "@babel/plugin-transform-async-to-generator": "^7.22.5",
                 "@babel/plugin-transform-block-scoped-functions": "^7.22.5",
-                "@babel/plugin-transform-block-scoping": "^7.22.5",
+                "@babel/plugin-transform-block-scoping": "^7.22.10",
                 "@babel/plugin-transform-class-properties": "^7.22.5",
                 "@babel/plugin-transform-class-static-block": "^7.22.5",
                 "@babel/plugin-transform-classes": "^7.22.6",
                 "@babel/plugin-transform-computed-properties": "^7.22.5",
-                "@babel/plugin-transform-destructuring": "^7.22.5",
+                "@babel/plugin-transform-destructuring": "^7.22.10",
                 "@babel/plugin-transform-dotall-regex": "^7.22.5",
                 "@babel/plugin-transform-duplicate-keys": "^7.22.5",
                 "@babel/plugin-transform-dynamic-import": "^7.22.5",
@@ -1740,27 +1883,27 @@
                 "@babel/plugin-transform-object-rest-spread": "^7.22.5",
                 "@babel/plugin-transform-object-super": "^7.22.5",
                 "@babel/plugin-transform-optional-catch-binding": "^7.22.5",
-                "@babel/plugin-transform-optional-chaining": "^7.22.6",
+                "@babel/plugin-transform-optional-chaining": "^7.22.10",
                 "@babel/plugin-transform-parameters": "^7.22.5",
                 "@babel/plugin-transform-private-methods": "^7.22.5",
                 "@babel/plugin-transform-private-property-in-object": "^7.22.5",
                 "@babel/plugin-transform-property-literals": "^7.22.5",
-                "@babel/plugin-transform-regenerator": "^7.22.5",
+                "@babel/plugin-transform-regenerator": "^7.22.10",
                 "@babel/plugin-transform-reserved-words": "^7.22.5",
                 "@babel/plugin-transform-shorthand-properties": "^7.22.5",
                 "@babel/plugin-transform-spread": "^7.22.5",
                 "@babel/plugin-transform-sticky-regex": "^7.22.5",
                 "@babel/plugin-transform-template-literals": "^7.22.5",
                 "@babel/plugin-transform-typeof-symbol": "^7.22.5",
-                "@babel/plugin-transform-unicode-escapes": "^7.22.5",
+                "@babel/plugin-transform-unicode-escapes": "^7.22.10",
                 "@babel/plugin-transform-unicode-property-regex": "^7.22.5",
                 "@babel/plugin-transform-unicode-regex": "^7.22.5",
                 "@babel/plugin-transform-unicode-sets-regex": "^7.22.5",
-                "@babel/preset-modules": "^0.1.5",
-                "@babel/types": "^7.22.5",
-                "babel-plugin-polyfill-corejs2": "^0.4.4",
-                "babel-plugin-polyfill-corejs3": "^0.8.2",
-                "babel-plugin-polyfill-regenerator": "^0.5.1",
+                "@babel/preset-modules": "0.1.6-no-external-plugins",
+                "@babel/types": "^7.22.10",
+                "babel-plugin-polyfill-corejs2": "^0.4.5",
+                "babel-plugin-polyfill-corejs3": "^0.8.3",
+                "babel-plugin-polyfill-regenerator": "^0.5.2",
                 "core-js-compat": "^3.31.0",
                 "semver": "^6.3.1"
             },
@@ -1770,6 +1913,16 @@
                     "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
                     "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
                 },
+                "@babel/types": {
+                    "version": "7.22.10",
+                    "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.10.tgz",
+                    "integrity": "sha512-obaoigiLrlDZ7TUQln/8m4mSqIW2QFeOrCQc9r+xsaHGNoplVNYlRVpsfE8Vj35GEm2ZH4ZhrNYogs/3fj85kg==",
+                    "requires": {
+                        "@babel/helper-string-parser": "^7.22.5",
+                        "@babel/helper-validator-identifier": "^7.22.5",
+                        "to-fast-properties": "^2.0.0"
+                    }
+                },
                 "semver": {
                     "version": "6.3.1",
                     "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
@@ -1778,13 +1931,11 @@
             }
         },
         "@babel/preset-modules": {
-            "version": "0.1.6",
-            "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6.tgz",
-            "integrity": "sha512-ID2yj6K/4lKfhuU3+EX4UvNbIt7eACFbHmNUjzA+ep+B5971CknnA/9DEWKbRokfbbtblxxxXFJJrH47UEAMVg==",
+            "version": "0.1.6-no-external-plugins",
+            "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz",
+            "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==",
             "requires": {
                 "@babel/helper-plugin-utils": "^7.0.0",
-                "@babel/plugin-proposal-unicode-property-regex": "^7.4.4",
-                "@babel/plugin-transform-dotall-regex": "^7.4.4",
                 "@babel/types": "^7.4.4",
                 "esutils": "^2.0.2"
             }
@@ -3060,12 +3211,17 @@
             },
             "dependencies": {
                 "@babel/runtime": {
-                    "version": "7.22.6",
-                    "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.6.tgz",
-                    "integrity": "sha512-wDb5pWm4WDdF6LFUde3Jl8WzPA+3ZbxYqkC6xAXuD3irdEHN1k0NfTRrJD8ZD378SJ61miMLCqIOXYhd8x+AJQ==",
+                    "version": "7.22.10",
+                    "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.10.tgz",
+                    "integrity": "sha512-21t/fkKLMZI4pqP2wlmsQAWnYW1PDyKyyUV4vCi+B25ydmdaYTKXPwCj0BzSUnZf4seIiYvSA3jcZ3gdsMFkLQ==",
                     "requires": {
-                        "regenerator-runtime": "^0.13.11"
+                        "regenerator-runtime": "^0.14.0"
                     }
+                },
+                "regenerator-runtime": {
+                    "version": "0.14.0",
+                    "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz",
+                    "integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA=="
                 }
             }
         },
@@ -3390,7 +3546,7 @@
         "@types/bcrypt-nodejs": {
             "version": "0.0.30",
             "resolved": "https://registry.npmjs.org/@types/bcrypt-nodejs/-/bcrypt-nodejs-0.0.30.tgz",
-            "integrity": "sha512-gSWCu7EOXhcM0FYM8tanV0deaX1VM07sgBS8dSUmgnAQ5/3Xn6k+mWF+ZfE+c/OCW14IVnNdTOKcHgvL78oDFQ==",
+            "integrity": "sha1-TN2WtJKTs5MhIuS34pVD415rrlg=",
             "dev": true
         },
         "@types/bezier-js": {
@@ -4621,7 +4777,7 @@
         "@types/strip-bom": {
             "version": "3.0.0",
             "resolved": "https://registry.npmjs.org/@types/strip-bom/-/strip-bom-3.0.0.tgz",
-            "integrity": "sha512-xevGOReSYGM7g/kUBZzPqCrR/KYAo+F0yiPc85WFTJa0MSLtyFTVTU6cJu/aV4mid7IffDIWqo69THF2o4JiEQ==",
+            "integrity": "sha1-FKjsOVbC6B7bdSB5CuzyHCkK69I=",
             "dev": true
         },
         "@types/strip-json-comments": {
@@ -4670,7 +4826,7 @@
         "@types/typescript": {
             "version": "2.0.0",
             "resolved": "https://registry.npmjs.org/@types/typescript/-/typescript-2.0.0.tgz",
-            "integrity": "sha512-WMEWfMISiJ2QKyk5/dSdgL0ZwP//PZj0jmDU0hMh51FmLq4WIYzjlngsUQZXejQL+QtkXJUOGjb3G3UCvgZuSQ==",
+            "integrity": "sha1-xDNTnJi64oaCswfqp6D9IRW4PCg=",
             "dev": true,
             "requires": {
                 "typescript": "*"
@@ -5004,7 +5160,7 @@
         "Base64": {
             "version": "0.2.1",
             "resolved": "https://registry.npmjs.org/Base64/-/Base64-0.2.1.tgz",
-            "integrity": "sha512-reGEWshDmTDQDsCec/HduOO9Wyj6yMOupMfhIf3ugN1TDlK2NQW4DDJSqNNtp380SNcvRfXtO8HSCQot0d0SMw=="
+            "integrity": "sha1-ujpCMHCOGGcFBl5mur3Uw1z2ACg="
         },
         "D": {
             "version": "1.0.0",
@@ -5253,7 +5409,7 @@
         "any-promise": {
             "version": "1.3.0",
             "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
-            "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A=="
+            "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8="
         },
         "anymatch": {
             "version": "2.0.0",
@@ -5406,7 +5562,7 @@
         "arr-diff": {
             "version": "4.0.0",
             "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz",
-            "integrity": "sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA=="
+            "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA="
         },
         "arr-flatten": {
             "version": "1.1.0",
@@ -5416,7 +5572,7 @@
         "arr-union": {
             "version": "3.1.0",
             "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz",
-            "integrity": "sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q=="
+            "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ="
         },
         "array-back": {
             "version": "2.0.0",
@@ -5518,7 +5674,7 @@
         "array-flatten": {
             "version": "1.1.1",
             "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
-            "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg=="
+            "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
         },
         "array-includes": {
             "version": "3.1.6",
@@ -5551,7 +5707,7 @@
         "array-unique": {
             "version": "0.3.2",
             "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz",
-            "integrity": "sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ=="
+            "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg="
         },
         "array.prototype.flat": {
             "version": "1.3.1",
@@ -5628,7 +5784,7 @@
         "assert-plus": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
-            "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw=="
+            "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
         },
         "assertion-error": {
             "version": "1.1.0",
@@ -5638,7 +5794,7 @@
         "assign-symbols": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz",
-            "integrity": "sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw=="
+            "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c="
         },
         "ast-types-flow": {
             "version": "0.0.7",
@@ -5668,7 +5824,7 @@
         "async-foreach": {
             "version": "0.1.3",
             "resolved": "https://registry.npmjs.org/async-foreach/-/async-foreach-0.1.3.tgz",
-            "integrity": "sha512-VUeSMD8nEGBWaZK4lizI1sf3yEC7pnAQ/mrI7pC2fBz2s/tq5jWWEngTwaf0Gruu/OoXRGLGg1XFqpYBiGTYJA=="
+            "integrity": "sha1-NhIfhFwFeBct5Bmpfb6x0W7DRUI="
         },
         "async-limiter": {
             "version": "1.0.1",
@@ -5679,7 +5835,7 @@
         "asynckit": {
             "version": "0.4.0",
             "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
-            "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
+            "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
         },
         "atob": {
             "version": "2.1.2",
@@ -5734,7 +5890,7 @@
         "aws-sign2": {
             "version": "0.7.0",
             "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
-            "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA=="
+            "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg="
         },
         "aws4": {
             "version": "1.12.0",
@@ -5812,7 +5968,7 @@
         "babel": {
             "version": "6.23.0",
             "resolved": "https://registry.npmjs.org/babel/-/babel-6.23.0.tgz",
-            "integrity": "sha512-ZDcCaI8Vlct8PJ3DvmyqUz+5X2Ylz3ZuuItBe/74yXosk2dwyVo/aN7MCJ8HJzhnnJ+6yP4o+lDgG9MBe91DLA=="
+            "integrity": "sha1-0NHn2APpdHZb7qMjLU4VPA77kPQ="
         },
         "babel-code-frame": {
             "version": "6.26.0",
@@ -5971,12 +6127,12 @@
         "babel-plugin-syntax-jsx": {
             "version": "6.18.0",
             "resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz",
-            "integrity": "sha512-qrPaCSo9c8RHNRHIotaufGbuOBN8rtdC4QrrFFc43vyWCCz7Kl7GL1PGaXtMGQZUXrkCjNEgxDfmAuAabr/rlw=="
+            "integrity": "sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY="
         },
         "babel-runtime": {
             "version": "6.26.0",
             "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
-            "integrity": "sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g==",
+            "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=",
             "requires": {
                 "core-js": "^2.4.0",
                 "regenerator-runtime": "^0.11.0"
@@ -6049,7 +6205,7 @@
                 "define-property": {
                     "version": "1.0.0",
                     "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
-                    "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==",
+                    "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
                     "requires": {
                         "is-descriptor": "^1.0.0"
                     }
@@ -6085,7 +6241,7 @@
         "base16": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/base16/-/base16-1.0.0.tgz",
-            "integrity": "sha512-pNdYkNPiJUnEhnfXV56+sQy8+AaPcG3POZAUnwr4EeqCUZFz4u2PePbo3e5Gj4ziYPCWGUZT9RHisvJKnwFuBQ=="
+            "integrity": "sha1-4pf2DX7BAUp6lxo568ipjAtoHnA="
         },
         "base64-arraybuffer": {
             "version": "0.1.4",
@@ -6110,18 +6266,18 @@
         "batch": {
             "version": "0.6.1",
             "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz",
-            "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==",
+            "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=",
             "dev": true
         },
         "bcrypt-nodejs": {
             "version": "0.0.3",
             "resolved": "https://registry.npmjs.org/bcrypt-nodejs/-/bcrypt-nodejs-0.0.3.tgz",
-            "integrity": "sha512-NmTbLm867btBHCBZ222FQXkQKzecB0KG6pTXFa6NeTVZaSnLfCsx7EK2PL3J+kX8xJThUquEBbhimRCKKZX9zA=="
+            "integrity": "sha1-xgkX8m3CNWYVZsaBBhwwPCsohCs="
         },
         "bcrypt-pbkdf": {
             "version": "1.0.2",
             "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
-            "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==",
+            "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=",
             "requires": {
                 "tweetnacl": "^0.14.3"
             }
@@ -6134,7 +6290,7 @@
         "bezier-curve": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/bezier-curve/-/bezier-curve-1.0.0.tgz",
-            "integrity": "sha512-h6uZJ6qdFfswS1rIRericgouhTeiVi/MnH10OKtCu2IZzXa+ZcjaxRLHY4u/evRsJcxYbbiNkgWQj2Z4UIcpEQ=="
+            "integrity": "sha1-o9+v6rEqlMRicw1QeYxSqEBdc3k="
         },
         "bezier-js": {
             "version": "4.1.1",
@@ -6273,7 +6429,7 @@
         "boolbase": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
-            "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww=="
+            "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24="
         },
         "bootstrap": {
             "version": "4.6.2",
@@ -6335,7 +6491,7 @@
                 "extend-shallow": {
                     "version": "2.0.1",
                     "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
-                    "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==",
+                    "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
                     "requires": {
                         "is-extendable": "^0.1.0"
                     }
@@ -6351,9 +6507,9 @@
             }
         },
         "browndash-components": {
-            "version": "0.0.91",
-            "resolved": "https://registry.npmjs.org/browndash-components/-/browndash-components-0.0.91.tgz",
-            "integrity": "sha512-VYW1C1XY6CcQD4OceQHK/2VGhSa0H0iboom7M9zy5F6WHJP03LFHrwKkRtgsqwxQBQLsj69XXlEfygbSkV3FvQ==",
+            "version": "0.0.92",
+            "resolved": "https://registry.npmjs.org/browndash-components/-/browndash-components-0.0.92.tgz",
+            "integrity": "sha512-eE/6WQNZiLnaXUKyoaMm0PDYjExUsFJ9VTAIIxROpYPosIBKWNZ743xaOfmehib5us9hEXJb0CvUFJQb8rzDVw==",
             "requires": {
                 "@emotion/react": "^11.11.1",
                 "@emotion/styled": "^11.11.0",
@@ -6368,9 +6524,9 @@
             },
             "dependencies": {
                 "@babel/cli": {
-                    "version": "7.22.9",
-                    "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.22.9.tgz",
-                    "integrity": "sha512-nb2O7AThqRo7/E53EGiuAkMaRbb7J5Qp3RvN+dmua1U+kydm0oznkhqbTEG15yk26G/C3yL6OdZjzgl+DMXVVA==",
+                    "version": "7.22.10",
+                    "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.22.10.tgz",
+                    "integrity": "sha512-rM9ZMmaII630zGvtMtQ3P4GyHs28CHLYE9apLG7L8TgaSqcfoIGrlLSLsh4Q8kDTdZQQEXZm1M0nQtOvU/2heg==",
                     "requires": {
                         "@jridgewell/trace-mapping": "^0.3.17",
                         "@nicolo-ribaudo/chokidar-2": "2.1.8-no-fsevents.3",
@@ -6471,48 +6627,48 @@
                     "integrity": "sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww=="
                 },
                 "@mui/base": {
-                    "version": "5.0.0-beta.8",
-                    "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-beta.8.tgz",
-                    "integrity": "sha512-b4vVjMZx5KzzEMf4arXKoeV5ZegAMOoPwoy1vfUBwhvXc2QtaaAyBp50U7OA2L06Leubc1A+lEp3eqwZoFn87g==",
+                    "version": "5.0.0-beta.10",
+                    "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-beta.10.tgz",
+                    "integrity": "sha512-moTAhGwFfQffj7hsu61FnqcGqVcd53A1CrOhnskM9TF0Uh2rnLDMCuar4JRUWWpaJofAfQEbQBBFPadFQLI4PA==",
                     "requires": {
                         "@babel/runtime": "^7.22.6",
                         "@emotion/is-prop-valid": "^1.2.1",
                         "@mui/types": "^7.2.4",
-                        "@mui/utils": "^5.14.1",
+                        "@mui/utils": "^5.14.4",
                         "@popperjs/core": "^2.11.8",
-                        "clsx": "^1.2.1",
+                        "clsx": "^2.0.0",
                         "prop-types": "^15.8.1",
                         "react-is": "^18.2.0"
                     },
                     "dependencies": {
                         "@babel/runtime": {
-                            "version": "7.22.6",
-                            "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.6.tgz",
-                            "integrity": "sha512-wDb5pWm4WDdF6LFUde3Jl8WzPA+3ZbxYqkC6xAXuD3irdEHN1k0NfTRrJD8ZD378SJ61miMLCqIOXYhd8x+AJQ==",
+                            "version": "7.22.10",
+                            "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.10.tgz",
+                            "integrity": "sha512-21t/fkKLMZI4pqP2wlmsQAWnYW1PDyKyyUV4vCi+B25ydmdaYTKXPwCj0BzSUnZf4seIiYvSA3jcZ3gdsMFkLQ==",
                             "requires": {
-                                "regenerator-runtime": "^0.13.11"
+                                "regenerator-runtime": "^0.14.0"
                             }
                         }
                     }
                 },
                 "@mui/core-downloads-tracker": {
-                    "version": "5.14.2",
-                    "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.14.2.tgz",
-                    "integrity": "sha512-x+c/MgDL1t/IIy5lDbMlrDouFG5DYZbl3DP4dbbuhlpPFBnE9glYwmJEee/orVHQpOPwLxCAIWQs+2DKSaBVWQ=="
+                    "version": "5.14.4",
+                    "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.14.4.tgz",
+                    "integrity": "sha512-pW2XghSi3hpYKX57Wu0SCWMTSpzvXZmmucj3TcOJWaCiFt4xr05w2gcwBZi36dAp9uvd9//9N51qbblmnD+GPg=="
                 },
                 "@mui/material": {
-                    "version": "5.14.2",
-                    "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.14.2.tgz",
-                    "integrity": "sha512-TgNR4/YRL11RifsnMWNhITNCkGJYVz20SCvVJBBoU5Y/KhUNSSJxjDpEB8VrnY+sUsV0NigLCkHZJglfsiS3Pw==",
+                    "version": "5.14.4",
+                    "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.14.4.tgz",
+                    "integrity": "sha512-2XUV3KyRC07BQPPzEgd+ss3x/ezXtHeKtOGCMCNmx3MauZojPYUpSwFkE0fYgYCD9dMQMVG4DY/VF38P0KShsg==",
                     "requires": {
                         "@babel/runtime": "^7.22.6",
-                        "@mui/base": "5.0.0-beta.8",
-                        "@mui/core-downloads-tracker": "^5.14.2",
-                        "@mui/system": "^5.14.1",
+                        "@mui/base": "5.0.0-beta.10",
+                        "@mui/core-downloads-tracker": "^5.14.4",
+                        "@mui/system": "^5.14.4",
                         "@mui/types": "^7.2.4",
-                        "@mui/utils": "^5.14.1",
+                        "@mui/utils": "^5.14.4",
                         "@types/react-transition-group": "^4.4.6",
-                        "clsx": "^1.2.1",
+                        "clsx": "^2.0.0",
                         "csstype": "^3.1.2",
                         "prop-types": "^15.8.1",
                         "react-is": "^18.2.0",
@@ -6520,31 +6676,31 @@
                     },
                     "dependencies": {
                         "@babel/runtime": {
-                            "version": "7.22.6",
-                            "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.6.tgz",
-                            "integrity": "sha512-wDb5pWm4WDdF6LFUde3Jl8WzPA+3ZbxYqkC6xAXuD3irdEHN1k0NfTRrJD8ZD378SJ61miMLCqIOXYhd8x+AJQ==",
+                            "version": "7.22.10",
+                            "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.10.tgz",
+                            "integrity": "sha512-21t/fkKLMZI4pqP2wlmsQAWnYW1PDyKyyUV4vCi+B25ydmdaYTKXPwCj0BzSUnZf4seIiYvSA3jcZ3gdsMFkLQ==",
                             "requires": {
-                                "regenerator-runtime": "^0.13.11"
+                                "regenerator-runtime": "^0.14.0"
                             }
                         }
                     }
                 },
                 "@mui/private-theming": {
-                    "version": "5.13.7",
-                    "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.13.7.tgz",
-                    "integrity": "sha512-qbSr+udcij5F9dKhGX7fEdx2drXchq7htLNr2Qg2Ma+WJ6q0ERlEqGSBiPiVDJkptcjeVL4DGmcf1wl5+vD4EA==",
+                    "version": "5.14.4",
+                    "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.14.4.tgz",
+                    "integrity": "sha512-ISXsHDiQ3z1XA4IuKn+iXDWvDjcz/UcQBiFZqtdoIsEBt8CB7wgdQf3LwcwqO81dl5ofg/vNQBEnXuKfZHrnYA==",
                     "requires": {
-                        "@babel/runtime": "^7.22.5",
-                        "@mui/utils": "^5.13.7",
+                        "@babel/runtime": "^7.22.6",
+                        "@mui/utils": "^5.14.4",
                         "prop-types": "^15.8.1"
                     },
                     "dependencies": {
                         "@babel/runtime": {
-                            "version": "7.22.6",
-                            "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.6.tgz",
-                            "integrity": "sha512-wDb5pWm4WDdF6LFUde3Jl8WzPA+3ZbxYqkC6xAXuD3irdEHN1k0NfTRrJD8ZD378SJ61miMLCqIOXYhd8x+AJQ==",
+                            "version": "7.22.10",
+                            "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.10.tgz",
+                            "integrity": "sha512-21t/fkKLMZI4pqP2wlmsQAWnYW1PDyKyyUV4vCi+B25ydmdaYTKXPwCj0BzSUnZf4seIiYvSA3jcZ3gdsMFkLQ==",
                             "requires": {
-                                "regenerator-runtime": "^0.13.11"
+                                "regenerator-runtime": "^0.14.0"
                             }
                         }
                     }
@@ -6561,44 +6717,44 @@
                     },
                     "dependencies": {
                         "@babel/runtime": {
-                            "version": "7.22.6",
-                            "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.6.tgz",
-                            "integrity": "sha512-wDb5pWm4WDdF6LFUde3Jl8WzPA+3ZbxYqkC6xAXuD3irdEHN1k0NfTRrJD8ZD378SJ61miMLCqIOXYhd8x+AJQ==",
+                            "version": "7.22.10",
+                            "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.10.tgz",
+                            "integrity": "sha512-21t/fkKLMZI4pqP2wlmsQAWnYW1PDyKyyUV4vCi+B25ydmdaYTKXPwCj0BzSUnZf4seIiYvSA3jcZ3gdsMFkLQ==",
                             "requires": {
-                                "regenerator-runtime": "^0.13.11"
+                                "regenerator-runtime": "^0.14.0"
                             }
                         }
                     }
                 },
                 "@mui/system": {
-                    "version": "5.14.1",
-                    "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.14.1.tgz",
-                    "integrity": "sha512-u+xlsU34Jdkgx1CxmBnIC4Y08uPdVX5iEd3S/1dggDFtOGp+Lj8xmKRJAQ8PJOOJLOh8pDwaZx4AwXikL4l1QA==",
+                    "version": "5.14.4",
+                    "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.14.4.tgz",
+                    "integrity": "sha512-oPgfWS97QNfHcDBapdkZIs4G5i85BJt69Hp6wbXF6s7vi3Evcmhdk8AbCRW6n0sX4vTj8oe0mh0RIm1G2A1KDA==",
                     "requires": {
                         "@babel/runtime": "^7.22.6",
-                        "@mui/private-theming": "^5.13.7",
+                        "@mui/private-theming": "^5.14.4",
                         "@mui/styled-engine": "^5.13.2",
                         "@mui/types": "^7.2.4",
-                        "@mui/utils": "^5.14.1",
-                        "clsx": "^1.2.1",
+                        "@mui/utils": "^5.14.4",
+                        "clsx": "^2.0.0",
                         "csstype": "^3.1.2",
                         "prop-types": "^15.8.1"
                     },
                     "dependencies": {
                         "@babel/runtime": {
-                            "version": "7.22.6",
-                            "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.6.tgz",
-                            "integrity": "sha512-wDb5pWm4WDdF6LFUde3Jl8WzPA+3ZbxYqkC6xAXuD3irdEHN1k0NfTRrJD8ZD378SJ61miMLCqIOXYhd8x+AJQ==",
+                            "version": "7.22.10",
+                            "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.10.tgz",
+                            "integrity": "sha512-21t/fkKLMZI4pqP2wlmsQAWnYW1PDyKyyUV4vCi+B25ydmdaYTKXPwCj0BzSUnZf4seIiYvSA3jcZ3gdsMFkLQ==",
                             "requires": {
-                                "regenerator-runtime": "^0.13.11"
+                                "regenerator-runtime": "^0.14.0"
                             }
                         }
                     }
                 },
                 "@mui/utils": {
-                    "version": "5.14.1",
-                    "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.14.1.tgz",
-                    "integrity": "sha512-39KHKK2JeqRmuUcLDLwM+c2XfVC136C5/yUyQXmO2PVbOb2Bol4KxtkssEqCbTwg87PSCG3f1Tb0keRsK7cVGw==",
+                    "version": "5.14.4",
+                    "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.14.4.tgz",
+                    "integrity": "sha512-4ANV0txPD3x0IcTCSEHKDWnsutg1K3m6Vz5IckkbLXVYu17oOZCVUdOKsb/txUmaCd0v0PmSRe5PW+Mlvns5dQ==",
                     "requires": {
                         "@babel/runtime": "^7.22.6",
                         "@types/prop-types": "^15.7.5",
@@ -6608,11 +6764,11 @@
                     },
                     "dependencies": {
                         "@babel/runtime": {
-                            "version": "7.22.6",
-                            "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.6.tgz",
-                            "integrity": "sha512-wDb5pWm4WDdF6LFUde3Jl8WzPA+3ZbxYqkC6xAXuD3irdEHN1k0NfTRrJD8ZD378SJ61miMLCqIOXYhd8x+AJQ==",
+                            "version": "7.22.10",
+                            "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.10.tgz",
+                            "integrity": "sha512-21t/fkKLMZI4pqP2wlmsQAWnYW1PDyKyyUV4vCi+B25ydmdaYTKXPwCj0BzSUnZf4seIiYvSA3jcZ3gdsMFkLQ==",
                             "requires": {
-                                "regenerator-runtime": "^0.13.11"
+                                "regenerator-runtime": "^0.14.0"
                             }
                         }
                     }
@@ -6681,6 +6837,11 @@
                         "readdirp": "~3.6.0"
                     }
                 },
+                "clsx": {
+                    "version": "2.0.0",
+                    "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.0.0.tgz",
+                    "integrity": "sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q=="
+                },
                 "color": {
                     "version": "4.2.3",
                     "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz",
@@ -6902,97 +7063,12 @@
                                         "strip-ansi": "^7.0.1"
                                     }
                                 },
-                                "string-width-cjs": {
-                                    "version": "npm:string-width@4.2.3",
-                                    "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
-                                    "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
-                                    "requires": {
-                                        "emoji-regex": "^8.0.0",
-                                        "is-fullwidth-code-point": "^3.0.0",
-                                        "strip-ansi": "^6.0.1"
-                                    },
-                                    "dependencies": {
-                                        "ansi-regex": {
-                                            "version": "5.0.1",
-                                            "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
-                                            "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="
-                                        },
-                                        "emoji-regex": {
-                                            "version": "8.0.0",
-                                            "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
-                                            "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
-                                        },
-                                        "strip-ansi": {
-                                            "version": "6.0.1",
-                                            "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
-                                            "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
-                                            "requires": {
-                                                "ansi-regex": "^5.0.1"
-                                            }
-                                        }
-                                    }
-                                },
                                 "strip-ansi": {
                                     "version": "7.1.0",
                                     "bundled": true,
                                     "requires": {
                                         "ansi-regex": "^6.0.1"
                                     }
-                                },
-                                "strip-ansi-cjs": {
-                                    "version": "npm:strip-ansi@6.0.1",
-                                    "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
-                                    "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
-                                    "requires": {
-                                        "ansi-regex": "^5.0.1"
-                                    },
-                                    "dependencies": {
-                                        "ansi-regex": {
-                                            "version": "5.0.1",
-                                            "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
-                                            "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="
-                                        }
-                                    }
-                                },
-                                "wrap-ansi-cjs": {
-                                    "version": "npm:wrap-ansi@7.0.0",
-                                    "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
-                                    "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
-                                    "requires": {
-                                        "ansi-styles": "^4.0.0",
-                                        "string-width": "^4.1.0",
-                                        "strip-ansi": "^6.0.0"
-                                    },
-                                    "dependencies": {
-                                        "ansi-regex": {
-                                            "version": "5.0.1",
-                                            "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
-                                            "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="
-                                        },
-                                        "emoji-regex": {
-                                            "version": "8.0.0",
-                                            "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
-                                            "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
-                                        },
-                                        "string-width": {
-                                            "version": "4.2.3",
-                                            "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
-                                            "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
-                                            "requires": {
-                                                "emoji-regex": "^8.0.0",
-                                                "is-fullwidth-code-point": "^3.0.0",
-                                                "strip-ansi": "^6.0.1"
-                                            }
-                                        },
-                                        "strip-ansi": {
-                                            "version": "6.0.1",
-                                            "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
-                                            "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
-                                            "requires": {
-                                                "ansi-regex": "^5.0.1"
-                                            }
-                                        }
-                                    }
                                 }
                             }
                         },
@@ -8497,7 +8573,7 @@
                             }
                         },
                         "string-width-cjs": {
-                            "version": "npm:string-width-cjs@4.2.3",
+                            "version": "npm:string-width@4.2.3",
                             "bundled": true,
                             "requires": {
                                 "emoji-regex": "^8.0.0",
@@ -8520,7 +8596,7 @@
                             }
                         },
                         "strip-ansi-cjs": {
-                            "version": "npm:strip-ansi-cjs@6.0.1",
+                            "version": "npm:strip-ansi@6.0.1",
                             "bundled": true,
                             "requires": {
                                 "ansi-regex": "^5.0.1"
@@ -8679,7 +8755,7 @@
                             }
                         },
                         "wrap-ansi-cjs": {
-                            "version": "npm:wrap-ansi-cjs@7.0.0",
+                            "version": "npm:wrap-ansi@7.0.0",
                             "bundled": true,
                             "requires": {
                                 "ansi-styles": "^4.0.0",
@@ -8739,15 +8815,20 @@
                         "picomatch": "^2.2.1"
                     }
                 },
+                "regenerator-runtime": {
+                    "version": "0.14.0",
+                    "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz",
+                    "integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA=="
+                },
                 "slash": {
                     "version": "2.0.0",
                     "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz",
                     "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A=="
                 },
                 "styled-components": {
-                    "version": "6.0.5",
-                    "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-6.0.5.tgz",
-                    "integrity": "sha512-308zi5o7LrA9cVaP4nPD0TaUpOjGPePkAUFb/OGB0xRI3I9ozpW5UyASvRVi9wJcYASG+Y3mLDLDUZC7nqzimw==",
+                    "version": "6.0.7",
+                    "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-6.0.7.tgz",
+                    "integrity": "sha512-xIwWuiRMYR43mskVsW9MGTRjSo7ol4bcVjT595fGUp3OLBJOlOgaiKaxsHdC4a2HqWKqKnh0CmcRbk5ogyDjTg==",
                     "requires": {
                         "@babel/cli": "^7.21.0",
                         "@babel/core": "^7.21.0",
@@ -8796,7 +8877,7 @@
         "browser-assert": {
             "version": "1.2.1",
             "resolved": "https://registry.npmjs.org/browser-assert/-/browser-assert-1.2.1.tgz",
-            "integrity": "sha512-nfulgvOR6S4gt9UKCeGJOuSGBPGiFT6oQ/2UBnvTY/5aQ1PnksW72fhZkM30DzoRRv2WpwZf1vHHEr3mtuXIWQ=="
+            "integrity": "sha1-mqpaKox0aFwq4Fv+Ru/WBvBowgA="
         },
         "browser-process-hrtime": {
             "version": "1.0.0",
@@ -8840,7 +8921,7 @@
         "buffer-crc32": {
             "version": "0.2.13",
             "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
-            "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ=="
+            "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI="
         },
         "buffer-equal-constant-time": {
             "version": "1.0.1",
@@ -8866,7 +8947,7 @@
         "built-in-math-eval": {
             "version": "0.3.0",
             "resolved": "https://registry.npmjs.org/built-in-math-eval/-/built-in-math-eval-0.3.0.tgz",
-            "integrity": "sha512-5XD5cujru60ooKJ4sGZqoH5v2Xvgw7ezV54gJX/OnPkgDKoH3BnlMEi8xW6hl8xaEjxKHebgrsawroeZnGwIMA==",
+            "integrity": "sha1-JA3CHLOJQ5WIxhxGDrAHZJfvxBw=",
             "requires": {
                 "math-codegen": "^0.3.5"
             }
@@ -8989,7 +9070,7 @@
         "caller-callsite": {
             "version": "2.0.0",
             "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz",
-            "integrity": "sha512-JuG3qI4QOftFsZyOn1qq87fq5grLIyk1JYd5lJmdA+fG7aQ9pA/i3JIJGcO3q0MrRcHlOt1U+ZeHW8Dq9axALQ==",
+            "integrity": "sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=",
             "requires": {
                 "callsites": "^2.0.0"
             },
@@ -8997,14 +9078,14 @@
                 "callsites": {
                     "version": "2.0.0",
                     "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz",
-                    "integrity": "sha512-ksWePWBloaWPxJYQ8TL0JHvtci6G5QTKwQ95RcWAa/lzoAKuAOflGdAK92hpHXjkwb8zLxoLNUoNYZgVsaJzvQ=="
+                    "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA="
                 }
             }
         },
         "caller-path": {
             "version": "2.0.0",
             "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz",
-            "integrity": "sha512-MCL3sf6nCSXOwCTzvPKhN18TU7AHTvdtam8DAogxcrJ8Rjfbbg7Lgng64H9Iy+vUV6VGFClN/TyxBkAebLRR4A==",
+            "integrity": "sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ=",
             "requires": {
                 "caller-callsite": "^2.0.0"
             }
@@ -9072,7 +9153,7 @@
         "caseless": {
             "version": "0.12.0",
             "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
-            "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw=="
+            "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw="
         },
         "ccount": {
             "version": "2.0.1",
@@ -9149,12 +9230,12 @@
         "check-error": {
             "version": "1.0.2",
             "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz",
-            "integrity": "sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA=="
+            "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII="
         },
         "child_process": {
             "version": "1.0.2",
             "resolved": "https://registry.npmjs.org/child_process/-/child_process-1.0.2.tgz",
-            "integrity": "sha512-Wmza/JzL0SiWz7kl6MhIKT5ceIlnFPJX+lwUGj7Clhy5MMldsSoJR0+uvRzOS5Kv45Mq7t1PoE8TsOA9bzvb6g=="
+            "integrity": "sha1-sffn/HPSXn/R1FWtyU4UODAYK1o="
         },
         "chokidar": {
             "version": "2.1.8",
@@ -9203,7 +9284,7 @@
         "clamp": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/clamp/-/clamp-1.0.1.tgz",
-            "integrity": "sha512-kgMuFyE78OC6Dyu3Dy7vcx4uy97EIbVxJB/B0eJ3bUNAkwdNcxYzgKltnyADiYwsR7SEqkkUPsEUT//OVS6XMA=="
+            "integrity": "sha1-ZqDmQBGBbjcZaCj9yMjBRzEshjQ="
         },
         "class-transformer": {
             "version": "0.2.3",
@@ -9224,7 +9305,7 @@
                 "define-property": {
                     "version": "0.2.5",
                     "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
-                    "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==",
+                    "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
                     "requires": {
                         "is-descriptor": "^0.1.0"
                     }
@@ -9274,7 +9355,7 @@
         "clipboard": {
             "version": "1.7.1",
             "resolved": "https://registry.npmjs.org/clipboard/-/clipboard-1.7.1.tgz",
-            "integrity": "sha512-smkaRaIQsrnKN1F3wd1/vY9Q+DeR4L8ZCXKeHCFC2j8RZuSBbuImcLdnIO4GTxmzJxQuDGNKkyfpGoPW7Ua5bQ==",
+            "integrity": "sha1-Ng1taUbpmnof7zleQrqStem1oWs=",
             "requires": {
                 "good-listener": "^1.2.2",
                 "select": "^1.1.2",
@@ -9349,7 +9430,7 @@
         "clj-fuzzy": {
             "version": "0.3.3",
             "resolved": "https://registry.npmjs.org/clj-fuzzy/-/clj-fuzzy-0.3.3.tgz",
-            "integrity": "sha512-9cyh9A8+OphDZeKIG21MgyDHWDkWxTvagwvFLVjtdi6eToFENF7iDLlKwhHrnBQRSQwprKNhazG053nE/UgwfQ=="
+            "integrity": "sha1-seU0MJHFIC28UlMoY+HEp4RX8D0="
         },
         "clone-deep": {
             "version": "4.0.1",
@@ -9384,7 +9465,7 @@
         "collection-visit": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz",
-            "integrity": "sha512-lNkKvzEeMBBjUGHZ+q6z9pSJla0KWAQPvtzhEV9+iGyQYG+pBpl7xKDhxoNSOZH2hhv0v5k0y2yAM4o4SjoSkw==",
+            "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=",
             "requires": {
                 "map-visit": "^1.0.0",
                 "object-visit": "^1.0.0"
@@ -9410,7 +9491,7 @@
         "color-name": {
             "version": "1.1.3",
             "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
-            "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="
+            "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
         },
         "color-string": {
             "version": "1.9.1",
@@ -9545,7 +9626,7 @@
                 "bytes": {
                     "version": "3.0.0",
                     "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz",
-                    "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==",
+                    "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=",
                     "dev": true
                 },
                 "debug": {
@@ -9560,7 +9641,7 @@
                 "ms": {
                     "version": "2.0.0",
                     "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-                    "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+                    "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
                     "dev": true
                 }
             }
@@ -9568,7 +9649,7 @@
         "concat-map": {
             "version": "0.0.1",
             "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
-            "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
+            "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
         },
         "concat-stream": {
             "version": "1.6.2",
@@ -9634,7 +9715,7 @@
         "connect-flash": {
             "version": "0.1.1",
             "resolved": "https://registry.npmjs.org/connect-flash/-/connect-flash-0.1.1.tgz",
-            "integrity": "sha512-2rcfELQt/ZMP+SM/pG8PyhJRaLKp+6Hk2IUBNkEit09X+vwn3QsAL3ZbYtxUn7NVPzbMTSLRDhqe0B/eh30RYA=="
+            "integrity": "sha1-2GMPJtlaf4UfmVax6MxnMvO2qjA="
         },
         "connect-history-api-fallback": {
             "version": "1.6.0",
@@ -9692,7 +9773,7 @@
         "console-control-strings": {
             "version": "1.1.0",
             "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
-            "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ=="
+            "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4="
         },
         "constantinople": {
             "version": "3.1.2",
@@ -9773,7 +9854,7 @@
         "cookie-signature": {
             "version": "1.0.6",
             "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
-            "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ=="
+            "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
         },
         "cookies": {
             "version": "0.8.0",
@@ -9818,7 +9899,7 @@
         "copy-descriptor": {
             "version": "0.1.1",
             "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz",
-            "integrity": "sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw=="
+            "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40="
         },
         "copy-webpack-plugin": {
             "version": "4.6.0",
@@ -10035,7 +10116,7 @@
         "crypto-random-string": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz",
-            "integrity": "sha512-GsVpkFPlycH7/fRR7Dhcmnoii54gV1nz7y4CWyeFS14N+JVBBhY+r8amRHE4BwSYal7BPTDp8isvAlCxyFt3Hg=="
+            "integrity": "sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4="
         },
         "css-box-model": {
             "version": "1.2.1",
@@ -10048,7 +10129,7 @@
         "css-color-keywords": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz",
-            "integrity": "sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg=="
+            "integrity": "sha1-/qJhbcZ2spYmhrOvjb2+GAskTgU="
         },
         "css-in-js-utils": {
             "version": "2.0.1",
@@ -10514,7 +10595,7 @@
         "dashdash": {
             "version": "1.14.1",
             "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
-            "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==",
+            "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
             "requires": {
                 "assert-plus": "^1.0.0"
             }
@@ -10566,7 +10647,7 @@
         "de-indent": {
             "version": "1.0.2",
             "resolved": "https://registry.npmjs.org/de-indent/-/de-indent-1.0.2.tgz",
-            "integrity": "sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg=="
+            "integrity": "sha1-sgOOhG3DO6pXlhKNCAS0VbjB4h0="
         },
         "debounce": {
             "version": "1.2.1",
@@ -10584,7 +10665,7 @@
         "decamelize": {
             "version": "1.2.0",
             "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
-            "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA=="
+            "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA="
         },
         "decimal.js-light": {
             "version": "2.5.1",
@@ -10823,7 +10904,7 @@
         "delayed-stream": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
-            "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="
+            "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
         },
         "delegate": {
             "version": "3.2.0",
@@ -10833,7 +10914,7 @@
         "delegates": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
-            "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ=="
+            "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o="
         },
         "denque": {
             "version": "1.5.1",
@@ -10936,7 +11017,7 @@
                 "import-fresh": {
                     "version": "2.0.0",
                     "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz",
-                    "integrity": "sha512-eZ5H8rcgYazHbKC3PG4ClHNykCSxtAhxSSEM+2mb+7evD2CKF5V7c0dNum7AdpDh0ZdICwZY9sRSn8f+KH96sg==",
+                    "integrity": "sha1-2BNVwVYS04bGH53dOSLUMEgipUY=",
                     "requires": {
                         "caller-path": "^2.0.0",
                         "resolve-from": "^3.0.0"
@@ -10971,7 +11052,7 @@
                 "parse-json": {
                     "version": "4.0.0",
                     "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
-                    "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==",
+                    "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=",
                     "requires": {
                         "error-ex": "^1.3.1",
                         "json-parse-better-errors": "^1.0.1"
@@ -10985,7 +11066,7 @@
                 "resolve-from": {
                     "version": "3.0.0",
                     "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz",
-                    "integrity": "sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw=="
+                    "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g="
                 },
                 "string-width": {
                     "version": "4.2.3",
@@ -11057,7 +11138,7 @@
         "deps-regex": {
             "version": "0.1.4",
             "resolved": "https://registry.npmjs.org/deps-regex/-/deps-regex-0.1.4.tgz",
-            "integrity": "sha512-3tzwGYogSJi8HoG93R5x9NrdefZQOXgHgGih/7eivloOq6yC6O+yoFxZnkgP661twvfILONfoKRdF9GQOGx2RA=="
+            "integrity": "sha1-UYZnt2kUYKXn4KNBvnbrfOgJAYQ="
         },
         "dequal": {
             "version": "2.0.3",
@@ -11262,7 +11343,7 @@
         "double-bits": {
             "version": "1.1.1",
             "resolved": "https://registry.npmjs.org/double-bits/-/double-bits-1.1.1.tgz",
-            "integrity": "sha512-BCLEIBq0O/DWoA7BsCu/R+RP0ZXiowP8BhtJT3qeuuQEBpnS8LK/Wo6UTJQv6v8mK1fj8n90YziHLwGdM5whSg=="
+            "integrity": "sha1-WKu6RUlNpND6Nrc60RoobJGEscY="
         },
         "duplexer3": {
             "version": "0.1.5",
@@ -11301,7 +11382,7 @@
         "dynamic-dedupe": {
             "version": "0.3.0",
             "resolved": "https://registry.npmjs.org/dynamic-dedupe/-/dynamic-dedupe-0.3.0.tgz",
-            "integrity": "sha512-ssuANeD+z97meYOqd50e04Ze5qp4bPqo8cCkI4TRjZkzAUgIDTrXV1R8QCdINpiI+hw14+rYazvTRdQrz0/rFQ==",
+            "integrity": "sha1-BuRMIj9eTpTXjvnbI6ZRXOL5YqE=",
             "dev": true,
             "requires": {
                 "xtend": "^4.0.0"
@@ -11310,7 +11391,7 @@
         "ecc-jsbn": {
             "version": "0.1.2",
             "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
-            "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==",
+            "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=",
             "requires": {
                 "jsbn": "~0.1.0",
                 "safer-buffer": "^2.1.0"
@@ -11327,7 +11408,7 @@
         "ee-first": {
             "version": "1.1.1",
             "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
-            "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="
+            "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
         },
         "electron-to-chromium": {
             "version": "1.4.454",
@@ -11356,7 +11437,7 @@
         "encodeurl": {
             "version": "1.0.2",
             "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
-            "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w=="
+            "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k="
         },
         "encoding": {
             "version": "0.1.13",
@@ -11660,12 +11741,12 @@
         "escape-html": {
             "version": "1.0.3",
             "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
-            "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="
+            "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
         },
         "escape-string-regexp": {
             "version": "1.0.5",
             "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
-            "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="
+            "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
         },
         "escodegen": {
             "version": "1.14.3",
@@ -12978,7 +13059,7 @@
         "etag": {
             "version": "1.8.1",
             "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
-            "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg=="
+            "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc="
         },
         "event-target-shim": {
             "version": "5.0.1",
@@ -13049,7 +13130,7 @@
         "exeq": {
             "version": "2.4.0",
             "resolved": "https://registry.npmjs.org/exeq/-/exeq-2.4.0.tgz",
-            "integrity": "sha512-B648qbDS00nQZv9UQGLT5RbZm/5dNBX10F8oWeXcgpFHSLm1249u95t/3sn2wXdQjLhlF+edAECdshFtSr1K0Q==",
+            "integrity": "sha1-Td8qaEZIxCeteZNJzzO9dTWPiEo=",
             "requires": {
                 "bluebird": "^3.0.3",
                 "native-or-bluebird": "^1.2.0"
@@ -13058,7 +13139,7 @@
         "exif": {
             "version": "0.6.0",
             "resolved": "https://registry.npmjs.org/exif/-/exif-0.6.0.tgz",
-            "integrity": "sha512-gEwM4uanNMfLnDNKclZ7jPEA99E3rpy4ntoS6QW8u6murZjl1o8qRaPdMoC46Syg3d9/QaET0bYKhWlTwJCPgg==",
+            "integrity": "sha1-YKYmaAdlQst+T1cZnUrG830sX0o=",
             "requires": {
                 "debug": "^2.2"
             },
@@ -13074,7 +13155,7 @@
                 "ms": {
                     "version": "2.0.0",
                     "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-                    "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
+                    "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
                 }
             }
         },
@@ -13086,7 +13167,7 @@
         "expand-brackets": {
             "version": "2.1.4",
             "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz",
-            "integrity": "sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA==",
+            "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=",
             "requires": {
                 "debug": "^2.3.3",
                 "define-property": "^0.2.5",
@@ -13108,7 +13189,7 @@
                 "define-property": {
                     "version": "0.2.5",
                     "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
-                    "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==",
+                    "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
                     "requires": {
                         "is-descriptor": "^0.1.0"
                     }
@@ -13116,7 +13197,7 @@
                 "extend-shallow": {
                     "version": "2.0.1",
                     "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
-                    "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==",
+                    "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
                     "requires": {
                         "is-extendable": "^0.1.0"
                     }
@@ -13124,7 +13205,7 @@
                 "ms": {
                     "version": "2.0.0",
                     "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-                    "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
+                    "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
                 }
             }
         },
@@ -13207,7 +13288,7 @@
         "express-flash": {
             "version": "0.0.2",
             "resolved": "https://registry.npmjs.org/express-flash/-/express-flash-0.0.2.tgz",
-            "integrity": "sha512-QVUR0ZZRCaa8+iPHoUQaQJrQWcQuK/Q+19M7IUIdIEtvwhrA/ifHT7y1CVJI41YfGiOQnbGtn3uvd2vOdgu58A==",
+            "integrity": "sha1-I9GovPP5DXB5KOSJ+Whp7K0KzaI=",
             "requires": {
                 "connect-flash": "0.1.x"
             }
@@ -13264,7 +13345,7 @@
         "expressjs": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/expressjs/-/expressjs-1.0.1.tgz",
-            "integrity": "sha512-eFnQ5bMJxTZ29XwRJPV8ee/OURBBMS6Fm+b5rvMMEyz6u2IxPEh2SRzMZt9WvgnV+SMLmnzkALE1DnGG1HxJCw=="
+            "integrity": "sha1-IgMoRpoY31rWFeK3oM6ZXxf7ru8="
         },
         "ext": {
             "version": "1.7.0",
@@ -13291,7 +13372,7 @@
         "extend-shallow": {
             "version": "3.0.2",
             "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz",
-            "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==",
+            "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=",
             "requires": {
                 "assign-symbols": "^1.0.0",
                 "is-extendable": "^1.0.1"
@@ -13355,7 +13436,7 @@
                 "define-property": {
                     "version": "1.0.0",
                     "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
-                    "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==",
+                    "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
                     "requires": {
                         "is-descriptor": "^1.0.0"
                     }
@@ -13363,7 +13444,7 @@
                 "extend-shallow": {
                     "version": "2.0.1",
                     "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
-                    "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==",
+                    "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
                     "requires": {
                         "is-extendable": "^0.1.0"
                     }
@@ -13433,7 +13514,7 @@
         "extsprintf": {
             "version": "1.3.0",
             "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
-            "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g=="
+            "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU="
         },
         "fast-deep-equal": {
             "version": "3.1.3",
@@ -13459,7 +13540,7 @@
         "fast-levenshtein": {
             "version": "2.0.6",
             "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
-            "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
+            "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=",
             "dev": true
         },
         "fast-text-encoding": {
@@ -13514,7 +13595,7 @@
         "fd-slicer": {
             "version": "1.1.0",
             "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz",
-            "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==",
+            "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=",
             "requires": {
                 "pend": "~1.2.0"
             }
@@ -13522,7 +13603,7 @@
         "ffmpeg": {
             "version": "0.0.4",
             "resolved": "https://registry.npmjs.org/ffmpeg/-/ffmpeg-0.0.4.tgz",
-            "integrity": "sha512-3TgWUJJlZGQn+crJFyhsO/oNeRRnGTy6GhgS98oUCIfZrOW5haPPV7DUfOm3xJcHr5q3TJpjk2GudPutrNisRA==",
+            "integrity": "sha1-HEYN+OfaUSf2LO70v6BsWciWMMs=",
             "requires": {
                 "when": ">= 0.0.1"
             }
@@ -13577,7 +13658,7 @@
         "fill-range": {
             "version": "4.0.0",
             "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
-            "integrity": "sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==",
+            "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=",
             "requires": {
                 "extend-shallow": "^2.0.1",
                 "is-number": "^3.0.0",
@@ -13588,7 +13669,7 @@
                 "extend-shallow": {
                     "version": "2.0.1",
                     "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
-                    "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==",
+                    "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
                     "requires": {
                         "is-extendable": "^0.1.0"
                     }
@@ -13598,7 +13679,7 @@
         "filter-obj": {
             "version": "1.1.0",
             "resolved": "https://registry.npmjs.org/filter-obj/-/filter-obj-1.1.0.tgz",
-            "integrity": "sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ=="
+            "integrity": "sha1-mzERErxsYSehbgFsbF1/GeCAXFs="
         },
         "finalhandler": {
             "version": "1.2.0",
@@ -13632,7 +13713,7 @@
         "find": {
             "version": "0.1.7",
             "resolved": "https://registry.npmjs.org/find/-/find-0.1.7.tgz",
-            "integrity": "sha512-jPrupTOe/pO//3a9Ty2o4NqQCp0L46UG+swUnfFtdmtQVN8pEltKpAqR7Nuf6vWn0GBXx5w+R1MyZzqwjEIqdA==",
+            "integrity": "sha1-yGyHrxqxjyIrvjjeyGy8dg0Wpvs=",
             "requires": {
                 "traverse-chain": "~0.1.0"
             }
@@ -13781,7 +13862,7 @@
         "fluent-ffmpeg": {
             "version": "2.1.2",
             "resolved": "https://registry.npmjs.org/fluent-ffmpeg/-/fluent-ffmpeg-2.1.2.tgz",
-            "integrity": "sha512-IZTB4kq5GK0DPp7sGQ0q/BWurGHffRtQQwVkiqDgeO6wYJLLV5ZhgNOQ65loZxxuPMKZKZcICCUnaGtlxBiR0Q==",
+            "integrity": "sha1-yVLeIkD4EuvaCqgAbXd27irPfXQ=",
             "requires": {
                 "async": ">=0.2.9",
                 "which": "^1.1.1"
@@ -13864,12 +13945,12 @@
         "for-in": {
             "version": "1.0.2",
             "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
-            "integrity": "sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ=="
+            "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA="
         },
         "forever-agent": {
             "version": "0.6.1",
             "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
-            "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw=="
+            "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE="
         },
         "fork-ts-checker-webpack-plugin": {
             "version": "1.6.0",
@@ -13923,7 +14004,7 @@
         "fragment-cache": {
             "version": "0.2.1",
             "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz",
-            "integrity": "sha512-GMBAbW9antB8iZRHLoGw0b3HANt57diZYFO/HL1JGIC1MjKrdmhxvrJbupnVvpys0zsz7yBApXdQyfepKly2kA==",
+            "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=",
             "requires": {
                 "map-cache": "^0.2.2"
             }
@@ -13931,7 +14012,7 @@
         "fresh": {
             "version": "0.5.2",
             "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
-            "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q=="
+            "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac="
         },
         "from2": {
             "version": "2.3.0",
@@ -13968,7 +14049,7 @@
         "fs-extra": {
             "version": "0.26.7",
             "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.26.7.tgz",
-            "integrity": "sha512-waKu+1KumRhYv8D8gMRCKJGAMI9pRnPuEb1mvgYD0f7wBscg+h6bW4FDTmEZhB9VKxvoTtxW+Y7bnIlB7zja6Q==",
+            "integrity": "sha1-muH92UiXeY7at20JGM9C0MMYT6k=",
             "requires": {
                 "graceful-fs": "^4.1.2",
                 "jsonfile": "^2.1.0",
@@ -14047,7 +14128,7 @@
         "fs.realpath": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
-            "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
+            "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
         },
         "fsevents": {
             "version": "1.2.13",
@@ -14225,7 +14306,7 @@
         "get-func-name": {
             "version": "2.0.0",
             "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz",
-            "integrity": "sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig=="
+            "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE="
         },
         "get-intrinsic": {
             "version": "1.2.0",
@@ -14269,12 +14350,12 @@
         "get-value": {
             "version": "2.0.6",
             "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz",
-            "integrity": "sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA=="
+            "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg="
         },
         "getpass": {
             "version": "0.1.7",
             "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
-            "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==",
+            "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
             "requires": {
                 "assert-plus": "^1.0.0"
             }
@@ -14401,7 +14482,7 @@
         "golden-layout": {
             "version": "1.5.9",
             "resolved": "https://registry.npmjs.org/golden-layout/-/golden-layout-1.5.9.tgz",
-            "integrity": "sha512-iBXDQCXOTgUEQJo96zPbjDoy5bRIk9XW5l+q+pDgLnIyReqaa1aiQctNud4epsskyLt952BG521dew5Z1liSxA==",
+            "integrity": "sha1-o5vB9qZ+b4hreXwBbdkk6UJrp38=",
             "requires": {
                 "jquery": "*"
             }
@@ -14409,7 +14490,7 @@
         "good-listener": {
             "version": "1.2.2",
             "resolved": "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz",
-            "integrity": "sha512-goW1b+d9q/HIwbVYZzZ6SsTr4IgE+WA44A0GmPIQstuOrgsFcT7VEJ48nmr9GaRtNu0XTKacFLGnBPAM6Afouw==",
+            "integrity": "sha1-1TswzfkxPf+33JoNR3CWqm0UXFA=",
             "requires": {
                 "delegate": "^3.1.2"
             }
@@ -14588,7 +14669,7 @@
         "har-schema": {
             "version": "2.0.0",
             "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
-            "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q=="
+            "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI="
         },
         "har-validator": {
             "version": "5.1.5",
@@ -14650,7 +14731,7 @@
         "has-flag": {
             "version": "3.0.0",
             "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
-            "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw=="
+            "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0="
         },
         "has-property-descriptors": {
             "version": "1.0.0",
@@ -14681,12 +14762,12 @@
         "has-unicode": {
             "version": "2.0.1",
             "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
-            "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ=="
+            "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk="
         },
         "has-value": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz",
-            "integrity": "sha512-IBXk4GTsLYdQ7Rvt+GRBrFSVEkmuOUy4re0Xjd9kJSUQpnTrWR4/y9RpfexN9vkAPMFuQoeWKwqzPozRTlasGw==",
+            "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=",
             "requires": {
                 "get-value": "^2.0.6",
                 "has-values": "^1.0.0",
@@ -14696,7 +14777,7 @@
         "has-values": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz",
-            "integrity": "sha512-ODYZC64uqzmtfGMEAX/FvZiRyWLpAC3vYnNunURUnkGVTS+mI0smVsWaPydRBsE3g+ok7h960jChO8mFcWlHaQ==",
+            "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=",
             "requires": {
                 "is-number": "^3.0.0",
                 "kind-of": "^4.0.0"
@@ -14710,7 +14791,7 @@
                 "kind-of": {
                     "version": "4.0.0",
                     "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz",
-                    "integrity": "sha512-24XsCxmEbRwEDbz/qz3stgin8TTzZ1ESR56OMCN0ujYg+vRutNSiOj9bHH9u85DKgXguraugV5sFuvbD4FW/hw==",
+                    "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=",
                     "requires": {
                         "is-buffer": "^1.1.5"
                     }
@@ -14813,7 +14894,7 @@
         "hpack.js": {
             "version": "2.1.6",
             "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz",
-            "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==",
+            "integrity": "sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=",
             "dev": true,
             "requires": {
                 "inherits": "^2.0.1",
@@ -14842,7 +14923,7 @@
         "html": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/html/-/html-1.0.0.tgz",
-            "integrity": "sha512-lw/7YsdKiP3kk5PnR1INY17iJuzdAtJewxr14ozKJWbbR97znovZ0mh+WEMZ8rjc3lgTK+ID/htTjuyGKB52Kw==",
+            "integrity": "sha1-pUT6nqVJK/s6LMqCEKEL57WvH2E=",
             "requires": {
                 "concat-stream": "^1.4.7"
             }
@@ -14925,7 +15006,7 @@
         "http-browserify": {
             "version": "1.7.0",
             "resolved": "https://registry.npmjs.org/http-browserify/-/http-browserify-1.7.0.tgz",
-            "integrity": "sha512-Irf/LJXmE3cBzU1eaR4+NEX6bmVLqt1wkmDiA7kBwH7zmb0D8kBAXsDmQ88hhj/qv9iEZKlyGx/hrMcFi8sOHw==",
+            "integrity": "sha1-M3la3nLfiKz7/TZ3PO/tp2RzWyA=",
             "requires": {
                 "Base64": "~0.2.0",
                 "inherits": "~2.0.1"
@@ -14939,7 +15020,7 @@
         "http-deceiver": {
             "version": "1.2.7",
             "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz",
-            "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==",
+            "integrity": "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=",
             "dev": true
         },
         "http-errors": {
@@ -14986,7 +15067,7 @@
         "http-signature": {
             "version": "1.2.0",
             "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
-            "integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==",
+            "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=",
             "requires": {
                 "assert-plus": "^1.0.0",
                 "jsprim": "^1.2.2",
@@ -15005,12 +15086,12 @@
         "https": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/https/-/https-1.0.0.tgz",
-            "integrity": "sha512-4EC57ddXrkaF0x83Oj8sM6SLQHAWXw90Skqu2M4AEWENZ3F02dFJE/GARA8igO79tcgYqGrD7ae4f5L3um2lgg=="
+            "integrity": "sha1-PDfHrhqO65ZpBKKtHpdaGUt+06Q="
         },
         "https-browserify": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz",
-            "integrity": "sha512-J+FkSdyD+0mA0N+81tMotaRMfSL9SGi+xpD3T6YApKsc3bGSXJlfXri3VyFOeYkfLRQisDk1W+jIFFKBeUBbBg=="
+            "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM="
         },
         "https-proxy-agent": {
             "version": "5.0.1",
@@ -15062,7 +15143,7 @@
         "icss-replace-symbols": {
             "version": "1.1.0",
             "resolved": "https://registry.npmjs.org/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz",
-            "integrity": "sha512-chIaY3Vh2mh2Q3RGXttaDIzeiPvaVXJ+C4DAh/w3c37SKZ/U6PGMmuicR2EQQp9bKG8zLMCl7I+PtIoOOPp8Gg==",
+            "integrity": "sha1-Bupvg2ead0njhs/h/oEq5dsiPe0=",
             "dev": true
         },
         "icss-utils": {
@@ -15094,7 +15175,7 @@
         "ignore-by-default": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz",
-            "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA=="
+            "integrity": "sha1-SMptcvbGo68Aqa1K5odr44ieKwk="
         },
         "iink-js": {
             "version": "1.5.4",
@@ -15138,7 +15219,7 @@
         "image-size-stream": {
             "version": "1.1.0",
             "resolved": "https://registry.npmjs.org/image-size-stream/-/image-size-stream-1.1.0.tgz",
-            "integrity": "sha512-N505B5FSy2Xf5l/Haef+99TwfJqTu40hnU560+rC0Cm6cxtwVz2yRFh9WpOk1YEjfv3dI0PgVYAH0hmXQmjDcw==",
+            "integrity": "sha1-Ivou2mbG31AQh0bacUkmSy0l+Gs=",
             "requires": {
                 "image-size": "github:netroy/image-size#da2c863807a3e9602617bdd357b0de3ab4a064c1",
                 "readable-stream": "^1.0.33",
@@ -15152,12 +15233,12 @@
                 "isarray": {
                     "version": "0.0.1",
                     "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
-                    "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ=="
+                    "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8="
                 },
                 "readable-stream": {
                     "version": "1.1.14",
                     "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
-                    "integrity": "sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ==",
+                    "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=",
                     "requires": {
                         "core-util-is": "~1.0.0",
                         "inherits": "~2.0.1",
@@ -15168,14 +15249,14 @@
                 "string_decoder": {
                     "version": "0.10.31",
                     "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
-                    "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ=="
+                    "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ="
                 }
             }
         },
         "immediate": {
             "version": "3.0.6",
             "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz",
-            "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ=="
+            "integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps="
         },
         "import-fresh": {
             "version": "3.3.0",
@@ -15203,7 +15284,7 @@
         "imurmurhash": {
             "version": "0.1.4",
             "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
-            "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA=="
+            "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o="
         },
         "in-publish": {
             "version": "2.0.1",
@@ -15226,7 +15307,7 @@
         "inflight": {
             "version": "1.0.6",
             "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
-            "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
+            "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
             "requires": {
                 "once": "^1.3.0",
                 "wrappy": "1"
@@ -15243,7 +15324,7 @@
                 "camelcase": {
                     "version": "4.1.0",
                     "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz",
-                    "integrity": "sha512-FxAv7HpHrXbh3aPo4o2qxHay2lkLY3x5Mw3KeE4KQE8ysVfziWeRZDwcjauvwBSGEC/nXUPzZy8zeh4HokqOnw=="
+                    "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0="
                 }
             }
         },
@@ -15597,7 +15678,7 @@
         "is-accessor-descriptor": {
             "version": "0.1.6",
             "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz",
-            "integrity": "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==",
+            "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=",
             "requires": {
                 "kind-of": "^3.0.2"
             },
@@ -15610,7 +15691,7 @@
                 "kind-of": {
                     "version": "3.2.2",
                     "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
-                    "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==",
+                    "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
                     "requires": {
                         "is-buffer": "^1.1.5"
                     }
@@ -15639,7 +15720,7 @@
         "is-arrayish": {
             "version": "0.2.1",
             "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
-            "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg=="
+            "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0="
         },
         "is-bigint": {
             "version": "1.0.4",
@@ -15695,7 +15776,7 @@
         "is-data-descriptor": {
             "version": "0.1.4",
             "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
-            "integrity": "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==",
+            "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=",
             "requires": {
                 "kind-of": "^3.0.2"
             },
@@ -15708,7 +15789,7 @@
                 "kind-of": {
                     "version": "3.2.2",
                     "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
-                    "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==",
+                    "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
                     "requires": {
                         "is-buffer": "^1.1.5"
                     }
@@ -15743,7 +15824,7 @@
         "is-directory": {
             "version": "0.3.1",
             "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz",
-            "integrity": "sha512-yVChGzahRFvbkscn2MlwGismPO12i9+znNruC5gVEntG3qu0xQMzsGg/JFbrsqDOHtHFPci+V5aP5T9I+yeKqw=="
+            "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE="
         },
         "is-expression": {
             "version": "3.0.0",
@@ -15769,7 +15850,7 @@
         "is-extglob": {
             "version": "2.1.1",
             "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
-            "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="
+            "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI="
         },
         "is-finite": {
             "version": "1.1.0",
@@ -15779,7 +15860,7 @@
         "is-fullwidth-code-point": {
             "version": "2.0.0",
             "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
-            "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w=="
+            "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8="
         },
         "is-generator-function": {
             "version": "1.0.10",
@@ -15800,7 +15881,7 @@
         "is-in-browser": {
             "version": "1.1.3",
             "resolved": "https://registry.npmjs.org/is-in-browser/-/is-in-browser-1.1.3.tgz",
-            "integrity": "sha512-FeXIBgG/CPGd/WUxuEyvgGTEfwiG9Z4EKGxjNMRqviiIIfsmgrpnHLffEDdwUHqNva1VEW91o3xBT/m8Elgl9g=="
+            "integrity": "sha1-Vv9NtoOgeMYILrldrX3GLh0E+DU="
         },
         "is-installed-globally": {
             "version": "0.1.0",
@@ -15830,7 +15911,7 @@
         "is-number": {
             "version": "3.0.0",
             "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
-            "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==",
+            "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
             "requires": {
                 "kind-of": "^3.0.2"
             },
@@ -15843,7 +15924,7 @@
                 "kind-of": {
                     "version": "3.2.2",
                     "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
-                    "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==",
+                    "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
                     "requires": {
                         "is-buffer": "^1.1.5"
                     }
@@ -15981,7 +16062,7 @@
         "is-typedarray": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
-            "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA=="
+            "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo="
         },
         "is-url": {
             "version": "1.2.4",
@@ -16036,17 +16117,17 @@
         "isarray": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
-            "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ=="
+            "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
         },
         "isexe": {
             "version": "2.0.0",
             "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
-            "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="
+            "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA="
         },
         "isobject": {
             "version": "3.0.1",
             "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
-            "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg=="
+            "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8="
         },
         "isomorphic-fetch": {
             "version": "2.2.1",
@@ -16071,7 +16152,7 @@
         "isstream": {
             "version": "0.1.2",
             "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
-            "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g=="
+            "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo="
         },
         "its-set": {
             "version": "1.2.3",
@@ -16153,7 +16234,7 @@
         "jsbn": {
             "version": "0.1.1",
             "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
-            "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg=="
+            "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM="
         },
         "jsdom": {
             "version": "15.2.1",
@@ -16279,7 +16360,7 @@
         "json-css": {
             "version": "1.5.6",
             "resolved": "https://registry.npmjs.org/json-css/-/json-css-1.5.6.tgz",
-            "integrity": "sha512-B/0T0OxZH9tSb93tXV6VOYtXqrPz/Vgz2QrCT/4NXen8HGElYkYr9V+8IrSVTMj/ftxa8cG1kcu7f3iAMlaFlQ=="
+            "integrity": "sha1-65ZPg0ouTqobwvaY/12wB6JsfAA="
         },
         "json-parse-better-errors": {
             "version": "1.0.2",
@@ -16310,7 +16391,7 @@
         "json-stringify-safe": {
             "version": "5.0.1",
             "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
-            "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA=="
+            "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus="
         },
         "json5": {
             "version": "1.0.2",
@@ -16332,7 +16413,7 @@
         "jsonfile": {
             "version": "2.4.0",
             "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz",
-            "integrity": "sha512-PKllAqbgLgxHaj8TElYymKCAgrASebJrWpTnEkOaTowt23VKXXN0sUeriJ+eh7y6ufb/CC5ap11pz71/cM0hUw==",
+            "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=",
             "requires": {
                 "graceful-fs": "^4.1.6"
             }
@@ -16562,7 +16643,7 @@
         "klaw": {
             "version": "1.3.1",
             "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz",
-            "integrity": "sha512-TED5xi9gGQjGpNnvRWknrwAB1eL5GciPfVFOt3Vk1OJCVDQbzuSfrF3hkUQKlsgKrG1F+0t5W0m+Fje1jIt8rw==",
+            "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=",
             "requires": {
                 "graceful-fs": "^4.1.9"
             }
@@ -16707,22 +16788,22 @@
         "lodash._getnative": {
             "version": "3.9.1",
             "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz",
-            "integrity": "sha512-RrL9VxMEPyDMHOd9uFbvMe8X55X16/cGM5IgOKgRElQZutpX89iS6vwl64duTV1/16w5JY7tuFNXqoekmh1EmA=="
+            "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U="
         },
         "lodash.chunk": {
             "version": "4.2.0",
             "resolved": "https://registry.npmjs.org/lodash.chunk/-/lodash.chunk-4.2.0.tgz",
-            "integrity": "sha512-ZzydJKfUHJwHa+hF5X66zLFCBrWn5GeF28OHEr4WVWtNDXlQ/IjWKPBiikqKo2ne0+v6JgCgJ0GzJp8k8bHC7w=="
+            "integrity": "sha1-ZuXOH3btJ7QwPYxlEujRIW6BBrw="
         },
         "lodash.curry": {
             "version": "4.1.1",
             "resolved": "https://registry.npmjs.org/lodash.curry/-/lodash.curry-4.1.1.tgz",
-            "integrity": "sha512-/u14pXGviLaweY5JI0IUzgzF2J6Ne8INyzAZjImcryjgkZ+ebruBxy2/JaOOkTqScddcYtakjhSaeemV8lR0tA=="
+            "integrity": "sha1-JI42By7ekGUB11lmIAqG2riyMXA="
         },
         "lodash.debounce": {
             "version": "3.1.1",
             "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-3.1.1.tgz",
-            "integrity": "sha512-lcmJwMpdPAtChA4hfiwxTtgFeNAaow701wWUgVUqeD0XJF7vMXIN+bu/2FJSGxT0NUbZy9g9VFrlOFfPjl+0Ew==",
+            "integrity": "sha1-gSIRw3ipTMKdWqTjNGzwv846ffU=",
             "requires": {
                 "lodash._getnative": "^3.0.0"
             }
@@ -16730,27 +16811,27 @@
         "lodash.defaults": {
             "version": "4.2.0",
             "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz",
-            "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ=="
+            "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw="
         },
         "lodash.difference": {
             "version": "4.5.0",
             "resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz",
-            "integrity": "sha512-dS2j+W26TQ7taQBGN8Lbbq04ssV3emRw4NY58WErlTO29pIqS0HmoT5aJ9+TUQ1N3G+JOZSji4eugsWwGp9yPA=="
+            "integrity": "sha1-nMtOUF1Ia5FlE0V3KIWi3yf9AXw="
         },
         "lodash.flatten": {
             "version": "4.4.0",
             "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz",
-            "integrity": "sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g=="
+            "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8="
         },
         "lodash.flow": {
             "version": "3.5.0",
             "resolved": "https://registry.npmjs.org/lodash.flow/-/lodash.flow-3.5.0.tgz",
-            "integrity": "sha512-ff3BX/tSioo+XojX4MOsOMhJw0nZoUEF011LX8g8d3gvjVbxd89cCio4BCXronjxcTUIJUoqKEUA+n4CqvvRPw=="
+            "integrity": "sha1-h79AKSuM+D5OjOGjrkIJ4gBxZ1o="
         },
         "lodash.get": {
             "version": "4.4.2",
             "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz",
-            "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ=="
+            "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk="
         },
         "lodash.isequal": {
             "version": "4.5.0",
@@ -16760,12 +16841,12 @@
         "lodash.isplainobject": {
             "version": "4.0.6",
             "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
-            "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA=="
+            "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs="
         },
         "lodash.memoize": {
             "version": "4.1.2",
             "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
-            "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag=="
+            "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4="
         },
         "lodash.merge": {
             "version": "4.6.2",
@@ -16786,12 +16867,12 @@
         "lodash.throttle": {
             "version": "4.1.1",
             "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz",
-            "integrity": "sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ=="
+            "integrity": "sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ="
         },
         "lodash.union": {
             "version": "4.6.0",
             "resolved": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz",
-            "integrity": "sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw=="
+            "integrity": "sha1-SLtQiECfFvGCFmZkHETdGqrjzYg="
         },
         "log-symbols": {
             "version": "2.2.0",
@@ -16947,7 +17028,7 @@
         "map-cache": {
             "version": "0.2.2",
             "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz",
-            "integrity": "sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg=="
+            "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8="
         },
         "map-obj": {
             "version": "1.0.1",
@@ -16957,7 +17038,7 @@
         "map-visit": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz",
-            "integrity": "sha512-4y7uGv8bd2WdM9vpQsiQNo41Ln1NvhvDRuVt0k2JZQ+ezN2uaQes7lZeZ+QQUHOLQAtDaBJ+7wCbi+ab/KFs+w==",
+            "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=",
             "requires": {
                 "object-visit": "^1.0.0"
             }
@@ -17007,7 +17088,7 @@
         "math-codegen": {
             "version": "0.3.5",
             "resolved": "https://registry.npmjs.org/math-codegen/-/math-codegen-0.3.5.tgz",
-            "integrity": "sha512-SsFYMv33FxMKYxI1PBiaZT+8AeDITK+k/PKhbHNlOPHIz5FIPF4wy78yWqanN6luXdsXENUZgCIC6xH6bfUq1g==",
+            "integrity": "sha1-R5nuRnfe0Ud2bQA8ykt4ee3UDMo=",
             "requires": {
                 "extend": "^3.0.0",
                 "mr-parser": "^0.2.1"
@@ -17194,7 +17275,7 @@
         "media-typer": {
             "version": "0.3.0",
             "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
-            "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ=="
+            "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
         },
         "memfs": {
             "version": "3.4.13",
@@ -17245,7 +17326,7 @@
         "memorystream": {
             "version": "0.3.1",
             "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz",
-            "integrity": "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw=="
+            "integrity": "sha1-htcJCzDORV1j+64S3aUaR93K+bI="
         },
         "meow": {
             "version": "3.7.0",
@@ -17275,7 +17356,7 @@
         "merge-descriptors": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
-            "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w=="
+            "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E="
         },
         "merge-stream": {
             "version": "2.0.0",
@@ -17286,7 +17367,7 @@
         "methods": {
             "version": "1.1.2",
             "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
-            "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w=="
+            "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4="
         },
         "microevent.ts": {
             "version": "0.1.1",
@@ -17850,7 +17931,7 @@
                 "he": {
                     "version": "1.1.1",
                     "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz",
-                    "integrity": "sha512-z/GDPjlRMNOa2XJiB4em8wJpuuBfrFOlYKTZxtpkdr1uPdibHI8rYA3MY0KDObpVyaes0e/aunid/t88ZI2EKA==",
+                    "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=",
                     "dev": true
                 },
                 "minimatch": {
@@ -17880,7 +17961,7 @@
                 "ms": {
                     "version": "2.0.0",
                     "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-                    "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+                    "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
                     "dev": true
                 },
                 "supports-color": {
@@ -18065,14 +18146,14 @@
                 "ms": {
                     "version": "2.0.0",
                     "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-                    "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
+                    "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
                 }
             }
         },
         "mr-parser": {
             "version": "0.2.1",
             "resolved": "https://registry.npmjs.org/mr-parser/-/mr-parser-0.2.1.tgz",
-            "integrity": "sha512-hug+mpbSSKnH13rFqy3zm+XiG+QTStiDAgMTHK355TIstQE0qBkBtSJsa5YHP94AuarVX9b/4dcebdTRZ9YiEw=="
+            "integrity": "sha1-hhi5ukF+KOn0OaQcaVtVTq/u2Sc="
         },
         "mri": {
             "version": "1.2.0",
@@ -18142,7 +18223,7 @@
         "native-or-bluebird": {
             "version": "1.2.0",
             "resolved": "https://registry.npmjs.org/native-or-bluebird/-/native-or-bluebird-1.2.0.tgz",
-            "integrity": "sha512-0SH8UubxDfe382eYiwmd12qxAbiWGzlGZv6CkMA+DPojWa/Y0oH4hE0lRtFfFgJmPQFyKXeB8XxPbZz6TvvKaQ=="
+            "integrity": "sha1-OcR7/Xgl0fuf+tMiEK4l2q3xAck="
         },
         "natural-compare": {
             "version": "1.4.0",
@@ -18169,7 +18250,7 @@
         "nextafter": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/nextafter/-/nextafter-1.0.0.tgz",
-            "integrity": "sha512-7PO+A89Tll2rSEfyrjtqO0MaI37+nnxBdnQcPypfbEYYuGaJxWGCqaOwQX4a3GHNTS08l1kazuiLEWZniZjMUQ==",
+            "integrity": "sha1-t9d7U1MQ4+CX5gJauwqQNHfsGjo=",
             "requires": {
                 "double-bits": "^1.1.0"
             }
@@ -18200,7 +18281,7 @@
         "node-ensure": {
             "version": "0.0.0",
             "resolved": "https://registry.npmjs.org/node-ensure/-/node-ensure-0.0.0.tgz",
-            "integrity": "sha512-DRI60hzo2oKN1ma0ckc6nQWlHU69RH6xN0sjQTjMpChPfTYvKZdcQFfdYK2RWbJcKyUizSIy/l8OTGxMAM1QDw=="
+            "integrity": "sha1-7K52QVDemYYexcgQ/V0Jaxg5Mqc="
         },
         "node-environment-flags": {
             "version": "1.0.5",
@@ -18710,7 +18791,7 @@
             "dependencies": {
                 "@iarna/cli": {
                     "version": "2.1.0",
-                    "resolved": "https://registry.npmjs.org/@iarna/cli/-/cli-2.1.0.tgz",
+                    "resolved": false,
                     "integrity": "sha512-rvVVqDa2g860niRbqs3D5RhL4la3dc1vwk+NlpKPZxKaMSHtE2se6C2x8NeveN+rcjp3/686X+u+09CZ+7lmAQ==",
                     "requires": {
                         "glob": "^7.1.2",
@@ -18813,7 +18894,7 @@
                             "dependencies": {
                                 "safe-buffer": {
                                     "version": "5.1.2",
-                                    "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+                                    "resolved": false,
                                     "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
                                 }
                             }
@@ -18828,7 +18909,7 @@
                             "dependencies": {
                                 "safe-buffer": {
                                     "version": "5.1.2",
-                                    "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+                                    "resolved": false,
                                     "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
                                 }
                             }
@@ -18837,12 +18918,12 @@
                 },
                 "asap": {
                     "version": "2.0.6",
-                    "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz",
+                    "resolved": false,
                     "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA=="
                 },
                 "asn1": {
                     "version": "0.2.6",
-                    "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz",
+                    "resolved": false,
                     "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==",
                     "requires": {
                         "safer-buffer": "~2.1.0"
@@ -18850,7 +18931,7 @@
                 },
                 "assert-plus": {
                     "version": "1.0.0",
-                    "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
+                    "resolved": false,
                     "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw=="
                 },
                 "asynckit": {
@@ -18860,22 +18941,22 @@
                 },
                 "aws-sign2": {
                     "version": "0.7.0",
-                    "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
+                    "resolved": false,
                     "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA=="
                 },
                 "aws4": {
                     "version": "1.11.0",
-                    "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz",
+                    "resolved": false,
                     "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA=="
                 },
                 "balanced-match": {
                     "version": "1.0.2",
-                    "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+                    "resolved": false,
                     "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
                 },
                 "bcrypt-pbkdf": {
                     "version": "1.0.2",
-                    "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
+                    "resolved": false,
                     "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==",
                     "requires": {
                         "tweetnacl": "^0.14.3"
@@ -18896,7 +18977,7 @@
                 },
                 "bluebird": {
                     "version": "3.7.2",
-                    "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
+                    "resolved": false,
                     "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg=="
                 },
                 "boxen": {
@@ -18944,7 +19025,7 @@
                 },
                 "cacache": {
                     "version": "12.0.4",
-                    "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz",
+                    "resolved": false,
                     "integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==",
                     "requires": {
                         "bluebird": "^3.5.5",
@@ -18981,7 +19062,7 @@
                 },
                 "caseless": {
                     "version": "0.12.0",
-                    "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
+                    "resolved": false,
                     "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw=="
                 },
                 "chalk": {
@@ -19125,7 +19206,7 @@
                 },
                 "combined-stream": {
                     "version": "1.0.8",
-                    "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+                    "resolved": false,
                     "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
                     "requires": {
                         "delayed-stream": "~1.0.0"
@@ -19133,7 +19214,7 @@
                 },
                 "concat-map": {
                     "version": "0.0.1",
-                    "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+                    "resolved": false,
                     "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
                 },
                 "concat-stream": {
@@ -19163,7 +19244,7 @@
                             "dependencies": {
                                 "safe-buffer": {
                                     "version": "5.1.2",
-                                    "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+                                    "resolved": false,
                                     "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
                                 }
                             }
@@ -19178,7 +19259,7 @@
                             "dependencies": {
                                 "safe-buffer": {
                                     "version": "5.1.2",
-                                    "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+                                    "resolved": false,
                                     "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
                                 }
                             }
@@ -19187,7 +19268,7 @@
                 },
                 "config-chain": {
                     "version": "1.1.13",
-                    "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz",
+                    "resolved": false,
                     "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==",
                     "requires": {
                         "ini": "^1.3.4",
@@ -19288,7 +19369,7 @@
                 },
                 "dashdash": {
                     "version": "1.14.1",
-                    "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
+                    "resolved": false,
                     "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==",
                     "requires": {
                         "assert-plus": "^1.0.0"
@@ -19321,7 +19402,7 @@
                 },
                 "decode-uri-component": {
                     "version": "0.2.2",
-                    "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz",
+                    "resolved": false,
                     "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ=="
                 },
                 "deep-extend": {
@@ -19367,7 +19448,7 @@
                 },
                 "dezalgo": {
                     "version": "1.0.4",
-                    "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz",
+                    "resolved": false,
                     "integrity": "sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==",
                     "requires": {
                         "asap": "^2.0.0",
@@ -19419,7 +19500,7 @@
                             "dependencies": {
                                 "safe-buffer": {
                                     "version": "5.1.2",
-                                    "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+                                    "resolved": false,
                                     "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
                                 }
                             }
@@ -19434,7 +19515,7 @@
                             "dependencies": {
                                 "safe-buffer": {
                                     "version": "5.1.2",
-                                    "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+                                    "resolved": false,
                                     "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
                                 }
                             }
@@ -19443,7 +19524,7 @@
                 },
                 "ecc-jsbn": {
                     "version": "0.1.2",
-                    "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
+                    "resolved": false,
                     "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==",
                     "requires": {
                         "jsbn": "~0.1.0",
@@ -19478,7 +19559,7 @@
                 },
                 "env-paths": {
                     "version": "2.2.1",
-                    "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz",
+                    "resolved": false,
                     "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A=="
                 },
                 "err-code": {
@@ -19562,7 +19643,7 @@
                 },
                 "extsprintf": {
                     "version": "1.3.0",
-                    "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
+                    "resolved": false,
                     "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g=="
                 },
                 "fast-json-stable-stringify": {
@@ -19572,12 +19653,12 @@
                 },
                 "figgy-pudding": {
                     "version": "3.5.2",
-                    "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz",
+                    "resolved": false,
                     "integrity": "sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw=="
                 },
                 "filter-obj": {
                     "version": "1.1.0",
-                    "resolved": "https://registry.npmjs.org/filter-obj/-/filter-obj-1.1.0.tgz",
+                    "resolved": false,
                     "integrity": "sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ=="
                 },
                 "find-npm-prefix": {
@@ -19610,7 +19691,7 @@
                             "dependencies": {
                                 "safe-buffer": {
                                     "version": "5.1.2",
-                                    "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+                                    "resolved": false,
                                     "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
                                 }
                             }
@@ -19625,7 +19706,7 @@
                             "dependencies": {
                                 "safe-buffer": {
                                     "version": "5.1.2",
-                                    "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+                                    "resolved": false,
                                     "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
                                 }
                             }
@@ -19634,12 +19715,12 @@
                 },
                 "forever-agent": {
                     "version": "0.6.1",
-                    "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
+                    "resolved": false,
                     "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw=="
                 },
                 "form-data": {
                     "version": "2.3.3",
-                    "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
+                    "resolved": false,
                     "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
                     "requires": {
                         "asynckit": "^0.4.0",
@@ -19672,7 +19753,7 @@
                             "dependencies": {
                                 "safe-buffer": {
                                     "version": "5.1.2",
-                                    "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+                                    "resolved": false,
                                     "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
                                 }
                             }
@@ -19687,7 +19768,7 @@
                             "dependencies": {
                                 "safe-buffer": {
                                     "version": "5.1.2",
-                                    "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+                                    "resolved": false,
                                     "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
                                 }
                             }
@@ -19755,7 +19836,7 @@
                             "dependencies": {
                                 "safe-buffer": {
                                     "version": "5.1.2",
-                                    "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+                                    "resolved": false,
                                     "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
                                 }
                             }
@@ -19770,7 +19851,7 @@
                             "dependencies": {
                                 "safe-buffer": {
                                     "version": "5.1.2",
-                                    "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+                                    "resolved": false,
                                     "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
                                 }
                             }
@@ -19779,7 +19860,7 @@
                 },
                 "fs.realpath": {
                     "version": "1.0.0",
-                    "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+                    "resolved": false,
                     "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
                 },
                 "function-bind": {
@@ -19869,7 +19950,7 @@
                 },
                 "getpass": {
                     "version": "0.1.7",
-                    "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
+                    "resolved": false,
                     "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==",
                     "requires": {
                         "assert-plus": "^1.0.0"
@@ -19877,7 +19958,7 @@
                 },
                 "glob": {
                     "version": "7.2.3",
-                    "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+                    "resolved": false,
                     "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
                     "requires": {
                         "fs.realpath": "^1.0.0",
@@ -19890,7 +19971,7 @@
                     "dependencies": {
                         "minimatch": {
                             "version": "3.1.2",
-                            "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+                            "resolved": false,
                             "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
                             "requires": {
                                 "brace-expansion": "^1.1.7"
@@ -19933,12 +20014,12 @@
                 },
                 "graceful-fs": {
                     "version": "4.2.10",
-                    "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz",
+                    "resolved": false,
                     "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA=="
                 },
                 "har-schema": {
                     "version": "2.0.0",
-                    "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
+                    "resolved": false,
                     "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q=="
                 },
                 "har-validator": {
@@ -20017,7 +20098,7 @@
                 },
                 "http-signature": {
                     "version": "1.2.0",
-                    "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
+                    "resolved": false,
                     "integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==",
                     "requires": {
                         "assert-plus": "^1.0.0",
@@ -20144,7 +20225,7 @@
                 },
                 "is-cidr": {
                     "version": "3.1.1",
-                    "resolved": "https://registry.npmjs.org/is-cidr/-/is-cidr-3.1.1.tgz",
+                    "resolved": false,
                     "integrity": "sha512-Gx+oErgq1j2jAKCR2Kbq0b3wbH0vQKqZ0wOlHxm0o56nq51Cs/DZA8oz9dMDhbHyHEGgJ86eTeVudtgMMOx3Mw==",
                     "requires": {
                         "cidr-regex": "^2.0.10"
@@ -20223,7 +20304,7 @@
                 },
                 "is-typedarray": {
                     "version": "1.0.0",
-                    "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
+                    "resolved": false,
                     "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA=="
                 },
                 "isarray": {
@@ -20238,12 +20319,12 @@
                 },
                 "isstream": {
                     "version": "0.1.2",
-                    "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
+                    "resolved": false,
                     "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g=="
                 },
                 "jsbn": {
                     "version": "0.1.1",
-                    "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
+                    "resolved": false,
                     "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg=="
                 },
                 "json-parse-better-errors": {
@@ -20253,7 +20334,7 @@
                 },
                 "json-parse-even-better-errors": {
                     "version": "2.3.1",
-                    "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
+                    "resolved": false,
                     "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w=="
                 },
                 "json-schema": {
@@ -20263,7 +20344,7 @@
                 },
                 "json-stringify-safe": {
                     "version": "5.0.1",
-                    "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
+                    "resolved": false,
                     "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA=="
                 },
                 "jsonparse": {
@@ -20481,7 +20562,7 @@
                 },
                 "lock-verify": {
                     "version": "2.2.2",
-                    "resolved": "https://registry.npmjs.org/lock-verify/-/lock-verify-2.2.2.tgz",
+                    "resolved": false,
                     "integrity": "sha512-2CUNtr1ZSVKJHcYP8uEzafmmuyauCB5zZimj8TvQd/Lflt9kXVZs+8S+EbAzZLaVUDn8CYGmeC3DFGdYfnCzeQ==",
                     "requires": {
                         "@iarna/cli": "^2.1.0",
@@ -20610,7 +20691,7 @@
                 },
                 "meant": {
                     "version": "1.0.3",
-                    "resolved": "https://registry.npmjs.org/meant/-/meant-1.0.3.tgz",
+                    "resolved": false,
                     "integrity": "sha512-88ZRGcNxAq4EH38cQ4D85PM57pikCwS8Z99EWHODxN7KBY+UuPiqzRTtZzS8KTXO/ywSWbdjjJST2Hly/EQxLw=="
                 },
                 "mime-db": {
@@ -20628,7 +20709,7 @@
                 },
                 "minimatch": {
                     "version": "3.1.2",
-                    "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+                    "resolved": false,
                     "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
                     "requires": {
                         "brace-expansion": "^1.1.7"
@@ -20677,7 +20758,7 @@
                 },
                 "mkdirp": {
                     "version": "0.5.6",
-                    "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz",
+                    "resolved": false,
                     "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==",
                     "requires": {
                         "minimist": "^1.2.6"
@@ -20725,7 +20806,7 @@
                 },
                 "node-gyp": {
                     "version": "5.1.1",
-                    "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-5.1.1.tgz",
+                    "resolved": false,
                     "integrity": "sha512-WH0WKGi+a4i4DUt2mHnvocex/xPLp9pYt5R6M2JdFB7pJ7Z34hveZ4nDTGTiLXCkitA9T8HFZjhinBCiVHYcWw==",
                     "requires": {
                         "env-paths": "^2.2.0",
@@ -21063,7 +21144,7 @@
                             "dependencies": {
                                 "safe-buffer": {
                                     "version": "5.1.2",
-                                    "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+                                    "resolved": false,
                                     "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
                                 }
                             }
@@ -21078,7 +21159,7 @@
                             "dependencies": {
                                 "safe-buffer": {
                                     "version": "5.1.2",
-                                    "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+                                    "resolved": false,
                                     "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
                                 }
                             }
@@ -21092,7 +21173,7 @@
                 },
                 "path-is-absolute": {
                     "version": "1.0.1",
-                    "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+                    "resolved": false,
                     "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg=="
                 },
                 "path-is-inside": {
@@ -21112,7 +21193,7 @@
                 },
                 "performance-now": {
                     "version": "2.1.0",
-                    "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
+                    "resolved": false,
                     "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow=="
                 },
                 "pify": {
@@ -21161,7 +21242,7 @@
                 },
                 "proto-list": {
                     "version": "1.2.4",
-                    "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz",
+                    "resolved": false,
                     "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA=="
                 },
                 "protoduck": {
@@ -21184,7 +21265,7 @@
                 },
                 "psl": {
                     "version": "1.9.0",
-                    "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz",
+                    "resolved": false,
                     "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag=="
                 },
                 "pump": {
@@ -21224,12 +21305,12 @@
                 },
                 "qs": {
                     "version": "6.5.3",
-                    "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz",
+                    "resolved": false,
                     "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA=="
                 },
                 "query-string": {
                     "version": "6.14.1",
-                    "resolved": "https://registry.npmjs.org/query-string/-/query-string-6.14.1.tgz",
+                    "resolved": false,
                     "integrity": "sha512-XDxAeVmpfu1/6IjyT/gXHOl+S0vQ9owggJ30hhWKdHAsNPOcasn5o9BW0eejZqL2e4vMjhAxoW3jVHcD6mbcYw==",
                     "requires": {
                         "decode-uri-component": "^0.2.0",
@@ -21240,7 +21321,7 @@
                 },
                 "qw": {
                     "version": "1.0.2",
-                    "resolved": "https://registry.npmjs.org/qw/-/qw-1.0.2.tgz",
+                    "resolved": false,
                     "integrity": "sha512-1PhZ/iLKwlVNq45dnerTMKFjMof49uqli7/0QsvPNbX5OJ3IZ8msa9lUpvPheVdP+IYYPrf6cOaVil7S35joVA=="
                 },
                 "rc": {
@@ -21286,7 +21367,7 @@
                 },
                 "read-package-json": {
                     "version": "2.1.2",
-                    "resolved": "https://registry.npmjs.org/read-package-json/-/read-package-json-2.1.2.tgz",
+                    "resolved": false,
                     "integrity": "sha512-D1KmuLQr6ZSJS0tW8hf3WGpRlwszJOXZ3E8Yd/DNRaM5d+1wVRZdHlpGBLAuovjr28LbWvjpWkBHMxpRGGjzNA==",
                     "requires": {
                         "glob": "^7.1.1",
@@ -21345,7 +21426,7 @@
                 },
                 "request": {
                     "version": "2.88.2",
-                    "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz",
+                    "resolved": false,
                     "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==",
                     "requires": {
                         "aws-sign2": "~0.7.0",
@@ -21415,7 +21496,7 @@
                 },
                 "safe-buffer": {
                     "version": "5.2.1",
-                    "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+                    "resolved": false,
                     "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
                 },
                 "safer-buffer": {
@@ -21586,7 +21667,7 @@
                 },
                 "sshpk": {
                     "version": "1.17.0",
-                    "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz",
+                    "resolved": false,
                     "integrity": "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==",
                     "requires": {
                         "asn1": "~0.2.3",
@@ -21642,7 +21723,7 @@
                             "dependencies": {
                                 "safe-buffer": {
                                     "version": "5.1.2",
-                                    "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+                                    "resolved": false,
                                     "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
                                 }
                             }
@@ -21657,7 +21738,7 @@
                             "dependencies": {
                                 "safe-buffer": {
                                     "version": "5.1.2",
-                                    "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+                                    "resolved": false,
                                     "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
                                 }
                             }
@@ -21671,7 +21752,7 @@
                 },
                 "strict-uri-encode": {
                     "version": "2.0.0",
-                    "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz",
+                    "resolved": false,
                     "integrity": "sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ=="
                 },
                 "string-width": {
@@ -21827,7 +21908,7 @@
                             "dependencies": {
                                 "safe-buffer": {
                                     "version": "5.1.2",
-                                    "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+                                    "resolved": false,
                                     "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
                                 }
                             }
@@ -21842,7 +21923,7 @@
                             "dependencies": {
                                 "safe-buffer": {
                                     "version": "5.1.2",
-                                    "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+                                    "resolved": false,
                                     "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
                                 }
                             }
@@ -21861,7 +21942,7 @@
                 },
                 "tough-cookie": {
                     "version": "2.5.0",
-                    "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz",
+                    "resolved": false,
                     "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==",
                     "requires": {
                         "psl": "^1.1.28",
@@ -21870,7 +21951,7 @@
                     "dependencies": {
                         "punycode": {
                             "version": "2.1.1",
-                            "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
+                            "resolved": false,
                             "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A=="
                         }
                     }
@@ -21885,7 +21966,7 @@
                 },
                 "tweetnacl": {
                     "version": "0.14.5",
-                    "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
+                    "resolved": false,
                     "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA=="
                 },
                 "typedarray": {
@@ -21956,7 +22037,7 @@
                 },
                 "uri-js": {
                     "version": "4.4.1",
-                    "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+                    "resolved": false,
                     "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
                     "requires": {
                         "punycode": "^2.1.0"
@@ -21997,7 +22078,7 @@
                 },
                 "uuid": {
                     "version": "3.4.0",
-                    "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
+                    "resolved": false,
                     "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A=="
                 },
                 "validate-npm-package-license": {
@@ -22019,7 +22100,7 @@
                 },
                 "verror": {
                     "version": "1.10.0",
-                    "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
+                    "resolved": false,
                     "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==",
                     "requires": {
                         "assert-plus": "^1.0.0",
@@ -22304,7 +22385,7 @@
         "oauth": {
             "version": "0.9.15",
             "resolved": "https://registry.npmjs.org/oauth/-/oauth-0.9.15.tgz",
-            "integrity": "sha512-a5ERWK1kh38ExDEfoO6qUHJb32rd7aYmPHuyCu3Fta/cnICvYmgd2uhuKXvPD+PXB+gCEYYEaQdIRAjCOwAKNA=="
+            "integrity": "sha1-vR/vr2hslrdUda7VGWQS/2DPucE="
         },
         "oauth-sign": {
             "version": "0.9.0",
@@ -22314,12 +22395,12 @@
         "object-assign": {
             "version": "4.1.1",
             "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
-            "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="
+            "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
         },
         "object-copy": {
             "version": "0.1.0",
             "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz",
-            "integrity": "sha512-79LYn6VAb63zgtmAteVOWo9Vdj71ZVBy3Pbse+VqxDpEP83XuujMrGqHIwAXJ5I/aM0zU7dIyIAhifVTPrNItQ==",
+            "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=",
             "requires": {
                 "copy-descriptor": "^0.1.0",
                 "define-property": "^0.2.5",
@@ -22329,7 +22410,7 @@
                 "define-property": {
                     "version": "0.2.5",
                     "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
-                    "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==",
+                    "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
                     "requires": {
                         "is-descriptor": "^0.1.0"
                     }
@@ -22342,7 +22423,7 @@
                 "kind-of": {
                     "version": "3.2.2",
                     "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
-                    "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==",
+                    "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
                     "requires": {
                         "is-buffer": "^1.1.5"
                     }
@@ -22412,7 +22493,7 @@
         "object-visit": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz",
-            "integrity": "sha512-GBaMwwAVK9qbQN3Scdo0OyvgPW7l3lnaVMj84uTOZlswkX0KpF6fyDBJhtTthf7pymztoN36/KEr1DyhF96zEA==",
+            "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=",
             "requires": {
                 "isobject": "^3.0.0"
             }
@@ -22474,7 +22555,7 @@
         "object.pick": {
             "version": "1.3.0",
             "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz",
-            "integrity": "sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ==",
+            "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=",
             "requires": {
                 "isobject": "^3.0.1"
             }
@@ -22512,7 +22593,7 @@
         "once": {
             "version": "1.4.0",
             "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
-            "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+            "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
             "requires": {
                 "wrappy": "1"
             }
@@ -22613,7 +22694,7 @@
         "os-tmpdir": {
             "version": "1.0.2",
             "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
-            "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g=="
+            "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ="
         },
         "osenv": {
             "version": "0.1.5",
@@ -22632,7 +22713,7 @@
         "p-debounce": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/p-debounce/-/p-debounce-1.0.0.tgz",
-            "integrity": "sha512-ttOxn4Yt0hzIsLLqKi/Ry9QRxW+UQKdoWHz7g99Ci57zPkqUU3kbWKAeHuv+HfRLe109acYLUY6kuVCOOqnt4g=="
+            "integrity": "sha1-y38svu/YegnrqGHhErZ1J+Yh4v0="
         },
         "p-finally": {
             "version": "1.0.0",
@@ -22809,7 +22890,7 @@
         "pascalcase": {
             "version": "0.1.1",
             "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz",
-            "integrity": "sha512-XHXfu/yOQRy9vYOtUDVMN60OEJjW013GoObG1o+xwQTpB9eYJX/BjXMsdW13ZDPruFhYYn0AG22w0xgQMwl3Nw=="
+            "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ="
         },
         "passport": {
             "version": "0.4.1",
@@ -22831,7 +22912,7 @@
         "passport-local": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/passport-local/-/passport-local-1.0.0.tgz",
-            "integrity": "sha512-9wCE6qKznvf9mQYYbgJ3sVOHmCWoUNMVFoZzNoznmISbhnNNPhN9xfY3sLmScHMetEJeoY7CXwfhCe7argfQow==",
+            "integrity": "sha1-H+YyaMkudWBmJkN+O5BmYsFbpu4=",
             "requires": {
                 "passport-strategy": "1.x.x"
             }
@@ -22851,7 +22932,7 @@
         "passport-strategy": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz",
-            "integrity": "sha512-CB97UUvDKJde2V0KDWWB3lyf6PC3FaZP7YxZ2G8OAtn9p4HI9j9JLP9qjOGZFvyl8uwNT8qM+hGnz/n16NI7oA=="
+            "integrity": "sha1-tVOaqPwiWj0a0XlHbd8ja0QPUuQ="
         },
         "path-browserify": {
             "version": "1.0.1",
@@ -22866,12 +22947,12 @@
         "path-exists": {
             "version": "3.0.0",
             "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
-            "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ=="
+            "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU="
         },
         "path-is-absolute": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
-            "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg=="
+            "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
         },
         "path-is-inside": {
             "version": "1.0.2",
@@ -22881,7 +22962,7 @@
         "path-key": {
             "version": "2.0.1",
             "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
-            "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw=="
+            "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A="
         },
         "path-parse": {
             "version": "1.0.7",
@@ -22891,7 +22972,7 @@
         "path-to-regexp": {
             "version": "0.1.7",
             "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
-            "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ=="
+            "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w="
         },
         "path-type": {
             "version": "4.0.0",
@@ -22906,7 +22987,7 @@
         "pause": {
             "version": "0.0.1",
             "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz",
-            "integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg=="
+            "integrity": "sha1-HUCLP9t2kjuVQ9lvtMnf1TXZy10="
         },
         "pdf-parse": {
             "version": "1.1.1",
@@ -22954,7 +23035,7 @@
         "pend": {
             "version": "1.2.0",
             "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
-            "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg=="
+            "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA="
         },
         "perfect-scrollbar": {
             "version": "1.5.5",
@@ -22964,7 +23045,7 @@
         "performance-now": {
             "version": "2.1.0",
             "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
-            "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow=="
+            "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns="
         },
         "picocolors": {
             "version": "1.0.0",
@@ -23110,7 +23191,7 @@
         "posix-character-classes": {
             "version": "0.1.1",
             "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz",
-            "integrity": "sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg=="
+            "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs="
         },
         "postcss": {
             "version": "7.0.39",
@@ -23363,7 +23444,7 @@
         "process": {
             "version": "0.11.10",
             "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
-            "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A=="
+            "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI="
         },
         "process-nextick-args": {
             "version": "2.0.1",
@@ -23437,7 +23518,7 @@
         "prosemirror-find-replace": {
             "version": "0.9.0",
             "resolved": "https://registry.npmjs.org/prosemirror-find-replace/-/prosemirror-find-replace-0.9.0.tgz",
-            "integrity": "sha512-LfhQ/Zr0PkkJpCsr9vTJ5ZPYh49mSVVG+hHJ6djT+chlCW+t2ilSxBpBG+2IeE/I5nlbcvuLLAbxeI1g3pTCpA=="
+            "integrity": "sha1-QgsENNF5xdBJD44hSNhVGpVJY4I="
         },
         "prosemirror-history": {
             "version": "1.3.0",
@@ -23542,7 +23623,7 @@
         "prr": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz",
-            "integrity": "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==",
+            "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=",
             "dev": true
         },
         "pseudomap": {
@@ -23780,12 +23861,12 @@
         "pure-color": {
             "version": "1.3.0",
             "resolved": "https://registry.npmjs.org/pure-color/-/pure-color-1.3.0.tgz",
-            "integrity": "sha512-QFADYnsVoBMw1srW7OVKEYjG+MbIa49s54w1MA1EDY6r2r/sTcKKYqRX1f4GYvnXP7eN/Pe9HFcX+hwzmrXRHA=="
+            "integrity": "sha1-H+Bk+wrIUfDeYTIKi/eWg2Qi8z4="
         },
         "q": {
             "version": "1.5.1",
             "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz",
-            "integrity": "sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw=="
+            "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc="
         },
         "qs": {
             "version": "6.5.3",
@@ -23833,7 +23914,7 @@
         "random-bytes": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz",
-            "integrity": "sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ=="
+            "integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs="
         },
         "randombytes": {
             "version": "2.1.0",
@@ -23936,7 +24017,7 @@
         "react-base16-styling": {
             "version": "0.5.3",
             "resolved": "https://registry.npmjs.org/react-base16-styling/-/react-base16-styling-0.5.3.tgz",
-            "integrity": "sha512-EPuchwVvYPSFFIjGpH0k6wM0HQsmJ0vCk7BSl5ryxMVFIWW4hX4Kksu4PNtxfgOxDebTLkJQ8iC7zwAql0eusg==",
+            "integrity": "sha1-OFjyTpxN2MvT9wLz901YHKKRcmk=",
             "requires": {
                 "base16": "^1.0.0",
                 "lodash.curry": "^4.0.1",
@@ -24010,7 +24091,7 @@
         "react-dock": {
             "version": "0.2.4",
             "resolved": "https://registry.npmjs.org/react-dock/-/react-dock-0.2.4.tgz",
-            "integrity": "sha512-ywUJPC/TIM9PO700skka0fH4aqbrH8RojUXejZFvjtqlc5KZ+xjHqFdo4A3j+dp+0NLFZ3Nai4xzcf3FUJ9BsQ==",
+            "integrity": "sha1-5yfcdVCztzEWY13LnA4E0Lev4Xw=",
             "requires": {
                 "lodash.debounce": "^3.1.1",
                 "prop-types": "^15.5.8"
@@ -24383,7 +24464,7 @@
         "react-themeable": {
             "version": "1.1.0",
             "resolved": "https://registry.npmjs.org/react-themeable/-/react-themeable-1.1.0.tgz",
-            "integrity": "sha512-kl5tQ8K+r9IdQXZd8WLa+xxYN04lLnJXRVhHfdgwsUJr/SlKJxIejoc9z9obEkx1mdqbTw1ry43fxEUwyD9u7w==",
+            "integrity": "sha1-fURm3ZsrX6dQWHJ4JenxUro3mg4=",
             "requires": {
                 "object-assign": "^3.0.0"
             },
@@ -24391,7 +24472,7 @@
                 "object-assign": {
                     "version": "3.0.0",
                     "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz",
-                    "integrity": "sha512-jHP15vXVGeVh1HuaA2wY6lxk+whK/x4KBG88VXeRma7CCun7iGD5qPc4eYykQ9sdQvg8jkwFKsSxHln2ybW3xQ=="
+                    "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I="
                 }
             }
         },
@@ -24540,7 +24621,7 @@
         "readline": {
             "version": "1.3.0",
             "resolved": "https://registry.npmjs.org/readline/-/readline-1.3.0.tgz",
-            "integrity": "sha512-k2d6ACCkiNYz222Fs/iNze30rRJ1iIicW7JuX/7/cozvih6YCkFZH+J6mAFDVgv0dRBaAyr4jDqC95R2y4IADg=="
+            "integrity": "sha1-xYDXfvLPyHUrEySYBg3JeTp6wBw="
         },
         "recharts": {
             "version": "2.5.0",
@@ -24569,7 +24650,7 @@
         "rechoir": {
             "version": "0.6.2",
             "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz",
-            "integrity": "sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==",
+            "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=",
             "requires": {
                 "resolve": "^1.1.6"
             }
@@ -24642,9 +24723,9 @@
             "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg=="
         },
         "regenerator-transform": {
-            "version": "0.15.1",
-            "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.1.tgz",
-            "integrity": "sha512-knzmNAcuyxV+gQCufkYcvOqX/qIIfHLv0u5x79kRxuGojfYVky1f15TzZEu2Avte8QGepvUNTnLskf8E6X6Vyg==",
+            "version": "0.15.2",
+            "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz",
+            "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==",
             "requires": {
                 "@babel/runtime": "^7.8.4"
             }
@@ -24737,7 +24818,7 @@
         "relateurl": {
             "version": "0.2.7",
             "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz",
-            "integrity": "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog=="
+            "integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk="
         },
         "remark-gfm": {
             "version": "3.0.1",
@@ -24860,7 +24941,7 @@
         "repeat-string": {
             "version": "1.6.1",
             "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
-            "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w=="
+            "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc="
         },
         "repeating": {
             "version": "2.0.1",
@@ -24969,7 +25050,7 @@
         "require-directory": {
             "version": "2.1.1",
             "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
-            "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q=="
+            "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I="
         },
         "require-from-string": {
             "version": "2.0.2",
@@ -24984,7 +25065,7 @@
         "require-package-name": {
             "version": "2.0.1",
             "resolved": "https://registry.npmjs.org/require-package-name/-/require-package-name-2.0.1.tgz",
-            "integrity": "sha512-uuoJ1hU/k6M0779t3VMVIYpb2VMJk05cehCaABFhXaibcbvfgR8wKiozLjVFSzJPmQMRqIcO0HMyTFqfV09V6Q=="
+            "integrity": "sha1-wR6XJ2tluOKSP3Xav1+y7ww4Qbk="
         },
         "require_optional": {
             "version": "1.0.1",
@@ -25005,7 +25086,7 @@
         "requires-port": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
-            "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ=="
+            "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8="
         },
         "resize-observer-polyfill": {
             "version": "1.5.1",
@@ -25050,7 +25131,7 @@
         "resolve-url": {
             "version": "0.2.1",
             "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz",
-            "integrity": "sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg=="
+            "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo="
         },
         "responselike": {
             "version": "3.0.0",
@@ -25196,7 +25277,7 @@
         "safe-regex": {
             "version": "1.1.0",
             "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz",
-            "integrity": "sha512-aJXcif4xnaNUzvUuC5gcb46oTS7zvg4jpMTnuqtrEPlR3vFr4pxtdTwaF1Qs3Enjn9HK+ZlwQui+a7z0SywIzg==",
+            "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=",
             "requires": {
                 "ret": "~0.1.10"
             }
@@ -25299,7 +25380,7 @@
         "scss-loader": {
             "version": "0.0.1",
             "resolved": "https://registry.npmjs.org/scss-loader/-/scss-loader-0.0.1.tgz",
-            "integrity": "sha512-SbT/smRJjkvvdHSEdAYAplosVkrtaSwwgUlnQCOuDS5sOKNjrS/eYCMvKeV6+YxK5cCOCsOJZd3vltrXatFp+g==",
+            "integrity": "sha1-6uAXueDzjBKlMtslwiC5Avs05nE=",
             "dev": true
         },
         "scss-tokenizer": {
@@ -25329,17 +25410,17 @@
         "section-iterator": {
             "version": "2.0.0",
             "resolved": "https://registry.npmjs.org/section-iterator/-/section-iterator-2.0.0.tgz",
-            "integrity": "sha512-xvTNwcbeDayXotnV32zLb3duQsP+4XosHpb/F+tu6VzEZFmIjzPdNk6/O+QOOx5XTh08KL2ufdXeCO33p380pQ=="
+            "integrity": "sha1-v0RNev7rlK1Dw5rS+yYVFifMuio="
         },
         "select": {
             "version": "1.1.2",
             "resolved": "https://registry.npmjs.org/select/-/select-1.1.2.tgz",
-            "integrity": "sha512-OwpTSOfy6xSs1+pwcNrv0RBMOzI39Lp3qQKUTPVVPRjCdNa5JH/oPRiqsesIskK8TVgmRiHwO4KXlV2Li9dANA=="
+            "integrity": "sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0="
         },
         "select-hose": {
             "version": "2.0.0",
             "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz",
-            "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==",
+            "integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=",
             "dev": true
         },
         "selfsigned": {
@@ -25359,7 +25440,7 @@
         "semver-compare": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz",
-            "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow=="
+            "integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w="
         },
         "semver-diff": {
             "version": "2.1.0",
@@ -25428,7 +25509,7 @@
         "serve-index": {
             "version": "1.9.1",
             "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz",
-            "integrity": "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==",
+            "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=",
             "dev": true,
             "requires": {
                 "accepts": "~1.3.4",
@@ -25458,7 +25539,7 @@
                 "http-errors": {
                     "version": "1.6.3",
                     "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz",
-                    "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==",
+                    "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=",
                     "dev": true,
                     "requires": {
                         "depd": "~1.1.2",
@@ -25470,13 +25551,13 @@
                 "inherits": {
                     "version": "2.0.3",
                     "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
-                    "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==",
+                    "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
                     "dev": true
                 },
                 "ms": {
                     "version": "2.0.0",
                     "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-                    "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+                    "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
                     "dev": true
                 },
                 "setprototypeof": {
@@ -25488,7 +25569,7 @@
                 "statuses": {
                     "version": "1.5.0",
                     "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
-                    "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==",
+                    "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=",
                     "dev": true
                 }
             }
@@ -25507,7 +25588,7 @@
         "set-blocking": {
             "version": "2.0.0",
             "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
-            "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw=="
+            "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc="
         },
         "set-value": {
             "version": "2.0.1",
@@ -25523,7 +25604,7 @@
                 "extend-shallow": {
                     "version": "2.0.1",
                     "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
-                    "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==",
+                    "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
                     "requires": {
                         "is-extendable": "^0.1.0"
                     }
@@ -25541,7 +25622,7 @@
         "setimmediate": {
             "version": "1.0.5",
             "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
-            "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA=="
+            "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU="
         },
         "setprototypeof": {
             "version": "1.2.0",
@@ -25716,7 +25797,7 @@
         "shebang-command": {
             "version": "1.2.0",
             "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
-            "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==",
+            "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=",
             "requires": {
                 "shebang-regex": "^1.0.0"
             }
@@ -25724,7 +25805,7 @@
         "shebang-regex": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
-            "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ=="
+            "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM="
         },
         "shelljs": {
             "version": "0.8.5",
@@ -25759,7 +25840,7 @@
         "simple-assign": {
             "version": "0.1.0",
             "resolved": "https://registry.npmjs.org/simple-assign/-/simple-assign-0.1.0.tgz",
-            "integrity": "sha512-otdSSQzuVsmDoe5MnSm4ZgHd5sl0ak6A1CTjW1R/DUHQ8xoZuU1NUzf9x6n9Dvp3nxpvW51WNMQ/7rQ9432xDg=="
+            "integrity": "sha1-F/0wZqXz13OPUDIbsPFMooHMS6o="
         },
         "simple-concat": {
             "version": "1.0.1",
@@ -25779,7 +25860,7 @@
         "simple-swizzle": {
             "version": "0.2.2",
             "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz",
-            "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==",
+            "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=",
             "requires": {
                 "is-arrayish": "^0.3.1"
             },
@@ -25811,7 +25892,7 @@
         "sliced": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/sliced/-/sliced-1.0.1.tgz",
-            "integrity": "sha512-VZBmZP8WU3sMOZm1bdgTadsQbcscK0UM8oKxKVBs4XAhUo2Xxzm/OFMGBkPusxw9xL3Uy8LrzEqGqJhclsr0yA=="
+            "integrity": "sha1-CzpmK10Ewxd7GSa+qCsD+Dei70E="
         },
         "snapdragon": {
             "version": "0.8.2",
@@ -25839,7 +25920,7 @@
                 "define-property": {
                     "version": "0.2.5",
                     "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
-                    "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==",
+                    "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
                     "requires": {
                         "is-descriptor": "^0.1.0"
                     }
@@ -25847,7 +25928,7 @@
                 "extend-shallow": {
                     "version": "2.0.1",
                     "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
-                    "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==",
+                    "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
                     "requires": {
                         "is-extendable": "^0.1.0"
                     }
@@ -25855,7 +25936,7 @@
                 "ms": {
                     "version": "2.0.0",
                     "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-                    "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
+                    "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
                 }
             }
         },
@@ -25872,7 +25953,7 @@
                 "define-property": {
                     "version": "1.0.0",
                     "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
-                    "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==",
+                    "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
                     "requires": {
                         "is-descriptor": "^1.0.0"
                     }
@@ -25921,7 +26002,7 @@
                 "kind-of": {
                     "version": "3.2.2",
                     "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
-                    "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==",
+                    "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
                     "requires": {
                         "is-buffer": "^1.1.5"
                     }
@@ -26090,7 +26171,7 @@
         "source-map": {
             "version": "0.5.7",
             "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
-            "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ=="
+            "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w="
         },
         "source-map-js": {
             "version": "1.0.2",
@@ -26138,7 +26219,7 @@
         "sparse-bitfield": {
             "version": "3.0.3",
             "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz",
-            "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==",
+            "integrity": "sha1-/0rm5oZWBWuks+eSqzM004JzyhE=",
             "optional": true,
             "requires": {
                 "memory-pager": "^1.0.2"
@@ -26254,7 +26335,7 @@
         "sprintf-js": {
             "version": "1.0.3",
             "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
-            "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g=="
+            "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw="
         },
         "sshpk": {
             "version": "1.17.0",
@@ -26284,12 +26365,12 @@
         "standard-error": {
             "version": "1.1.0",
             "resolved": "https://registry.npmjs.org/standard-error/-/standard-error-1.1.0.tgz",
-            "integrity": "sha512-4v7qzU7oLJfMI5EltUSHCaaOd65J6S4BqKRWgzMi4EYaE5fvNabPxmAPGdxpGXqrcWjhDGI/H09CIdEuUOUeXg=="
+            "integrity": "sha1-I+UWj6HAggGJ5YEnAaeQWFENDTQ="
         },
         "standard-http-error": {
             "version": "2.0.1",
             "resolved": "https://registry.npmjs.org/standard-http-error/-/standard-http-error-2.0.1.tgz",
-            "integrity": "sha512-DX/xPIoyXQTuY6BMZK4Utyi4l3A4vFoafsfqrU6/dO4Oe/59c7PyqPd2IQj9m+ZieDg2K3RL9xOYJsabcD9IUA==",
+            "integrity": "sha1-+K6RcuPO+cs40ucIShkl9Xp8NL0=",
             "requires": {
                 "standard-error": ">= 1.1.0 < 2"
             }
@@ -26297,7 +26378,7 @@
         "static-extend": {
             "version": "0.1.2",
             "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz",
-            "integrity": "sha512-72E9+uLc27Mt718pMHt9VMNiAL4LMsmDbBva8mxWUCkT07fSzEGMYUCk0XWY6lp0j6RBAG4cJ3mWuZv2OE3s0g==",
+            "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=",
             "requires": {
                 "define-property": "^0.2.5",
                 "object-copy": "^0.1.0"
@@ -26306,7 +26387,7 @@
                 "define-property": {
                     "version": "0.2.5",
                     "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
-                    "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==",
+                    "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
                     "requires": {
                         "is-descriptor": "^0.1.0"
                     }
@@ -26345,7 +26426,7 @@
         "stealthy-require": {
             "version": "1.1.1",
             "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz",
-            "integrity": "sha512-ZnWpYnYugiOVEY5GkcuJK1io5V8QmNYChG62gSit9pQVGErXtrKuPC55ITaVSukmMta5qpMU7vqLt2Lnni4f/g=="
+            "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks="
         },
         "stop-iteration-iterator": {
             "version": "1.0.0",
@@ -26378,7 +26459,7 @@
         "stream-parser": {
             "version": "0.3.1",
             "resolved": "https://registry.npmjs.org/stream-parser/-/stream-parser-0.3.1.tgz",
-            "integrity": "sha512-bJ/HgKq41nlKvlhccD5kaCr/P+Hu0wPNKPJOH7en+YrJu/9EgqUF+88w5Jb6KNcjOFMhfX4B2asfeAtIGuHObQ==",
+            "integrity": "sha1-FhhUhpRCACGhGC/wrxkRwSl2F3M=",
             "requires": {
                 "debug": "2"
             },
@@ -26394,7 +26475,7 @@
                 "ms": {
                     "version": "2.0.0",
                     "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-                    "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
+                    "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
                 }
             }
         },
@@ -26407,7 +26488,7 @@
         "strict-uri-encode": {
             "version": "2.0.0",
             "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz",
-            "integrity": "sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ=="
+            "integrity": "sha1-ucczDHBChi9rFC3CdLvMWGbONUY="
         },
         "string-width": {
             "version": "2.1.1",
@@ -26497,7 +26578,7 @@
         "strip-ansi": {
             "version": "4.0.0",
             "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
-            "integrity": "sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==",
+            "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
             "requires": {
                 "ansi-regex": "^3.0.0"
             }
@@ -26533,7 +26614,7 @@
         "strip-json-comments": {
             "version": "2.0.1",
             "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
-            "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ=="
+            "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo="
         },
         "style-loader": {
             "version": "0.23.1",
@@ -26735,7 +26816,7 @@
         "temp-dir": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-1.0.0.tgz",
-            "integrity": "sha512-xZFXEGbG7SNC3itwBzI3RYjq/cEhBkx2hJuKGIUOcEULmkQExXiHat2z/qkISYsuR+IKumhEfKKbV5qXmhICFQ=="
+            "integrity": "sha1-CnwOom06Oa+n4OvqnB/AvE2qAR0="
         },
         "tempy": {
             "version": "0.2.1",
@@ -26817,7 +26898,7 @@
         "through": {
             "version": "2.3.8",
             "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
-            "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg=="
+            "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU="
         },
         "through2": {
             "version": "2.0.5",
@@ -26899,12 +26980,12 @@
         "to-fast-properties": {
             "version": "2.0.0",
             "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
-            "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog=="
+            "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4="
         },
         "to-object-path": {
             "version": "0.3.0",
             "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz",
-            "integrity": "sha512-9mWHdnGRuh3onocaHzukyvCZhzvr6tiflAy/JRFXcJX0TjgfWA9pk9t8CMbzmBE4Jfw58pXbkngtBtqYxzNEyg==",
+            "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=",
             "requires": {
                 "kind-of": "^3.0.2"
             },
@@ -26917,7 +26998,7 @@
                 "kind-of": {
                     "version": "3.2.2",
                     "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
-                    "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==",
+                    "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
                     "requires": {
                         "is-buffer": "^1.1.5"
                     }
@@ -26938,7 +27019,7 @@
         "to-regex-range": {
             "version": "2.1.1",
             "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz",
-            "integrity": "sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==",
+            "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=",
             "requires": {
                 "is-number": "^3.0.0",
                 "repeat-string": "^1.6.1"
@@ -26965,7 +27046,7 @@
                 "nopt": {
                     "version": "1.0.10",
                     "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz",
-                    "integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==",
+                    "integrity": "sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=",
                     "requires": {
                         "abbrev": "1"
                     }
@@ -26986,7 +27067,7 @@
         "tr46": {
             "version": "0.0.3",
             "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
-            "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="
+            "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o="
         },
         "translate-google-api": {
             "version": "1.0.4",
@@ -27014,7 +27095,7 @@
         "traverse-chain": {
             "version": "0.1.0",
             "resolved": "https://registry.npmjs.org/traverse-chain/-/traverse-chain-0.1.0.tgz",
-            "integrity": "sha512-up6Yvai4PYKhpNp5PkYtx50m3KbwQrqDwbuZP/ItyL64YEWHAvH6Md83LFLV/GRSk/BoUVwwgUzX6SOQSbsfAg=="
+            "integrity": "sha1-YdvC1Ttp/2CRoSoWj9fUMxB+QPE="
         },
         "tree-kill": {
             "version": "1.2.2",
@@ -27048,7 +27129,7 @@
         "tryit": {
             "version": "1.0.3",
             "resolved": "https://registry.npmjs.org/tryit/-/tryit-1.0.3.tgz",
-            "integrity": "sha512-6C5h3CE+0qjGp+YKYTs74xR0k/Nw/ePtl/Lp6CCf44hqBQ66qnH1sDFR5mV/Gc48EsrHLB53lCFSffQCkka3kg=="
+            "integrity": "sha1-OTvnMKlEb9Hq1tpZoBQwjzbCics="
         },
         "ts-loader": {
             "version": "5.4.5",
@@ -27266,7 +27347,7 @@
                 "strip-bom": {
                     "version": "3.0.0",
                     "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
-                    "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==",
+                    "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=",
                     "dev": true
                 }
             }
@@ -27397,7 +27478,7 @@
         "tunnel-agent": {
             "version": "0.6.0",
             "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
-            "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==",
+            "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
             "requires": {
                 "safe-buffer": "^5.0.1"
             }
@@ -27405,7 +27486,7 @@
         "tweetnacl": {
             "version": "0.14.5",
             "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
-            "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA=="
+            "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q="
         },
         "type": {
             "version": "1.2.0",
@@ -27460,7 +27541,7 @@
         "typedarray": {
             "version": "0.0.6",
             "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
-            "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA=="
+            "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c="
         },
         "typescript": {
             "version": "4.9.5",
@@ -27505,7 +27586,7 @@
                 "jsonfile": {
                     "version": "4.0.0",
                     "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
-                    "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==",
+                    "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=",
                     "requires": {
                         "graceful-fs": "^4.1.6"
                     }
@@ -27641,7 +27722,7 @@
         "unicode-trie": {
             "version": "0.3.1",
             "resolved": "https://registry.npmjs.org/unicode-trie/-/unicode-trie-0.3.1.tgz",
-            "integrity": "sha512-WgVuO0M2jDl7hVfbPgXv2LUrD81HM0bQj/bvLGiw6fJ4Zo8nNFnDrA0/hU2Te/wz6pjxCm5cxJwtLjo2eyV51Q==",
+            "integrity": "sha1-1nHd3YkQGgi6w3tqUWEBBgIFIIU=",
             "requires": {
                 "pako": "^0.2.5",
                 "tiny-inflate": "^1.0.0"
@@ -27650,7 +27731,7 @@
                 "pako": {
                     "version": "0.2.9",
                     "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz",
-                    "integrity": "sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA=="
+                    "integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU="
                 }
             }
         },
@@ -27700,7 +27781,7 @@
         "unique-string": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-1.0.0.tgz",
-            "integrity": "sha512-ODgiYu03y5g76A1I9Gt0/chLCzQjvzDy7DsZGsLOE/1MrF6wriEskSncj1+/C58Xk/kPZDppSctDybCwOSaGAg==",
+            "integrity": "sha1-nhBXzKhRq7kzmPizOuGHuZyuwRo=",
             "requires": {
                 "crypto-random-string": "^1.0.0"
             }
@@ -27773,12 +27854,12 @@
         "unpipe": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
-            "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ=="
+            "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw="
         },
         "unset-value": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz",
-            "integrity": "sha512-PcA2tsuGSF9cnySLHTLSh2qrQiJ70mn+r+Glzxv2TWZblxsxCC52BDlZoPCsz7STd9pN7EZetkWZBAvk4cgZdQ==",
+            "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=",
             "requires": {
                 "has-value": "^0.3.1",
                 "isobject": "^3.0.0"
@@ -27787,7 +27868,7 @@
                 "has-value": {
                     "version": "0.3.1",
                     "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz",
-                    "integrity": "sha512-gpG936j8/MzaeID5Yif+577c17TxaDmhuyVgSwtnL/q8UUTySg8Mecb+8Cf1otgLoD7DDH75axp86ER7LFsf3Q==",
+                    "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=",
                     "requires": {
                         "get-value": "^2.0.3",
                         "has-values": "^0.1.4",
@@ -27797,7 +27878,7 @@
                         "isobject": {
                             "version": "2.1.0",
                             "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz",
-                            "integrity": "sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA==",
+                            "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=",
                             "requires": {
                                 "isarray": "1.0.0"
                             }
@@ -27807,7 +27888,7 @@
                 "has-values": {
                     "version": "0.1.4",
                     "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz",
-                    "integrity": "sha512-J8S0cEdWuQbqD9//tlZxiMuMNmxB8PlEwvYwuxsTmR1G5RXUePEX/SJn7aD0GMLieuZYSwNH0cQuJGwnYunXRQ=="
+                    "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E="
                 }
             }
         },
@@ -27873,7 +27954,7 @@
         "urix": {
             "version": "0.1.0",
             "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz",
-            "integrity": "sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg=="
+            "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI="
         },
         "url": {
             "version": "0.11.0",
@@ -27965,12 +28046,12 @@
         "util-deprecate": {
             "version": "1.0.2",
             "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
-            "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
+            "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
         },
         "utila": {
             "version": "0.4.0",
             "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz",
-            "integrity": "sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA=="
+            "integrity": "sha1-ihagXURWV6Oupe7MWxKk+lN5dyw="
         },
         "utility-types": {
             "version": "3.10.0",
@@ -27980,7 +28061,7 @@
         "utils-merge": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
-            "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA=="
+            "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM="
         },
         "uuid": {
             "version": "3.4.0",
@@ -27990,7 +28071,7 @@
         "uuid-js": {
             "version": "0.7.5",
             "resolved": "https://registry.npmjs.org/uuid-js/-/uuid-js-0.7.5.tgz",
-            "integrity": "sha512-lJFducSMfVDO3E1wBe/zflgU25JbpX9KfF+g0k6OxIt9xeybdZd27n75vPg+4cLN55UKGjJ46w3K3q3l+8KgkQ=="
+            "integrity": "sha1-bIhtAqU9LUDc8l2RoXC0p7JblNA="
         },
         "uvu": {
             "version": "0.5.6",
@@ -28025,7 +28106,7 @@
         "valid-url": {
             "version": "1.0.9",
             "resolved": "https://registry.npmjs.org/valid-url/-/valid-url-1.0.9.tgz",
-            "integrity": "sha512-QQDsV8OnSf5Uc30CKSwG9lnhMPe6exHtTXLRYX8uMwKENy640pU+2BgBL0LRbDh/eYRahNCS7aewCx0wf3NYVA=="
+            "integrity": "sha1-HBRHm0DxOXp1eC8RXkCGRHQzogA="
         },
         "validate-npm-package-license": {
             "version": "3.0.4",
@@ -28044,12 +28125,12 @@
         "vary": {
             "version": "1.1.2",
             "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
-            "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg=="
+            "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw="
         },
         "verror": {
             "version": "1.10.0",
             "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
-            "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==",
+            "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=",
             "requires": {
                 "assert-plus": "^1.0.0",
                 "core-util-is": "1.0.2",
@@ -28221,7 +28302,7 @@
         "warning": {
             "version": "3.0.0",
             "resolved": "https://registry.npmjs.org/warning/-/warning-3.0.0.tgz",
-            "integrity": "sha512-jMBt6pUrKn5I+OGgtQ4YZLdhIeJmObddh6CsibPxyQ5yPZm1XExSyzC1LCNX7BzhxWgiHmizBWJTHJIjMjTQYQ==",
+            "integrity": "sha1-MuU3fLVy3kqwR1O9+IIcAe1gW3w=",
             "requires": {
                 "loose-envify": "^1.0.0"
             }
@@ -28253,7 +28334,7 @@
         "web-request": {
             "version": "1.0.7",
             "resolved": "https://registry.npmjs.org/web-request/-/web-request-1.0.7.tgz",
-            "integrity": "sha512-mVySwo0f8FFw77ZCEEjZ93g7SqAvWREj15FefhJgPkkylu7b185N/u3Oa92sNpMdhjcErGB7oGpOkAAIvflSjw==",
+            "integrity": "sha1-twxCs81FV3noLbaIYlOySR8r1Wk=",
             "requires": {
                 "request": "^2.69.0"
             }
@@ -28266,7 +28347,7 @@
         "webidl-conversions": {
             "version": "3.0.1",
             "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
-            "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="
+            "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE="
         },
         "webpack": {
             "version": "5.75.0",
@@ -28743,7 +28824,7 @@
         "whatwg-url": {
             "version": "5.0.0",
             "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
-            "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
+            "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=",
             "requires": {
                 "tr46": "~0.0.3",
                 "webidl-conversions": "^3.0.0"
@@ -28752,7 +28833,7 @@
         "when": {
             "version": "3.7.8",
             "resolved": "https://registry.npmjs.org/when/-/when-3.7.8.tgz",
-            "integrity": "sha512-5cZ7mecD3eYcMiCH4wtRPA5iFJZ50BJYDfckI5RRpQiktMiYTcn0ccLTZOvcbBume+1304fQztxeNzNS9Gvrnw=="
+            "integrity": "sha1-xxMLan6gRpPoQs3J56Hyqjmjn4I="
         },
         "which": {
             "version": "1.3.1",
@@ -28789,7 +28870,7 @@
         "which-module": {
             "version": "2.0.0",
             "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz",
-            "integrity": "sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q=="
+            "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho="
         },
         "which-pm-runs": {
             "version": "1.1.0",
@@ -28938,7 +29019,7 @@
         "wrappy": {
             "version": "1.0.2",
             "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
-            "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
+            "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
         },
         "write": {
             "version": "1.0.3",
@@ -29025,7 +29106,7 @@
         "xoauth2": {
             "version": "1.2.0",
             "resolved": "https://registry.npmjs.org/xoauth2/-/xoauth2-1.2.0.tgz",
-            "integrity": "sha512-hKuNbkj3q/ifCcfWnW6KURP+6ExSuLdLG007gasNhMEMKlLaejNkIA6eu5Ol1xPP0/kzTuA87XHDaAcUw5k73Q=="
+            "integrity": "sha1-8u76wRRyyXHqO8RuVU60sSMhRuU="
         },
         "xregexp": {
             "version": "4.4.1",
@@ -29120,7 +29201,7 @@
         "yauzl": {
             "version": "2.10.0",
             "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz",
-            "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==",
+            "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=",
             "requires": {
                 "buffer-crc32": "~0.2.3",
                 "fd-slicer": "~1.1.0"
diff --git a/package.json b/package.json
index 1c1bce20d..1f961687e 100644
--- a/package.json
+++ b/package.json
@@ -178,7 +178,7 @@
         "body-parser": "^1.19.2",
         "bootstrap": "^4.6.1",
         "brotli": "^1.3.3",
-        "browndash-components": "^0.0.91",
+        "browndash-components": "^0.0.92",
         "browser-assert": "^1.2.1",
         "bson": "^4.6.1",
         "canvas": "^2.9.3",
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index e8262ff3b..017fb6061 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -295,7 +295,7 @@ export class CurrentUserUtils {
             { toolTip: "Tap or drag to create a note",            title: "Note", icon: "sticky-note",   dragFactory: doc.emptyNote as Doc,       clickFactory: DocCast(doc.emptyNote)},
             { toolTip: "Tap or drag to create a flashcard",       title: "Flashcard", icon: "id-card",  dragFactory: doc.emptyFlashcard as Doc,  clickFactory: DocCast(doc.emptyFlashcard)},
             { toolTip: "Tap or drag to create an equation",       title: "Math", icon: "calculator",    dragFactory: doc.emptyEquation as Doc,   clickFactory: DocCast(doc.emptyEquation)},
-            { toolTip: "Tap or drag to create a physics simulation", title: "Simulation", icon: "atom", dragFactory: doc.emptySimulation as Doc, }, 
+            { toolTip: "Tap or drag to create a physics simulation", title: "Simulation", icon: "atom", dragFactory: doc.emptySimulation as Doc, funcs: { hidden: "IsNoviceMode()"}}, 
             { toolTip: "Tap or drag to create a note board",      title: "Notes", icon: "folder",       dragFactory: doc.emptyNoteboard as Doc,  clickFactory: DocCast(doc.emptyNoteboard)},
             { toolTip: "Tap or drag to create a collection",      title: "Col", icon: "folder",         dragFactory: doc.emptyCollection as Doc, clickFactory: DocCast(doc.emptyTab)},
             { toolTip: "Tap or drag to create a webpage",         title: "Web", icon: "globe-asia",     dragFactory: doc.emptyWebpage as Doc,    clickFactory: DocCast(doc.emptyWebpage)},
@@ -303,18 +303,19 @@ export class CurrentUserUtils {
             { toolTip: "Tap or drag to create an audio recorder", title: "Audio", icon: "microphone",   dragFactory: doc.emptyAudio as Doc,      clickFactory: DocCast(doc.emptyAudio),      openFactoryLocation: OpenWhere.overlay},
             { toolTip: "Tap or drag to create a map",             title: "Map", icon: "map-marker-alt", dragFactory: doc.emptyMap as Doc,        clickFactory: DocCast(doc.emptyMap)},
             { toolTip: "Tap or drag to create a screen grabber",  title: "Grab", icon: "photo-video",   dragFactory: doc.emptyScreengrab as Doc, clickFactory: DocCast(doc.emptyScreengrab), openFactoryLocation: OpenWhere.overlay},
-            { toolTip: "Tap or drag to create a WebCam recorder", title: "WebCam", icon: "photo-video", dragFactory: doc.emptyWebCam as Doc,     clickFactory: DocCast(doc.emptyWebCam),     openFactoryLocation: OpenWhere.overlay},
+            { toolTip: "Tap or drag to create a WebCam recorder", title: "WebCam", icon: "photo-video", dragFactory: doc.emptyWebCam as Doc,     clickFactory: DocCast(doc.emptyWebCam),     openFactoryLocation: OpenWhere.overlay, funcs: { hidden: "IsNoviceMode()"}},
             { toolTip: "Tap or drag to create a button",          title: "Button", icon: "bolt",        dragFactory: doc.emptyButton as Doc,     clickFactory: DocCast(doc.emptyButton)},
-            { toolTip: "Tap or drag to create a scripting box",   title: "Script", icon: "terminal",    dragFactory: doc.emptyScript as Doc,     clickFactory: DocCast(doc.emptyScript)},
+            { toolTip: "Tap or drag to create a scripting box",   title: "Script", icon: "terminal",    dragFactory: doc.emptyScript as Doc,     clickFactory: DocCast(doc.emptyScript), funcs: { hidden: "IsNoviceMode()"}},
             { toolTip: "Tap or drag to create a data viz node",   title: "DataViz", icon: "file",       dragFactory: doc.emptyDataViz as Doc,    clickFactory: DocCast(doc.emptyDataViz)},
-            { toolTip: "Tap or drag to create a bullet slide",    title: "PPT Slide", icon: "file",     dragFactory: doc.emptySlide as Doc,      clickFactory: DocCast(doc.emptySlide),      openFactoryLocation: OpenWhere.overlay},
-            { toolTip: "Tap or drag to create a data note",       title: "DataNote", icon: "window-maximize",dragFactory: doc.emptyHeader as Doc,clickFactory: DocCast(doc.emptyHeader),     openFactoryAsDelegate: true },
-            { toolTip: "Toggle a Calculator REPL",                title: "replviewer",  icon: "calculator",                                      clickFactory: '<ScriptingRepl />' as any,   openFactoryLocation: OpenWhere.overlay}, // hack: clickFactory is not a Doc but will get interpreted as a custom UI by the openDoc() onClick script
-            { toolTip: "Toggle an UndoStack",                     title: "undostacker", icon: "calculator",                                      clickFactory: "<UndoStack>" as any,         openFactoryLocation: OpenWhere.overlay},
+            { toolTip: "Tap or drag to create a bullet slide",    title: "PPT Slide", icon: "file",     dragFactory: doc.emptySlide as Doc,      clickFactory: DocCast(doc.emptySlide),      openFactoryLocation: OpenWhere.overlay, funcs: { hidden: "IsNoviceMode()"}},
+            { toolTip: "Tap or drag to create a data note",       title: "DataNote", icon: "window-maximize",dragFactory: doc.emptyHeader as Doc,clickFactory: DocCast(doc.emptyHeader),     openFactoryAsDelegate: true , funcs: { hidden: "IsNoviceMode()"}},
+            { toolTip: "Toggle a Calculator REPL",                title: "replviewer",  icon: "calculator",                                      clickFactory: '<ScriptingRepl />' as any,   openFactoryLocation: OpenWhere.overlay, funcs: { hidden: "IsNoviceMode()"}}, // hack: clickFactory is not a Doc but will get interpreted as a custom UI by the openDoc() onClick script
+            { toolTip: "Toggle an UndoStack",                     title: "undostacker", icon: "calculator",                                      clickFactory: "<UndoStack>" as any,         openFactoryLocation: OpenWhere.overlay, funcs: { hidden: "IsNoviceMode()"}},
           ].map(tuple => (
               { openFactoryLocation: OpenWhere.addRight, 
                 scripts: { onClick:     'openDoc(copyDragFactory(this.clickFactory,this.openFactoryAsDelegate), this.openFactoryLocation)', 
                            onDragStart: '{ return copyDragFactory(this.dragFactory,this.openFactoryAsDelegate); }'}, 
+                funcs: tuple.funcs,
                 ...tuple, }))
     }
 
@@ -323,7 +324,7 @@ export class CurrentUserUtils {
         const creatorBtns = CurrentUserUtils.creatorBtnDescriptors(doc).map((reqdOpts) => {
             const btn = dragCreatorDoc ? DocListCast(dragCreatorDoc.data).find(doc => doc.title === reqdOpts.title): undefined;
             const opts:DocumentOptions = {...OmitKeys(reqdOpts, ["funcs", "scripts", "backgroundColor"]).omit, 
-                _width: 35, _height: 35, _layout_hideContextMenu: true, _dragOnlyWithinContainer: true, 
+                _width: 60, _height: 60, _layout_hideContextMenu: true, _dragOnlyWithinContainer: true, 
                 btnType: ButtonType.ToolButton, backgroundColor: reqdOpts.backgroundColor ?? Colors.DARK_GRAY, color: Colors.WHITE, isSystem: true,
                 };
             return DocUtils.AssignScripts(DocUtils.AssignOpts(btn, opts) ?? Docs.Create.FontIconDocument(opts), reqdOpts.scripts, reqdOpts.funcs);
@@ -346,7 +347,7 @@ export class CurrentUserUtils {
             { title: "Dashboards",      toolTip: "Dashboards",      target: this.setupDashboards(doc, "myDashboards"),         ignoreClick: true, icon: "desktop",     funcs: {hidden: "IsNoviceMode()"} },
             { title: "Search",          toolTip: "Search ⌘F",       target: this.setupSearcher(doc, "mySearcher"),             ignoreClick: true, icon: "search",      },
             { title: "Files",           toolTip: "Files",           target: this.setupFilesystem(doc, "myFilesystem"),         ignoreClick: true, icon: "folder-open", },
-            { title: "Tools",           toolTip: "Tools",           target: this.setupToolsBtnPanel(doc, "myTools"),           ignoreClick: true, icon: "wrench",      funcs: {hidden: "IsNoviceMode()"} },
+            { title: "Tools",           toolTip: "Tools",           target: this.setupToolsBtnPanel(doc, "myTools"),           ignoreClick: true, icon: "wrench",      },
             { title: "Imports",         toolTip: "Imports ⌘I",      target: this.setupImportSidebar(doc, "myImports"),         ignoreClick:false, icon: "upload",      },
             { title: "Closed",          toolTip: "Recently Closed", target: this.setupRecentlyClosed(doc, "myRecentlyClosed"), ignoreClick: true, icon: "archive",     hidden: true }, // this doc is hidden from the Sidebar, but it's still being used in MyFilesystem which ignores the hidden field
             { title: "Shared",          toolTip: "Shared Docs",     target: Doc.MySharedDocs,                                  ignoreClick: true, icon: "users",       funcs: {badgeValue: badgeValue}},
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 956dac555..f3daf3ffa 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -617,8 +617,8 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P
                     }
                     let actualdW = Math.max(docwidth + dW * scale, 20);
                     let actualdH = Math.max(docheight + dH * scale, 20);
-                    let dX = !dWin ? 0 : scale * refCent[0] * (1 - (1 + dWin / refWidth));
-                    let dY = !dHin ? 0 : scale * refCent[1] * (1 - (1 + dHin / refHeight));
+                    let dX = !dWin ? 0 : (scale * refCent[0] * -dWin) / refWidth;
+                    let dY = !dHin ? 0 : (scale * refCent[1] * -dHin) / refHeight;
                     const preserveNativeDim = !doc._nativeHeightUnfrozen && !doc._nativeDimModifiable;
                     const fixedAspect = nwidth && nheight && (!doc._layout_fitWidth || preserveNativeDim || e.ctrlKey || doc.nativeHeightUnfrozen || doc.nativeDimModifiable);
                     if (fixedAspect) {
@@ -630,6 +630,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P
                             } else {
                                 if (!doc._layout_fitWidth || preserveNativeDim) {
                                     actualdH = (nheight / nwidth) * actualdW;
+                                    dYin && (dY = -dW * scale * (nheight / nwidth));
                                     doc._height = actualdH;
                                 } else if (!modifyNativeDim || dragBotRight) {
                                     doc._height = actualdH;
@@ -646,6 +647,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P
                             } else {
                                 if (!doc._layout_fitWidth || preserveNativeDim) {
                                     actualdW = (nwidth / nheight) * actualdH;
+                                    dXin && (dX = -dH * scale * (nwidth / nheight));
                                     doc._width = actualdW;
                                 } else if (!modifyNativeDim || dragBotRight) {
                                     doc._width = actualdW;
diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx
index 4a986cb54..d60617020 100644
--- a/src/client/views/EditableView.tsx
+++ b/src/client/views/EditableView.tsx
@@ -232,7 +232,7 @@ export class EditableView extends React.Component<EditableProps> {
                     onChange: this.props.autosuggestProps.onChange,
                 }}
             />
-        ) : 
+        ) : (
             <input
                 className="editableView-input"
                 ref={r => (this._inputref = r)}
@@ -248,6 +248,7 @@ export class EditableView extends React.Component<EditableProps> {
                 onClick={this.stopPropagation}
                 onPointerUp={this.stopPropagation}
             />
+        );
         // ) : (
         //     <textarea
         //         className="editableView-input"
diff --git a/src/client/views/collections/CollectionMasonryViewFieldRow.tsx b/src/client/views/collections/CollectionMasonryViewFieldRow.tsx
index 22beb19de..06522b85e 100644
--- a/src/client/views/collections/CollectionMasonryViewFieldRow.tsx
+++ b/src/client/views/collections/CollectionMasonryViewFieldRow.tsx
@@ -7,7 +7,6 @@ import { DocData } from '../../../fields/DocSymbols';
 import { Id } from '../../../fields/FieldSymbols';
 import { PastelSchemaPalette, SchemaHeaderField } from '../../../fields/SchemaHeaderField';
 import { ScriptField } from '../../../fields/ScriptField';
-import { NumCast, StrCast } from '../../../fields/Types';
 import { emptyFunction, numberRange, returnEmptyString, returnFalse, setupMoveUpEvents } from '../../../Utils';
 import { Docs } from '../../documents/Documents';
 import { DragManager } from '../../util/DragManager';
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index 056204ad3..e4a0d6dad 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -598,7 +598,7 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection
                             action((entries: any) => {
                                 if (this.layoutDoc._layout_autoHeight && ref && this.refList.length && !SnappingManager.GetIsDragging()) {
                                     const height = this.refList.reduce((p, r) => p + Number(getComputedStyle(r).height.replace('px', '')), 0);
-                                    this.props.setHeight?.(this.headerMargin + height);
+                                    this.props.setHeight?.(2 * this.headerMargin + height); // bcz: added 2x for header to fix problem with scrollbars appearing in Tools panel
                                 }
                             })
                         );
diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx
index 6e0ccd4be..25a547066 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -903,6 +903,7 @@ export class TreeView extends React.Component<TreeViewProps> {
                 height={12}
                 sizeToContent={true}
                 fontSize={12}
+                isEditingCallback={action(e => (this._editTitle = e))}
                 GetValue={() => StrCast(this.doc.title)}
                 OnTab={undoBatch((shift?: boolean) => {
                     if (!shift) this.props.indentDocument?.(true);
diff --git a/src/client/views/nodes/EquationBox.scss b/src/client/views/nodes/EquationBox.scss
index 9714e1bd0..f5871db22 100644
--- a/src/client/views/nodes/EquationBox.scss
+++ b/src/client/views/nodes/EquationBox.scss
@@ -1,8 +1,9 @@
-@import "../global/globalCssVariables.scss";
+@import '../global/globalCssVariables.scss';
 
 .equationBox-cont {
-    transform-origin: top left;
+    transform-origin: center;
+    background-color: #e7e7e7;
     > span {
-        width: 100%; 
+        width: 100%;
     }
-}
\ No newline at end of file
+}
diff --git a/src/client/views/nodes/FontIconBox/FontIconBox.tsx b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
index ad3532502..91eac675f 100644
--- a/src/client/views/nodes/FontIconBox/FontIconBox.tsx
+++ b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
@@ -378,38 +378,26 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
     }
 
     render() {
-        // determine dash button metadata
         const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color);
-        const tooltip: string = StrCast(this.rootDoc.toolTip);
-        const onClickScript = ScriptCast(this.rootDoc.onClick);
-        // TODO:glr Add label of button type
-        let button: JSX.Element = this.defaultButton;
+        const tooltip = StrCast(this.rootDoc.toolTip);
+        const scriptFunc = () => ScriptCast(this.rootDoc.onClick)?.script.run({ this: this.layoutDoc, self: this.rootDoc, _readOnly_: false });
+        const btnProps = { tooltip, icon: this.Icon(color)!, label: this.label };
         // prettier-ignore
         switch (this.type) {
-            case ButtonType.EditableText: 
-                button = this.editableText; break;
-            case ButtonType.DropdownList:
-                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.MultiToggleButton: 
-                button = this.multiToggleButton; break; 
-            case ButtonType.ToggleButton: button = this.toggleButton; break;
+            case ButtonType.NumberSliderButton: return this.numberDropdown;
+            case ButtonType.EditableText:       return this.editableText; 
+            case ButtonType.DropdownList:       return this.dropdownListButton;
+            case ButtonType.ColorButton:        return this.colorButton; 
+            case ButtonType.DropdownButton:     return this.dropdownButton;
+            case ButtonType.MultiToggleButton:  return this.multiToggleButton;
+            case ButtonType.ToggleButton:       return this.toggleButton;
             case ButtonType.ClickButton:
-            case ButtonType.ToolButton: 
-                button = <IconButton tooltip={tooltip} color={color} icon={this.Icon(color)!} label={this.label}/>; break;
-            case ButtonType.TextButton: 
-                button = <Button tooltip={tooltip} icon={this.Icon(color)!} text={StrCast(this.rootDoc.buttonText)} label={this.label}/>; break;
-            case ButtonType.MenuButton: 
-                button = <IconButton tooltip={tooltip} onPointerDown={() => onClickScript?.script.run({ this: this.layoutDoc, self: this.rootDoc, _readOnly_: false })} tooltipPlacement='right' size={Size.LARGE} color={color} icon={this.Icon(color)!} label={this.label}/>; break;
+            case ButtonType.ToolButton: return <IconButton {...btnProps} size={Size.LARGE} color={color} />;
+            case ButtonType.TextButton: return <Button     {...btnProps} text={StrCast(this.rootDoc.buttonText)}/>;
+            case ButtonType.MenuButton: return <IconButton {...btnProps} color={color}  size={Size.LARGE} tooltipPlacement='right' onPointerDown={scriptFunc} />; 
         }
-
-        return button;
+        return this.defaultButton;
     }
 }
-- 
cgit v1.2.3-70-g09d2


From 372face940712d239d48f9884ded34d82d170a94 Mon Sep 17 00:00:00 2001
From: geireann <geireann.lindfield@gmail.com>
Date: Tue, 15 Aug 2023 15:33:28 -0400
Subject: trying to prevent colorpicker from generating undo event for every
 drag movement.

---
 package-lock.json                                  | 64 +++++++++++-----------
 package.json                                       |  2 +-
 src/client/views/nodes/FontIconBox/FontIconBox.tsx | 11 +++-
 3 files changed, 41 insertions(+), 36 deletions(-)

(limited to 'src/client/views/nodes/FontIconBox/FontIconBox.tsx')

diff --git a/package-lock.json b/package-lock.json
index 1d334cbeb..7be724df1 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -6507,9 +6507,9 @@
             }
         },
         "browndash-components": {
-            "version": "0.0.93",
-            "resolved": "https://registry.npmjs.org/browndash-components/-/browndash-components-0.0.93.tgz",
-            "integrity": "sha512-JL9Hi7Nq+zHZtjLCQSuGhID0Hd7X6sARutyJqbECfsLWACsIC/JfeEQZdUeH5CqO+R7pJKeoWM82AIkWGtN2Xw==",
+            "version": "0.0.95",
+            "resolved": "https://registry.npmjs.org/browndash-components/-/browndash-components-0.0.95.tgz",
+            "integrity": "sha512-1sTyIyzngLSMWqit7bysNH3Xb24QEXsctlm1u14RBK8826Q8ALlK1YxbFMYjzFMNK1WggC0TQ31VdKA3iuTamQ==",
             "requires": {
                 "@emotion/react": "^11.11.1",
                 "@emotion/styled": "^11.11.0",
@@ -6627,14 +6627,14 @@
                     "integrity": "sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww=="
                 },
                 "@mui/base": {
-                    "version": "5.0.0-beta.10",
-                    "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-beta.10.tgz",
-                    "integrity": "sha512-moTAhGwFfQffj7hsu61FnqcGqVcd53A1CrOhnskM9TF0Uh2rnLDMCuar4JRUWWpaJofAfQEbQBBFPadFQLI4PA==",
+                    "version": "5.0.0-beta.11",
+                    "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-beta.11.tgz",
+                    "integrity": "sha512-FdKZGPd8qmC3ZNke7CNhzcEgToc02M6WYZc9hcBsNQ17bgAd3s9F//1bDDYgMVBYxDM71V0sv/hBHlOY4I1ZVA==",
                     "requires": {
                         "@babel/runtime": "^7.22.6",
                         "@emotion/is-prop-valid": "^1.2.1",
                         "@mui/types": "^7.2.4",
-                        "@mui/utils": "^5.14.4",
+                        "@mui/utils": "^5.14.5",
                         "@popperjs/core": "^2.11.8",
                         "clsx": "^2.0.0",
                         "prop-types": "^15.8.1",
@@ -6652,21 +6652,21 @@
                     }
                 },
                 "@mui/core-downloads-tracker": {
-                    "version": "5.14.4",
-                    "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.14.4.tgz",
-                    "integrity": "sha512-pW2XghSi3hpYKX57Wu0SCWMTSpzvXZmmucj3TcOJWaCiFt4xr05w2gcwBZi36dAp9uvd9//9N51qbblmnD+GPg=="
+                    "version": "5.14.5",
+                    "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.14.5.tgz",
+                    "integrity": "sha512-+wpGH1USwPcKMFPMvXqYPC6fEvhxM3FzxC8lyDiNK/imLyyJ6y2DPb1Oue7OGIKJWBmYBqrWWtfovrxd1aJHTA=="
                 },
                 "@mui/material": {
-                    "version": "5.14.4",
-                    "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.14.4.tgz",
-                    "integrity": "sha512-2XUV3KyRC07BQPPzEgd+ss3x/ezXtHeKtOGCMCNmx3MauZojPYUpSwFkE0fYgYCD9dMQMVG4DY/VF38P0KShsg==",
+                    "version": "5.14.5",
+                    "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.14.5.tgz",
+                    "integrity": "sha512-4qa4GMfuZH0Ai3mttk5ccXP8a3sf7aPlAJwyMrUSz6h9hPri6BPou94zeu3rENhhmKLby9S/W1y+pmficy8JKA==",
                     "requires": {
                         "@babel/runtime": "^7.22.6",
-                        "@mui/base": "5.0.0-beta.10",
-                        "@mui/core-downloads-tracker": "^5.14.4",
-                        "@mui/system": "^5.14.4",
+                        "@mui/base": "5.0.0-beta.11",
+                        "@mui/core-downloads-tracker": "^5.14.5",
+                        "@mui/system": "^5.14.5",
                         "@mui/types": "^7.2.4",
-                        "@mui/utils": "^5.14.4",
+                        "@mui/utils": "^5.14.5",
                         "@types/react-transition-group": "^4.4.6",
                         "clsx": "^2.0.0",
                         "csstype": "^3.1.2",
@@ -6686,12 +6686,12 @@
                     }
                 },
                 "@mui/private-theming": {
-                    "version": "5.14.4",
-                    "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.14.4.tgz",
-                    "integrity": "sha512-ISXsHDiQ3z1XA4IuKn+iXDWvDjcz/UcQBiFZqtdoIsEBt8CB7wgdQf3LwcwqO81dl5ofg/vNQBEnXuKfZHrnYA==",
+                    "version": "5.14.5",
+                    "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.14.5.tgz",
+                    "integrity": "sha512-cC4C5RrpXpDaaZyH9QwmPhRLgz+f2SYbOty3cPkk4qPSOSfif2ZEcDD9HTENKDDd9deB+xkPKzzZhi8cxIx8Ig==",
                     "requires": {
                         "@babel/runtime": "^7.22.6",
-                        "@mui/utils": "^5.14.4",
+                        "@mui/utils": "^5.14.5",
                         "prop-types": "^15.8.1"
                     },
                     "dependencies": {
@@ -6727,15 +6727,15 @@
                     }
                 },
                 "@mui/system": {
-                    "version": "5.14.4",
-                    "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.14.4.tgz",
-                    "integrity": "sha512-oPgfWS97QNfHcDBapdkZIs4G5i85BJt69Hp6wbXF6s7vi3Evcmhdk8AbCRW6n0sX4vTj8oe0mh0RIm1G2A1KDA==",
+                    "version": "5.14.5",
+                    "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.14.5.tgz",
+                    "integrity": "sha512-mextXZHDeGcR7E1kx43TRARrVXy+gI4wzpUgNv7MqZs1dvTVXQGVeAT6ydj9d6FUqHBPMNLGV/21vJOrpqsL+w==",
                     "requires": {
                         "@babel/runtime": "^7.22.6",
-                        "@mui/private-theming": "^5.14.4",
+                        "@mui/private-theming": "^5.14.5",
                         "@mui/styled-engine": "^5.13.2",
                         "@mui/types": "^7.2.4",
-                        "@mui/utils": "^5.14.4",
+                        "@mui/utils": "^5.14.5",
                         "clsx": "^2.0.0",
                         "csstype": "^3.1.2",
                         "prop-types": "^15.8.1"
@@ -6752,9 +6752,9 @@
                     }
                 },
                 "@mui/utils": {
-                    "version": "5.14.4",
-                    "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.14.4.tgz",
-                    "integrity": "sha512-4ANV0txPD3x0IcTCSEHKDWnsutg1K3m6Vz5IckkbLXVYu17oOZCVUdOKsb/txUmaCd0v0PmSRe5PW+Mlvns5dQ==",
+                    "version": "5.14.5",
+                    "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.14.5.tgz",
+                    "integrity": "sha512-6Hzw63VR9C5xYv+CbjndoRLU6Gntal8rJ5W+GUzkyHrGWIyYPWZPa6AevnyGioySNETATe1H9oXS8f/7qgIHJA==",
                     "requires": {
                         "@babel/runtime": "^7.22.6",
                         "@types/prop-types": "^15.7.5",
@@ -8787,9 +8787,9 @@
                     "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g=="
                 },
                 "postcss": {
-                    "version": "8.4.27",
-                    "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.27.tgz",
-                    "integrity": "sha512-gY/ACJtJPSmUFPDCHtX78+01fHa64FaU4zaaWfuh1MhGJISufJAH4cun6k/8fwsHYeK4UQmENQK+tRLCFJE8JQ==",
+                    "version": "8.4.28",
+                    "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.28.tgz",
+                    "integrity": "sha512-Z7V5j0cq8oEKyejIKfpD8b4eBy9cwW2JWPk0+fB1HOAMsfHbnAXLLS+PfVWlzMSLQaWttKDt607I0XHmpE67Vw==",
                     "requires": {
                         "nanoid": "^3.3.6",
                         "picocolors": "^1.0.0",
diff --git a/package.json b/package.json
index aff438dd9..63f6a7040 100644
--- a/package.json
+++ b/package.json
@@ -178,7 +178,7 @@
         "body-parser": "^1.19.2",
         "bootstrap": "^4.6.1",
         "brotli": "^1.3.3",
-        "browndash-components": "^0.0.93",
+        "browndash-components": "^0.0.95",
         "browser-assert": "^1.2.1",
         "bson": "^4.6.1",
         "canvas": "^2.9.3",
diff --git a/src/client/views/nodes/FontIconBox/FontIconBox.tsx b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
index 91eac675f..1b2209224 100644
--- a/src/client/views/nodes/FontIconBox/FontIconBox.tsx
+++ b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
@@ -267,20 +267,25 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
         return ScriptCast(this.rootDoc.script);
     }
 
+    colorBatch:UndoManager.Batch|undefined;
     /**
      * Color button
      */
     @computed get colorButton() {
         const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color);
-        const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor);
         const curColor = this.colorScript?.script.run({ this: this.layoutDoc, self: this.rootDoc, value: undefined, _readOnly_: true }).result ?? 'transparent';
         const tooltip: string = StrCast(this.rootDoc.toolTip);
 
         return (
             <ColorPicker
                 setSelectedColor={value => {
-                    const s = this.colorScript;
-                    s && undoable(() => s.script.run({ this: this.layoutDoc, self: this.rootDoc, value: value, _readOnly_: false }).result, `Set ${tooltip} to ${value}`)();
+                    if (!this.colorBatch) this.colorBatch = UndoManager.StartBatch(`Set ${tooltip} color`);
+                    this.colorScript?.script.run({ this: this.layoutDoc, self: this.rootDoc, value: value, _readOnly_: false });
+                }}
+                setFinalColor={value => {
+                    this.colorScript?.script.run({ this: this.layoutDoc, self: this.rootDoc, value: value, _readOnly_: false });
+                    this.colorBatch?.end();
+                    this.colorBatch= undefined;
                 }}
                 selectedColor={curColor}
                 type={Type.PRIM}
-- 
cgit v1.2.3-70-g09d2


From 0eb9d37a9dd1a6539f331f953d5f20c761d5f940 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Thu, 17 Aug 2023 10:00:10 -0400
Subject: fixed brushing of pinned viewports for chrome to not flash. converted
 pres<Property> to config_<property> and treeView<Property> to
 treeView_Property.  fixed text toolbar to show/set text properties based on
 insertion point.

---
 src/client/documents/Documents.ts                  | 101 ++--
 src/client/util/CurrentUserUtils.ts                |  38 +-
 src/client/util/DocumentManager.ts                 |   6 +-
 src/client/views/DashboardView.tsx                 |  15 +-
 src/client/views/DocumentButtonBar.tsx             |   6 +-
 src/client/views/InkStroke.scss                    |   1 +
 src/client/views/InkingStroke.tsx                  |   6 +-
 src/client/views/MainView.tsx                      |   4 +-
 src/client/views/MarqueeAnnotator.tsx              |   2 +-
 src/client/views/PropertiesView.scss               |  88 ++--
 src/client/views/PropertiesView.tsx                |  32 +-
 src/client/views/StyleProvider.tsx                 |   8 +-
 src/client/views/TemplateMenu.tsx                  |   2 +-
 .../views/collections/CollectionTimeView.tsx       |   6 +-
 .../views/collections/CollectionTreeView.tsx       |  22 +-
 src/client/views/collections/CollectionView.tsx    |   2 +-
 src/client/views/collections/TabDocView.tsx        |  45 +-
 src/client/views/collections/TreeView.tsx          |  90 ++--
 .../collectionFreeForm/CollectionFreeFormView.scss |   7 +-
 .../collectionFreeForm/CollectionFreeFormView.tsx  |  46 +-
 src/client/views/linking/LinkMenuItem.tsx          |   2 +-
 src/client/views/nodes/DataVizBox/DataVizBox.tsx   | 111 ++--
 .../nodes/DataVizBox/components/Histogram.tsx      | 534 ++++++++++---------
 .../nodes/DataVizBox/components/LineChart.tsx      | 105 ++--
 .../views/nodes/DataVizBox/components/PieChart.tsx | 401 ++++++++-------
 .../views/nodes/DataVizBox/components/TableBox.tsx |  87 ++--
 src/client/views/nodes/DocumentView.tsx            |  17 +-
 src/client/views/nodes/FontIconBox/FontIconBox.tsx |   4 +-
 src/client/views/nodes/FunctionPlotBox.tsx         |   4 +-
 src/client/views/nodes/ImageBox.tsx                |  14 +-
 src/client/views/nodes/KeyValueBox.tsx             |  17 +-
 src/client/views/nodes/LinkBox.tsx                 |   2 +-
 src/client/views/nodes/MapBox/MapBox.tsx           |   2 +-
 src/client/views/nodes/MapBox/MapBox2.tsx          |   2 +-
 src/client/views/nodes/PDFBox.tsx                  |   6 +-
 src/client/views/nodes/WebBox.tsx                  |  16 +-
 .../views/nodes/formattedText/FormattedTextBox.tsx |  29 +-
 .../formattedText/ProsemirrorExampleTransfer.ts    |   2 +-
 .../views/nodes/formattedText/RichTextMenu.tsx     |   2 +-
 src/client/views/nodes/trails/PresBox.tsx          | 567 +++++++++++----------
 src/client/views/nodes/trails/PresElementBox.tsx   |  50 +-
 src/client/views/pdf/Annotation.tsx                |   4 +-
 src/client/views/pdf/PDFViewer.tsx                 |   8 +-
 src/fields/Doc.ts                                  |   8 +-
 src/fields/documentSchemas.ts                      |  10 +-
 45 files changed, 1334 insertions(+), 1197 deletions(-)

(limited to 'src/client/views/nodes/FontIconBox/FontIconBox.tsx')

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 5c33e319d..96a983153 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -288,12 +288,12 @@ export class DocumentOptions {
     _isTimelineLabel?: BOOLt = new BoolInfo('is document a timeline label');
     _isLightbox?: BOOLt = new BoolInfo('whether a collection acts as a lightbox by opening lightbox links by hiding all other documents in collection besides link target');
 
-    presPanX?: NUMt = new NumInfo('panX saved as a view spec');
-    presPanY?: NUMt = new NumInfo('panY saved as a view spec');
-    presViewScale?: NUMt = new NumInfo('viewScale saved as a view Spec');
-    presTransition?: NUMt = new NumInfo('the time taken for the transition TO a document');
-    presDuration?: NUMt = new NumInfo('the duration of the slide in presentation view');
-    presZoomText?: BOOLt = new BoolInfo('whether text anchors should shown in a larger box when following links to make them stand out');
+    config_panX?: NUMt = new NumInfo('panX saved as a view spec');
+    config_panY?: NUMt = new NumInfo('panY saved as a view spec');
+    config_viewScale?: NUMt = new NumInfo('viewScale saved as a view Spec');
+    presentation_transition?: NUMt = new NumInfo('the time taken for the transition TO a document');
+    presentation_duration?: NUMt = new NumInfo('the duration of the slide in presentation view');
+    presentation_zoomText?: BOOLt = new BoolInfo('whether text anchors should shown in a larger box when following links to make them stand out');
 
     data?: any;
     data_useCors?: BOOLt = new BoolInfo('whether CORS protocol should be used for web page');
@@ -378,21 +378,21 @@ export class DocumentOptions {
     onDragStart?: ScriptField; //script to execute at start of drag operation --  e.g., when a "creator" button is dragged this script generates a different document to drop
     target?: Doc; // available for use in scripts.  used to provide a document parameter to the script (Note, this is a convenience entry since any field could be used for parameterizing a script)
 
-    treeViewHideTitle?: BOOLt = new BoolInfo('whether to hide the top document title of a tree view');
-    treeViewHideUnrendered?: BOOLt = new BoolInfo("tells tree view not to display documents that have an 'layout_unrendered' tag unless they also have a treeViewFieldKey tag (presBox)");
-    treeViewHideHeaderIfTemplate?: BOOLt = new BoolInfo('whether to hide the header for a document in a tree view only if a childLayoutTemplate is provided (presBox)');
-    treeViewHideHeader?: BOOLt = new BoolInfo('whether to hide the header for a document in a tree view');
-    treeViewHideHeaderFields?: BOOLt = new BoolInfo('whether to hide the drop down options for tree view items.');
-    treeViewChildDoubleClick?: ScriptField; //
-    treeViewOpenIsTransient?: BOOLt = new BoolInfo("ignores the treeViewOpen Doc flag, allowing a treeViewItem's expand/collapse state to be independent of other views of the same document in the same or any other tree view");
-    treeViewOpen?: BOOLt = new BoolInfo('whether this document is expanded in a tree view');
-    treeViewExpandedView?: string; // which field/thing is displayed when this item is opened in tree view
-    treeViewExpandedViewLock?: BOOLt = new BoolInfo('whether the expanded view can be changed');
-    treeViewChecked?: ScriptField; // script to call when a tree view checkbox is checked
-    treeViewTruncateTitleWidth?: NUMt = new NumInfo('maximum width of a treew view title before truncation');
-    treeViewHasOverlay?: BOOLt = new BoolInfo('whether the treeview has an overlay for freeform annotations');
-    treeViewType?: string; // whether treeview is a Slide, file system, or (default) collection hierarchy
-    treeViewFreezeChildren?: STRt = new StrInfo('set (add, remove, add|remove) to disable adding, removing or both from collection');
+    treeView_HideTitle?: BOOLt = new BoolInfo('whether to hide the top document title of a tree view');
+    treeView_HideUnrendered?: BOOLt = new BoolInfo("tells tree view not to display documents that have an 'layout_unrendered' tag unless they also have a treeView_FieldKey tag (presBox)");
+    treeView_HideHeaderIfTemplate?: BOOLt = new BoolInfo('whether to hide the header for a document in a tree view only if a childLayoutTemplate is provided (presBox)');
+    treeView_HideHeader?: BOOLt = new BoolInfo('whether to hide the header for a document in a tree view');
+    treeView_HideHeaderFields?: BOOLt = new BoolInfo('whether to hide the drop down options for tree view items.');
+    treeView_ChildDoubleClick?: ScriptField; //
+    treeView_OpenIsTransient?: BOOLt = new BoolInfo("ignores the treeView_Open Doc flag, allowing a treeView_Item's expand/collapse state to be independent of other views of the same document in the same or any other tree view");
+    treeView_Open?: BOOLt = new BoolInfo('whether this document is expanded in a tree view');
+    treeView_ExpandedView?: string; // which field/thing is displayed when this item is opened in tree view
+    treeView_ExpandedViewLock?: BOOLt = new BoolInfo('whether the expanded view can be changed');
+    treeView_Checked?: ScriptField; // script to call when a tree view checkbox is checked
+    treeView_TruncateTitleWidth?: NUMt = new NumInfo('maximum width of a treew view title before truncation');
+    treeView_HasOverlay?: BOOLt = new BoolInfo('whether the treeview has an overlay for freeform annotations');
+    treeView_Type?: string; // whether treeview is a Slide, file system, or (default) collection hierarchy
+    treeView_FreezeChildren?: STRt = new StrInfo('set (add, remove, add|remove) to disable adding, removing or both from collection');
 
     sidebar_color?: string; // background color of text sidebar
     sidebar_collectionType?: string; // collection type of text sidebar
@@ -635,7 +635,7 @@ export namespace Docs {
                 DocumentType.CONFIG,
                 {
                     layout: { view: CollectionView, dataField: defaultDataKey },
-                    options: { layout_hideLinkButton: true, layout_unrendered: true },
+                    options: { config: '', layout_hideLinkButton: true, layout_unrendered: true },
                 },
             ],
             [
@@ -679,7 +679,7 @@ export namespace Docs {
                 DocumentType.DATAVIZ,
                 {
                     layout: { view: DataVizBox, dataField: defaultDataKey },
-                    options: { _layout_fitWidth: true, nativeDimModifiable: true },
+                    options: { dataViz_title: '', _layout_fitWidth: true, nativeDimModifiable: true },
                 },
             ],
             [
@@ -845,7 +845,7 @@ export namespace Docs {
          * only when creating a DockDocument from the current user's already existing
          * main document.
          */
-        function InstanceFromProto(proto: Doc, data: Field | undefined, options: DocumentOptions, delegId?: string, fieldKey: string = 'data', protoId?: string, placeholderDoc?: Doc) {
+        function InstanceFromProto(proto: Doc, data: Field | undefined, options: DocumentOptions, delegId?: string, fieldKey: string = 'data', protoId?: string, placeholderDoc?: Doc, noView?: boolean) {
             const viewKeys = ['x', 'y', 'isSystem']; // keys that should be addded to the view document even though they don't begin with an "_"
             const { omit: dataProps, extract: viewProps } = OmitKeys(options, viewKeys, '^_');
 
@@ -872,29 +872,34 @@ export namespace Docs {
                 dataDoc.proto = proto;
             }
 
-            const viewFirstProps: { [id: string]: any } = { author: Doc.CurrentUserEmail };
-            viewFirstProps['acl-Guest'] = options['_acl-Guest'] ?? (Doc.defaultAclPrivate ? SharingPermissions.None : SharingPermissions.View);
-            let viewDoc: Doc;
-            // determines whether viewDoc should be created using placeholder Doc or default
-            if (placeholderDoc) {
-                placeholderDoc._height = options._height !== undefined ? Number(options._height) : undefined;
-                placeholderDoc._width = options._width !== undefined ? Number(options._width) : undefined;
-                viewDoc = Doc.assign(placeholderDoc, viewFirstProps, true, true);
-                Array.from(Object.keys(placeholderDoc))
-                    .filter(key => key.startsWith('acl'))
-                    .forEach(key => (dataDoc[key] = viewDoc[key] = placeholderDoc[key]));
-            } else {
-                viewDoc = Doc.assign(Doc.MakeDelegate(dataDoc, delegId), viewFirstProps, true, true);
-            }
-            Doc.assign(viewDoc, viewProps, true, true);
-            if (![DocumentType.LINK, DocumentType.CONFIG, DocumentType.LABEL].includes(viewDoc.type as any)) {
-                DocUtils.MakeLinkToActiveAudio(() => viewDoc);
+            if (!noView) {
+                const viewFirstProps: { [id: string]: any } = { author: Doc.CurrentUserEmail };
+                viewFirstProps['acl-Guest'] = options['_acl-Guest'] ?? (Doc.defaultAclPrivate ? SharingPermissions.None : SharingPermissions.View);
+                let viewDoc: Doc;
+                // determines whether viewDoc should be created using placeholder Doc or default
+                if (placeholderDoc) {
+                    placeholderDoc._height = options._height !== undefined ? Number(options._height) : undefined;
+                    placeholderDoc._width = options._width !== undefined ? Number(options._width) : undefined;
+                    viewDoc = Doc.assign(placeholderDoc, viewFirstProps, true, true);
+                    Array.from(Object.keys(placeholderDoc))
+                        .filter(key => key.startsWith('acl'))
+                        .forEach(key => (dataDoc[key] = viewDoc[key] = placeholderDoc[key]));
+                } else {
+                    viewDoc = Doc.assign(Doc.MakeDelegate(dataDoc, delegId), viewFirstProps, true, true);
+                }
+                Doc.assign(viewDoc, viewProps, true, true);
+                if (![DocumentType.LINK, DocumentType.CONFIG, DocumentType.LABEL].includes(viewDoc.type as any)) {
+                    DocUtils.MakeLinkToActiveAudio(() => viewDoc);
+                }
+                updateCachedAcls(dataDoc);
+                updateCachedAcls(viewDoc);
+
+                return viewDoc;
             }
 
             updateCachedAcls(dataDoc);
-            updateCachedAcls(viewDoc);
 
-            return viewDoc;
+            return dataDoc;
         }
 
         export function ImageDocument(url: string | ImageField, options: DocumentOptions = {}, overwriteDoc?: Doc) {
@@ -1065,7 +1070,7 @@ export namespace Docs {
         }
 
         export function ConfigDocument(options: DocumentOptions, id?: string) {
-            return InstanceFromProto(Prototypes.get(DocumentType.CONFIG), options?.data, options, id);
+            return InstanceFromProto(Prototypes.get(DocumentType.CONFIG), options?.data, options, id, '', undefined, undefined, true);
         }
 
         export function HTMLMarkerDocument(documents: Array<Doc>, options: DocumentOptions, id?: string) {
@@ -1105,7 +1110,9 @@ export namespace Docs {
         }
 
         export function TreeDocument(documents: Array<Doc>, options: DocumentOptions, id?: string, protoId?: string) {
-            return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _xMargin: 5, _yMargin: 5, ...options, _type_collection: CollectionViewType.Tree }, id, undefined, protoId);
+            const doc = InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _xMargin: 5, _yMargin: 5, ...options, _type_collection: CollectionViewType.Tree }, id, undefined, protoId);
+            Doc.GetProto(doc).treeView = ''; /// not really needed, but makes keyvalue pane look better
+            return doc;
         }
 
         export function StackingDocument(documents: Array<Doc>, options: DocumentOptions, id?: string, protoId?: string) {
@@ -1163,11 +1170,11 @@ export namespace Docs {
         }
 
         export function DataVizDocument(url: string, options?: DocumentOptions, overwriteDoc?: Doc) {
-            return InstanceFromProto(Prototypes.get(DocumentType.DATAVIZ), new CsvField(url), { title: 'Data Viz', type: 'dataviz',  ...options }, undefined, undefined, undefined, overwriteDoc);
+            return InstanceFromProto(Prototypes.get(DocumentType.DATAVIZ), new CsvField(url), { title: 'Data Viz', type: 'dataviz', ...options }, undefined, undefined, undefined, overwriteDoc);
         }
 
         export function DockDocument(documents: Array<Doc>, config: string, options: DocumentOptions, id?: string) {
-            const ret = InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { treeViewFreezeChildren: 'remove|add', ...options, type_collection: CollectionViewType.Docking, dockingConfig: config }, id);
+            const ret = InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { treeView_FreezeChildren: 'remove|add', ...options, type_collection: CollectionViewType.Docking, dockingConfig: config }, id);
             documents.map(c => Doc.SetContainer(c, ret));
             return ret;
         }
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 47cd866cb..af43ef16a 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -278,12 +278,12 @@ export class CurrentUserUtils {
             {key: "Button",     creator: Docs.Create.ButtonDocument,                        opts: { _width: 150, _height: 50, _xPadding: 10, _yPadding: 10}, scripts: {onClick: FollowLinkScript()?.script.originalScript ?? ""}},
             {key: "Script",     creator: opts => Docs.Create.ScriptingDocument(null, opts), opts: { _width: 200, _height: 250, }},
             {key: "DataViz",    creator: opts => Docs.Create.DataVizDocument("/users/rz/Downloads/addresses.csv", opts),   opts: { _width: 300, _height: 300 }},
-            {key: "Header",     creator: headerTemplate,                                    opts: { _width: 300, _height: 70, _headerPointerEvents: "all", _headerHeight: 12, _headerFontSize: 9, _layout_autoHeight: true, treeViewHideUnrendered: true}},
-            {key: "Trail",      creator: Docs.Create.PresDocument,                          opts: { _width: 400, _height: 30, _type_collection: CollectionViewType.Stacking, dropAction: "embed" as dropActionType, treeViewHideTitle: true, _layout_fitWidth:true, _chromeHidden: true, layout_boxShadow: "0 0" }},
+            {key: "Header",     creator: headerTemplate,                                    opts: { _width: 300, _height: 70, _headerPointerEvents: "all", _headerHeight: 12, _headerFontSize: 9, _layout_autoHeight: true, treeView_HideUnrendered: true}},
+            {key: "Trail",      creator: Docs.Create.PresDocument,                          opts: { _width: 400, _height: 30, _type_collection: CollectionViewType.Stacking, dropAction: "embed" as dropActionType, treeView_HideTitle: true, _layout_fitWidth:true, _chromeHidden: true, layout_boxShadow: "0 0" }},
             {key: "Tab",        creator: opts => Docs.Create.FreeformDocument([], opts),    opts: { _width: 500, _height: 800, _layout_fitWidth: true, _freeform_backgroundGrid: true, }},
             {key: "Slide",      creator: opts => Docs.Create.TreeDocument([], opts),        opts: { _width: 300, _height: 200, _type_collection: CollectionViewType.Tree, 
-                                                                                                treeViewHasOverlay: true, _text_fontSize: "20px", _layout_autoHeight: true, 
-                                                                                                dropAction:'move', treeViewType: TreeViewType.outline, 
+                                                                                                treeView_HasOverlay: true, _text_fontSize: "20px", _layout_autoHeight: true, 
+                                                                                                dropAction:'move', treeView_Type: TreeViewType.outline, 
                                                                                                 backgroundColor: "white", _xMargin: 0, _yMargin: 0, _createDocOnCR: true 
                                                                                             }, funcs: {title: 'self.text?.Text'}},
             ];
@@ -493,8 +493,8 @@ export class CurrentUserUtils {
         const childContextMenuLabels =  ["Toggle Dark Theme", "Toggle Comic Mode", "Snapshot Dashboard", "Share Dashboard", "Remove Dashboard", "Reset Dashboard"];// entries must be kept in synch with childContextMenuScripts, childContextMenuIcons, and childContextMenuFilters
         const childContextMenuIcons = ["chalkboard", "tv", "camera", "users", "times", "trash"]; // entries must be kept in synch with childContextMenuScripts, childContextMenuLabels, and childContextMenuFilters
         const reqdOpts:DocumentOptions = {
-            title: "My Dashboards", childHideLinkButton: true, treeViewFreezeChildren: "remove|add", treeViewHideTitle: true, layout_boxShadow: "0 0", childDontRegisterViews: true,
-            dropAction: "same", treeViewType: TreeViewType.fileSystem, isFolder: true, isSystem: true,  treeViewTruncateTitleWidth: 350, ignoreClick: true, 
+            title: "My Dashboards", childHideLinkButton: true, treeView_FreezeChildren: "remove|add", treeView_HideTitle: true, layout_boxShadow: "0 0", childDontRegisterViews: true,
+            dropAction: "same", treeView_Type: TreeViewType.fileSystem, isFolder: true, isSystem: true,  treeView_TruncateTitleWidth: 350, ignoreClick: true, 
             layout_headerButton: newDashboardButton, childDragAction: "none",
             _layout_showTitle: "title", _height: 400, _gridGap: 5, _forceActive: true, _lockedPosition: true,
             contextMenuLabels:new List<string>(contextMenuLabels),
@@ -522,16 +522,16 @@ 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']),
+            _forceActive: true, _dragOnlyWithinContainer: true, _layout_hideContextMenu: true, _width: 30, _height: 30, undoIgnoreFields:new List<string>(['treeView_SortCriterion']),
             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);
         
         const reqdOpts:DocumentOptions = { _layout_showTitle: "title", _height: 100, _gridGap: 5, _forceActive: true, _lockedPosition: true, 
-            title: "My Documents", layout_headerButton: newFolderButton, treeViewHideTitle: true, dropAction: 'add', isSystem: true,
-            isFolder: true, treeViewType: TreeViewType.fileSystem, childHideLinkButton: true, layout_boxShadow: "0 0", childDontRegisterViews: true, 
-            treeViewTruncateTitleWidth: 350, ignoreClick: true, childDragAction: "embed",
+            title: "My Documents", layout_headerButton: newFolderButton, treeView_HideTitle: true, dropAction: 'add', isSystem: true,
+            isFolder: true, treeView_Type: TreeViewType.fileSystem, childHideLinkButton: true, layout_boxShadow: "0 0", childDontRegisterViews: true, 
+            treeView_TruncateTitleWidth: 350, ignoreClick: true, childDragAction: "embed",
             childContextMenuLabels: new List<string>(["Create new folder"]),
             childContextMenuIcons: new List<string>(["plus"]),
             layout_explainer: "This is your file manager where you can create folders to keep track of documents independently of your dashboard."
@@ -548,8 +548,8 @@ export class CurrentUserUtils {
     /// initializes the panel displaying docs that have been recently closed
     static setupRecentlyClosed(doc: Doc, field:string) {
         const reqdOpts:DocumentOptions = { _layout_showTitle: "title", _lockedPosition: true, _gridGap: 5, _forceActive: true, isFolder: true,
-            title: "My Recently Closed", childHideLinkButton: true, treeViewHideTitle: true, childDragAction: "move", isSystem: true,
-            treeViewTruncateTitleWidth: 350, ignoreClick: true,  layout_boxShadow: "0 0", childDontRegisterViews: true, dropAction: "same",
+            title: "My Recently Closed", childHideLinkButton: true, treeView_HideTitle: true, childDragAction: "move", isSystem: true,
+            treeView_TruncateTitleWidth: 350, ignoreClick: true,  layout_boxShadow: "0 0", childDontRegisterViews: true, dropAction: "same",
             contextMenuLabels: new List<string>(["Empty recently closed"]),
             contextMenuIcons:new List<string>(["trash"]),
             layout_explainer: "Recently closed documents appear in this menu. They will only be deleted if you explicity empty this list."
@@ -573,9 +573,9 @@ export class CurrentUserUtils {
         const reqdOpts:DocumentOptions = {
             _lockedPosition: true, _gridGap: 5, _forceActive: true, title: Doc.CurrentUserEmail +"-view",
             layout_boxShadow: "0 0", childDontRegisterViews: true, dropAction: "same", ignoreClick: true, isSystem: true,
-            treeViewHideTitle: true, treeViewTruncateTitleWidth: 350
+            treeView_HideTitle: true, treeView_TruncateTitleWidth: 350
         };
-        if (!doc[field]) DocUtils.AssignOpts(doc, {treeViewOpen: true, treeViewExpandedView: "fields" });
+        if (!doc[field]) DocUtils.AssignOpts(doc, {treeView_Open: true, treeView_ExpandedView: "fields" });
         return DocUtils.AssignDocField(doc, field, (opts, items) => Docs.Create.TreeDocument(items??[], opts), reqdOpts, [doc]);
     }
 
@@ -789,19 +789,19 @@ export class CurrentUserUtils {
     static setupSharedDocs(doc: Doc, sharingDocumentId: string) {
         const dblClkScript = "{scriptContext.openLevel(documentView); addDocToList(scriptContext.props.treeView.props.Document, 'viewed', documentView.rootDoc);}";
         
-        const sharedScripts = {  treeViewChildDoubleClick: dblClkScript,  }
+        const sharedScripts = {  treeView_ChildDoubleClick: dblClkScript,  }
         const sharedDocOpts:DocumentOptions = {
             title: "My Shared Docs",
             userColor: "rgb(202, 202, 202)",
-            isFolder:true, undoIgnoreFields:new List<string>(['treeViewSortCriterion']),
+            isFolder:true, undoIgnoreFields:new List<string>(['treeView_SortCriterion']),
             // childContextMenuFilters: new List<ScriptField>([dashboardFilter!,]),
             // childContextMenuScripts: new List<ScriptField>([addToDashboards!,]),
             // childContextMenuLabels: new List<string>(["Add to Dashboards",]),
             // childContextMenuIcons: new List<string>(["user-plus",]),
             "acl-Guest": SharingPermissions.Augment, "_acl-Guest": SharingPermissions.Augment,
             childDragAction: "embed", isSystem: true, contentPointerEvents: "all", childLimitHeight: 0, _yMargin: 0, _gridGap: 15, childDontRegisterViews:true,
-            // NOTE: treeViewHideTitle & _layout_showTitle is for a TreeView's editable title, _layout_showTitle is for DocumentViews title bar
-            _layout_showTitle: "title", treeViewHideTitle: true, ignoreClick: true, _lockedPosition: true, layout_boxShadow: "0 0", _chromeHidden: true, dontRegisterView: true, 
+            // NOTE: treeView_HideTitle & _layout_showTitle is for a TreeView's editable title, _layout_showTitle is for DocumentViews title bar
+            _layout_showTitle: "title", treeView_HideTitle: true, ignoreClick: true, _lockedPosition: true, layout_boxShadow: "0 0", _chromeHidden: true, dontRegisterView: true, 
             layout_explainer: "This is where documents or dashboards that other users have shared with you will appear. To share a document or dashboard right click and select 'Share'"
         };
         
@@ -864,7 +864,7 @@ export class CurrentUserUtils {
         doc.userColor ?? (doc.userColor = Colors.LIGHT_GRAY);
         doc.userTheme ?? (doc.userTheme = ColorScheme.Dark);
         doc.filterDocCount = 0;
-        doc.treeViewFreezeChildren = "remove|add";
+        doc.treeView_FreezeChildren = "remove|add";
         doc.activePage = doc.activeDashboard === undefined ? 'home': doc.activePage;
         this.setupLinkDocs(doc, linkDatabaseId);
         this.setupSharedDocs(doc, sharingDocumentId);  // sets up the right sidebar collection for mobile upload documents and sharing
diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts
index 42132c2d7..9779639f4 100644
--- a/src/client/util/DocumentManager.ts
+++ b/src/client/util/DocumentManager.ts
@@ -315,10 +315,10 @@ export class DocumentManager {
             if (options.toggleTarget && (!options.didMove || docView.rootDoc.hidden)) docView.rootDoc.hidden = !docView.rootDoc.hidden;
             if (options.effect) docView.rootDoc[Animation] = options.effect;
 
-            if (options.zoomTextSelections && Doc.UnhighlightTimer && contextView && viewSpec.textHtml) {
+            if (options.zoomTextSelections && Doc.UnhighlightTimer && contextView && viewSpec.text_html) {
                 // if the docView is a text anchor, the contextView is the PDF/Web/Text doc
-                contextView.htmlOverlayEffect = StrCast(options?.effect?.presEffect, StrCast(options?.effect?.followLinkAnimEffect));
-                contextView.textHtmlOverlay = StrCast(targetDoc.textHtml);
+                contextView.htmlOverlayEffect = StrCast(options?.effect?.presentation_effect, StrCast(options?.effect?.followLinkAnimEffect));
+                contextView.textHtmlOverlay = StrCast(targetDoc.text_html);
                 DocumentManager._overlayViews.add(contextView);
             }
             Doc.AddUnHighlightWatcher(() => {
diff --git a/src/client/views/DashboardView.tsx b/src/client/views/DashboardView.tsx
index 21808d6e0..3e4827c83 100644
--- a/src/client/views/DashboardView.tsx
+++ b/src/client/views/DashboardView.tsx
@@ -108,7 +108,14 @@ export class DashboardView extends React.Component {
                 }}>
                 <div className="header">Create New Dashboard</div>
                 <EditableText formLabel="Title" placeholder={placeholder} type={Type.SEC} color={StrCast(Doc.UserDoc().userColor)} setVal={val => this.setNewDashboardName(val as string)} fillWidth />
-                <ColorPicker formLabel="Background" colorPickerType="github" type={Type.TERT} selectedColor={this.newDashboardColor} setSelectedColor={this.setNewDashboardColor} />
+                <ColorPicker
+                    formLabel="Background" //
+                    colorPickerType="github"
+                    type={Type.TERT}
+                    selectedColor={this.newDashboardColor}
+                    setFinalColor={this.setNewDashboardColor}
+                    setSelectedColor={this.setNewDashboardColor}
+                />
                 <div className="button-bar">
                     <Button text="Cancel" color={StrCast(Doc.UserDoc().userColor)} onClick={this.abortCreateNewDashboard} />
                     <Button type={Type.TERT} text="Create" color={StrCast(Doc.UserDoc().userVariantColor)} onClick={() => this.createNewDashboard(this.newDashboardName!, this.newDashboardColor)} />
@@ -437,12 +444,12 @@ export class DashboardView extends React.Component {
             title: 'My Trails',
             _layout_showTitle: 'title',
             _height: 100,
-            treeViewHideTitle: true,
+            treeView_HideTitle: true,
             _layout_fitWidth: true,
             _gridGap: 5,
             _forceActive: true,
             childDragAction: 'embed',
-            treeViewTruncateTitleWidth: 150,
+            treeView_TruncateTitleWidth: 150,
             ignoreClick: true,
             layout_headerButton: myTrailsBtn,
             contextMenuIcons: new List<string>(['plus']),
@@ -454,7 +461,7 @@ export class DashboardView extends React.Component {
             isSystem: true,
             layout_explainer: 'All of the trails that you have created will appear here.',
         };
-        const myTrails = DocUtils.AssignScripts(Docs.Create.TreeDocument([], reqdOpts), { treeViewChildDoubleClick: 'openPresentation(documentView.rootDoc)' });
+        const myTrails = DocUtils.AssignScripts(Docs.Create.TreeDocument([], reqdOpts), { treeView_ChildDoubleClick: 'openPresentation(documentView.rootDoc)' });
         dashboardDoc.myTrails = new PrefetchProxy(myTrails);
 
         const contextMenuScripts = [reqdBtnScript.onClick];
diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx
index 6f5e9f5c0..345135a1a 100644
--- a/src/client/views/DocumentButtonBar.tsx
+++ b/src/client/views/DocumentButtonBar.tsx
@@ -563,10 +563,10 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
         const rootDoc = rootView?.rootDoc;
         if (rootDoc) {
             const anchor = rootView.ComponentView?.getAnchor?.(false) ?? rootDoc;
-            const trail = DocCast(anchor.presTrail) ?? Doc.MakeCopy(DocCast(Doc.UserDoc().emptyTrail), true);
-            if (trail !== anchor.presTrail) {
+            const trail = DocCast(anchor.presentationTrail) ?? Doc.MakeCopy(DocCast(Doc.UserDoc().emptyTrail), true);
+            if (trail !== anchor.presentationTrail) {
                 DocUtils.MakeLink(anchor, trail, { link_relationship: 'link trail' });
-                anchor.presTrail = trail;
+                anchor.presentationTrail = trail;
             }
             Doc.ActivePresentation = trail;
             this.props.views().lastElement()?.props.addDocTab(trail, OpenWhere.replaceRight);
diff --git a/src/client/views/InkStroke.scss b/src/client/views/InkStroke.scss
index f504890a5..c672824bf 100644
--- a/src/client/views/InkStroke.scss
+++ b/src/client/views/InkStroke.scss
@@ -17,6 +17,7 @@
     display: flex;
     align-items: center;
     height: 100%;
+    width: 100%;
     transition: inherit;
     .inkStroke {
         mix-blend-mode: multiply;
diff --git a/src/client/views/InkingStroke.tsx b/src/client/views/InkingStroke.tsx
index 93163c1a3..b3647249a 100644
--- a/src/client/views/InkingStroke.tsx
+++ b/src/client/views/InkingStroke.tsx
@@ -91,8 +91,8 @@ export class InkingStroke extends ViewBoxBaseComponent<FieldViewProps>() {
         const anchor = Docs.Create.ConfigDocument({
             title: 'Ink anchor:' + this.rootDoc.title,
             // set presentation timing for restoring shape
-            presDuration: 1100,
-            presTransition: 1000,
+            presentation_duration: 1100,
+            presentation_transition: 1000,
             annotationOn: this.rootDoc,
         });
         if (anchor) {
@@ -362,7 +362,7 @@ export class InkingStroke extends ViewBoxBaseComponent<FieldViewProps>() {
 
     _subContentView: DocComponentView | undefined;
     setSubContentView = (doc: DocComponentView) => (this._subContentView = doc);
-    @computed get fillColor() { 
+    @computed get fillColor() {
         const isInkMask = BoolCast(this.layoutDoc.stroke_isInkMask);
         return isInkMask ? DashColor(StrCast(this.layoutDoc.fillColor, 'transparent')).blacken(0).rgb().toString() : this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.FillColor) ?? 'transparent';
     }
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index dc236b603..e376c4fdf 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -156,8 +156,8 @@ export class MainView extends React.Component {
             DocServer.setLivePlaygroundFields([
                 'dataTransition',
                 'viewTransition',
-                'treeViewOpen',
-                'treeViewExpandedView',
+                'treeView_Open',
+                'treeView_ExpandedView',
                 'carousel_index',
                 'itemIndex', // for changing slides in presentations
                 'layout_sidebarWidthPercent',
diff --git a/src/client/views/MarqueeAnnotator.tsx b/src/client/views/MarqueeAnnotator.tsx
index a4a2c1df9..4aabb83dc 100644
--- a/src/client/views/MarqueeAnnotator.tsx
+++ b/src/client/views/MarqueeAnnotator.tsx
@@ -201,7 +201,7 @@ export class MarqueeAnnotator extends React.Component<MarqueeAnnotatorProps> {
         textRegionAnnoProto.height = Math.max(maxY, 0) - Math.max(minY, 0);
         textRegionAnnoProto.width = Math.max(maxX, 0) - Math.max(minX, 0);
         // mainAnnoDocProto.text = this._selectionText;
-        textRegionAnnoProto.textInlineAnnotations = new List<Doc>(annoDocs);
+        textRegionAnnoProto.text_inlineAnnotations = new List<Doc>(annoDocs);
         savedAnnoMap.clear();
         return textRegionAnno;
     };
diff --git a/src/client/views/PropertiesView.scss b/src/client/views/PropertiesView.scss
index b79486167..1a7c9eb64 100644
--- a/src/client/views/PropertiesView.scss
+++ b/src/client/views/PropertiesView.scss
@@ -26,36 +26,34 @@
         padding: 5px 10px;
     }
 
-
     .propertiesView-sharing {
         //border-bottom: 1px solid black;
         //padding: 8.5px;
 
+        .propertiesView-buttonContainer {
+            float: right;
+            display: flex;
 
-            .propertiesView-buttonContainer {
-                float: right;
-                display: flex;
-
-                button {
-                    width: 15;
-                    height: 15;
-                    padding: 0;
-                    margin-top: -5;
-                }
+            button {
+                width: 15;
+                height: 15;
+                padding: 0;
+                margin-top: -5;
             }
+        }
 
-            .change-buttons {
-                display: flex;
+        .change-buttons {
+            display: flex;
 
-                button {
-                    width: 5;
-                    height: 5;
-                }
+            button {
+                width: 5;
+                height: 5;
+            }
 
-                input {
-                    width: 100%;
-                }
+            input {
+                width: 100%;
             }
+        }
     }
 
     .propertiesView-acls-checkbox {
@@ -63,11 +61,11 @@
         margin-left: 50px;
     }
 
-    .propertiesView-shareDropDown{
+    .propertiesView-shareDropDown {
         margin-right: 10px;
         min-width: 65px;
-        
-        & .propertiesView-shareDropDownNone{
+
+        & .propertiesView-shareDropDownNone {
             padding: 0px;
             padding-left: 3px;
             padding-right: 3px;
@@ -77,7 +75,7 @@
             border: 1px solid rgb(71, 71, 71);
         }
         & .propertiesView-shareDropDownEdit,
-        .propertiesView-shareDropDownAdmin{
+        .propertiesView-shareDropDownAdmin {
             padding: 0px;
             padding-left: 3px;
             padding-right: 3px;
@@ -86,17 +84,16 @@
             border-radius: 6px;
             border: 1px solid rgb(75, 75, 5);
         }
-        & .propertiesView-shareDropDownAugment{
+        & .propertiesView-shareDropDownAugment {
             padding: 0px;
             padding-left: 3px;
             padding-right: 3px;
             background: rgb(208, 255, 208);
-            color:rgb(19, 80, 19);
+            color: rgb(19, 80, 19);
             border-radius: 6px;
             border: 1px solid rgb(19, 80, 19);
-
         }
-        & .propertiesView-shareDropDownView{
+        & .propertiesView-shareDropDownView {
             padding: 0px;
             padding-left: 3px;
             padding-right: 3px;
@@ -105,7 +102,7 @@
             border-radius: 6px;
             border: 1px solid rgb(25, 25, 101);
         }
-        & .propertiesView-shareDropDownNot-Shared{
+        & .propertiesView-shareDropDownNot-Shared {
             padding: 0px;
             padding-left: 3px;
             padding-right: 3px;
@@ -245,15 +242,12 @@
             cursor: auto;
         }
     }
+}
 
-    }
-
-    .propertiesView-presTrails {
-        //border-bottom: 1px solid black;
-        //padding: 8.5px;
-
-      
-    }
+.propertiesView-presentationTrails {
+    //border-bottom: 1px solid black;
+    //padding: 8.5px;
+}
 
 .inking-button {
     display: flex;
@@ -515,9 +509,9 @@
     }
 }
 
-.propertiesView-wordTitle{
-    color:darkslategray;
-    font-weight:200;
+.propertiesView-wordTitle {
+    color: darkslategray;
+    font-weight: 200;
 }
 
 .editable-title {
@@ -532,15 +526,15 @@
     }
 }
 
-.propertiesView-wordType{
-    color:darkslategray;
-    font-weight:200;
+.propertiesView-wordType {
+    color: darkslategray;
+    font-weight: 200;
 }
 
-.currentType{
+.currentType {
     text-decoration: underline;
     display: flex;
-    align-items:center;
+    align-items: center;
     // border: solid 1px #323232;
     // padding-left: 5px;
     // padding-top: 4px;
@@ -548,8 +542,8 @@
     // height: fit-content;
 }
 
-.currentType-icon{
-    margin-right:5px;
+.currentType-icon {
+    margin-right: 5px;
 }
 
 .properties-flyout {
diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx
index 872f1c6ab..1b6037ed9 100644
--- a/src/client/views/PropertiesView.tsx
+++ b/src/client/views/PropertiesView.tsx
@@ -1700,50 +1700,50 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                             </div>
                         </div>
                         {!selectedItem ? null : (
-                            <div className="propertiesView-presTrails">
-                                <div className="propertiesView-presTrails-title" onPointerDown={action(() => (this.openPresTransitions = !this.openPresTransitions))} style={{ backgroundColor: this.openPresTransitions ? 'black' : '' }}>
+                            <div className="propertiesView-presentationTrails">
+                                <div className="propertiesView-presentationTrails-title" onPointerDown={action(() => (this.openPresTransitions = !this.openPresTransitions))} style={{ backgroundColor: this.openPresTransitions ? 'black' : '' }}>
                                     &nbsp; <FontAwesomeIcon style={{ alignSelf: 'center' }} icon={'rocket'} /> &nbsp; Transitions
-                                    <div className="propertiesView-presTrails-title-icon">
+                                    <div className="propertiesView-presentationTrails-title-icon">
                                         <FontAwesomeIcon icon={this.openPresTransitions ? 'caret-down' : 'caret-right'} size="lg" />
                                     </div>
                                 </div>
-                                {this.openPresTransitions ? <div className="propertiesView-presTrails-content">{PresBox.Instance.transitionDropdown}</div> : null}
+                                {this.openPresTransitions ? <div className="propertiesView-presentationTrails-content">{PresBox.Instance.transitionDropdown}</div> : null}
                             </div>
                         )}
                         {!selectedItem ? null : (
-                            <div className="propertiesView-presTrails">
+                            <div className="propertiesView-presentationTrails">
                                 <div
-                                    className="propertiesView-presTrails-title"
+                                    className="propertiesView-presentationTrails-title"
                                     onPointerDown={action(() => (this.openPresVisibilityAndDuration = !this.openPresVisibilityAndDuration))}
                                     style={{ backgroundColor: this.openPresTransitions ? 'black' : '' }}>
                                     &nbsp; <FontAwesomeIcon style={{ alignSelf: 'center' }} icon={'rocket'} /> &nbsp; Visibilty
-                                    <div className="propertiesView-presTrails-title-icon">
+                                    <div className="propertiesView-presentationTrails-title-icon">
                                         <FontAwesomeIcon icon={this.openPresVisibilityAndDuration ? 'caret-down' : 'caret-right'} size="lg" />
                                     </div>
                                 </div>
-                                {this.openPresVisibilityAndDuration ? <div className="propertiesView-presTrails-content">{PresBox.Instance.visibiltyDurationDropdown}</div> : null}
+                                {this.openPresVisibilityAndDuration ? <div className="propertiesView-presentationTrails-content">{PresBox.Instance.visibiltyDurationDropdown}</div> : null}
                             </div>
                         )}
                         {!selectedItem ? null : (
-                            <div className="propertiesView-presTrails">
-                                <div className="propertiesView-presTrails-title" onPointerDown={action(() => (this.openPresProgressivize = !this.openPresProgressivize))} style={{ backgroundColor: this.openPresTransitions ? 'black' : '' }}>
+                            <div className="propertiesView-presentationTrails">
+                                <div className="propertiesView-presentationTrails-title" onPointerDown={action(() => (this.openPresProgressivize = !this.openPresProgressivize))} style={{ backgroundColor: this.openPresTransitions ? 'black' : '' }}>
                                     &nbsp; <FontAwesomeIcon style={{ alignSelf: 'center' }} icon={'rocket'} /> &nbsp; Progressivize
-                                    <div className="propertiesView-presTrails-title-icon">
+                                    <div className="propertiesView-presentationTrails-title-icon">
                                         <FontAwesomeIcon icon={this.openPresProgressivize ? 'caret-down' : 'caret-right'} size="lg" />
                                     </div>
                                 </div>
-                                {this.openPresProgressivize ? <div className="propertiesView-presTrails-content">{PresBox.Instance.progressivizeDropdown}</div> : null}
+                                {this.openPresProgressivize ? <div className="propertiesView-presentationTrails-content">{PresBox.Instance.progressivizeDropdown}</div> : null}
                             </div>
                         )}
                         {!selectedItem || (type !== DocumentType.VID && type !== DocumentType.AUDIO) ? null : (
-                            <div className="propertiesView-presTrails">
-                                <div className="propertiesView-presTrails-title" onPointerDown={action(() => (this.openSlideOptions = !this.openSlideOptions))} style={{ backgroundColor: this.openSlideOptions ? 'black' : '' }}>
+                            <div className="propertiesView-presentationTrails">
+                                <div className="propertiesView-presentationTrails-title" onPointerDown={action(() => (this.openSlideOptions = !this.openSlideOptions))} style={{ backgroundColor: this.openSlideOptions ? 'black' : '' }}>
                                     &nbsp; <FontAwesomeIcon style={{ alignSelf: 'center' }} icon={type === DocumentType.AUDIO ? 'file-audio' : 'file-video'} /> &nbsp; {type === DocumentType.AUDIO ? 'Audio Options' : 'Video Options'}
-                                    <div className="propertiesView-presTrails-title-icon">
+                                    <div className="propertiesView-presentationTrails-title-icon">
                                         <FontAwesomeIcon icon={this.openSlideOptions ? 'caret-down' : 'caret-right'} size="lg" />
                                     </div>
                                 </div>
-                                {this.openSlideOptions ? <div className="propertiesView-presTrails-content">{PresBox.Instance.mediaOptionsDropdown}</div> : null}
+                                {this.openSlideOptions ? <div className="propertiesView-presentationTrails-content">{PresBox.Instance.mediaOptionsDropdown}</div> : null}
                             </div>
                         )}
                     </div>
diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx
index 63ff348e3..a757a0715 100644
--- a/src/client/views/StyleProvider.tsx
+++ b/src/client/views/StyleProvider.tsx
@@ -27,8 +27,8 @@ import './StyleProvider.scss';
 import React = require('react');
 
 export enum StyleProp {
-    TreeViewIcon = 'treeViewIcon',
-    TreeViewSortings = 'treeViewSortings', // options for how to sort tree view items
+    TreeViewIcon = 'treeView_Icon',
+    TreeViewSortings = 'treeView_Sortings', // options for how to sort tree view items
     DocContents = 'docContents', // when specified, the JSX returned will replace the normal rendering of the document view
     Opacity = 'opacity', // opacity of the document view
     BoxShadow = 'boxShadow', // box shadow - used for making collections standout and for showing clusters in free form views
@@ -133,7 +133,7 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
             return undefined;
         case StyleProp.DocContents:return undefined;
         case StyleProp.WidgetColor:return isAnnotated ? Colors.LIGHT_BLUE : darkScheme() ? 'lightgrey' : 'dimgrey';
-        case StyleProp.Opacity:    return props?.LayoutTemplateString?.includes(KeyValueBox.name) ? 1 : doc?.textInlineAnnotations ? 0 :  Cast(doc?._opacity, "number", Cast(doc?.opacity, 'number', null));
+        case StyleProp.Opacity:    return props?.LayoutTemplateString?.includes(KeyValueBox.name) ? 1 : doc?.text_inlineAnnotations ? 0 :  Cast(doc?._opacity, "number", Cast(doc?.opacity, 'number', null));
         case StyleProp.HideLinkBtn:return props?.hideLinkButton || (!selected && doc?.layout_hideLinkButton);
         case StyleProp.FontSize:   return StrCast(doc?.[fieldKey + 'fontSize'],   StrCast(doc?._text_fontSize,   StrCast(Doc.UserDoc().fontSize)));
         case StyleProp.FontFamily: return StrCast(doc?.[fieldKey + 'fontFamily'], StrCast(doc?._text_fontFamily, StrCast(Doc.UserDoc().fontFamily)));
@@ -144,7 +144,7 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
         case StyleProp.ShowTitle:
             return (
                 (doc &&
-                    !doc.presentationTargetDoc &&
+                    !doc.presentation_targetDoc &&
                     !props?.LayoutTemplateString?.includes(KeyValueBox.name) &&
                     props?.layout_showTitle?.() !== '' &&
                     StrCast(
diff --git a/src/client/views/TemplateMenu.tsx b/src/client/views/TemplateMenu.tsx
index 5c2ab3f70..a3884c9eb 100644
--- a/src/client/views/TemplateMenu.tsx
+++ b/src/client/views/TemplateMenu.tsx
@@ -102,7 +102,7 @@ export class TemplateMenu extends React.Component<TemplateMenuProps> {
         const templateMenu: Array<JSX.Element> = [];
         this.props.templates?.forEach((checked, template) => templateMenu.push(<TemplateToggle key={template} template={template} checked={checked} toggle={this.toggleTemplate} />));
         templateMenu.push(<OtherToggle key={'default'} name={'Default'} checked={templateName === 'layout'} toggle={this.toggleDefault} />);
-        addedTypes.concat(noteTypes).map(template => (template.treeViewChecked = this.templateIsUsed(firstDoc, template)));
+        addedTypes.concat(noteTypes).map(template => (template.treeView_Checked = this.templateIsUsed(firstDoc, template)));
         this._addedKeys &&
             Array.from(this._addedKeys)
                 .filter(key => !noteTypes.some(nt => nt.title === key))
diff --git a/src/client/views/collections/CollectionTimeView.tsx b/src/client/views/collections/CollectionTimeView.tsx
index 192d48c64..a8f5345b7 100644
--- a/src/client/views/collections/CollectionTimeView.tsx
+++ b/src/client/views/collections/CollectionTimeView.tsx
@@ -65,9 +65,9 @@ export class CollectionTimeView extends CollectionSubView() {
     @action
     scrollPreview = (docView: DocumentView, anchor: Doc, focusSpeed: number, options: DocFocusOptions) => {
         // if in preview, then override document's fields with view spec
-        this._focusFilters = StrListCast(anchor.presDocFilters);
-        this._focusRangeFilters = StrListCast(anchor.presPinDocRangeFilters);
-        this._focusPivotField = StrCast(anchor.presPivotField);
+        this._focusFilters = StrListCast(anchor.config_docFilters);
+        this._focusRangeFilters = StrListCast(anchor.config_docRangeFilters);
+        this._focusPivotField = StrCast(anchor.config_pivotField);
         return undefined;
     };
 
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index ea3b5065f..b5c7d3f5d 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -66,17 +66,17 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
         return this.props.DataDoc || this.doc;
     }
     @computed get treeViewtruncateTitleWidth() {
-        return NumCast(this.doc.treeViewTruncateTitleWidth, this.panelWidth());
+        return NumCast(this.doc.treeView_TruncateTitleWidth, this.panelWidth());
     }
     @computed get treeChildren() {
         TraceMobx();
         return this.props.childDocuments || this.childDocs;
     }
     @computed get outlineMode() {
-        return this.doc.treeViewType === TreeViewType.outline;
+        return this.doc.treeView_Type === TreeViewType.outline;
     }
     @computed get fileSysMode() {
-        return this.doc.treeViewType === TreeViewType.fileSystem;
+        return this.doc.treeView_Type === TreeViewType.fileSystem;
     }
     @computed get dashboardMode() {
         return this.doc === Doc.MyDashboards;
@@ -191,9 +191,9 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
         // need to test if propagation has stopped because GoldenLayout forces a parallel react hierarchy to be created for its top-level layout
         if (!Doc.noviceMode) {
             const layoutItems: ContextMenuProps[] = [];
-            layoutItems.push({ description: 'Make tree state ' + (this.doc.treeViewOpenIsTransient ? 'persistent' : 'transient'), event: () => (this.doc.treeViewOpenIsTransient = !this.doc.treeViewOpenIsTransient), icon: 'paint-brush' });
-            layoutItems.push({ description: (this.doc.treeViewHideHeaderFields ? 'Show' : 'Hide') + ' Header Fields', event: () => (this.doc.treeViewHideHeaderFields = !this.doc.treeViewHideHeaderFields), icon: 'paint-brush' });
-            layoutItems.push({ description: (this.doc.treeViewHideTitle ? 'Show' : 'Hide') + ' Title', event: () => (this.doc.treeViewHideTitle = !this.doc.treeViewHideTitle), icon: 'paint-brush' });
+            layoutItems.push({ description: 'Make tree state ' + (this.doc.treeView_OpenIsTransient ? 'persistent' : 'transient'), event: () => (this.doc.treeView_OpenIsTransient = !this.doc.treeView_OpenIsTransient), icon: 'paint-brush' });
+            layoutItems.push({ description: (this.doc.treeView_HideHeaderFields ? 'Show' : 'Hide') + ' Header Fields', event: () => (this.doc.treeView_HideHeaderFields = !this.doc.treeView_HideHeaderFields), icon: 'paint-brush' });
+            layoutItems.push({ description: (this.doc.treeView_HideTitle ? 'Show' : 'Hide') + ' Title', event: () => (this.doc.treeView_HideTitle = !this.doc.treeView_HideTitle), icon: 'paint-brush' });
             ContextMenu.Instance.addItem({ description: 'Options...', subitems: layoutItems, icon: 'eye' });
             const existingOnClick = ContextMenu.Instance.findByDescription('OnClick...');
             const onClicks: ContextMenuProps[] = existingOnClick && 'subitems' in existingOnClick ? existingOnClick.subitems : [];
@@ -215,7 +215,7 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
                 height={'auto'}
                 GetValue={() => StrCast(this.dataDoc.title)}
                 SetValue={undoBatch((value: string, shift: boolean, enter: boolean) => {
-                    if (enter && this.props.Document.treeViewType === TreeViewType.outline) this.makeTextCollection(this.treeChildren);
+                    if (enter && this.props.Document.treeView_Type === TreeViewType.outline) this.makeTextCollection(this.treeChildren);
                     this.dataDoc.title = value;
                     return true;
                 })}
@@ -261,7 +261,7 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
         const icons = StrListCast(this.doc.childContextMenuIcons);
         return StrListCast(this.doc.childContextMenuLabels).map((label, i) => ({ script: customScripts[i], filter: customFilters[i], icon: icons[i], label }));
     };
-    headerFields = () => this.props.treeViewHideHeaderFields || BoolCast(this.doc.treeViewHideHeaderFields);
+    headerFields = () => this.props.treeViewHideHeaderFields || BoolCast(this.doc.treeView_HideHeaderFields);
     @observable _renderCount = 1;
     @computed get treeViewElements() {
         TraceMobx();
@@ -389,7 +389,7 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
         const background = () => this.props.styleProvider?.(this.doc, this.props, StyleProp.BackgroundColor);
         const color = () => this.props.styleProvider?.(this.doc, this.props, StyleProp.Color);
         const pointerEvents = () => (this.props.isContentActive() === false ? 'none' : undefined);
-        const titleBar = this.props.treeViewHideTitle || this.doc.treeViewHideTitle ? null : this.titleBar;
+        const titleBar = this.props.treeViewHideTitle || this.doc.treeView_HideTitle ? null : this.titleBar;
         return (
             <div style={{ display: 'flex', flexDirection: 'column', height: '100%', pointerEvents: 'all' }}>
                 {!this.buttonMenu && !this.noviceExplainer ? null : (
@@ -401,7 +401,7 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
                 <div
                     className="collectionTreeView-contents"
                     key="tree"
-                    ref={r => !this.doc.treeViewHasOverlay && r && this.createTreeDropTarget(r)}
+                    ref={r => !this.doc.treeView_HasOverlay && r && this.createTreeDropTarget(r)}
                     style={{
                         ...(!titleBar ? { marginLeft: this.marginX(), paddingTop: this.marginTop() } : {}),
                         color: color(),
@@ -440,7 +440,7 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
         const scale = (this.props.NativeDimScaling?.() || 1) * NumCast(this.layoutDoc._freeform_scale, 1) || 1;
         return (
             <div style={{ transform: `scale(${scale})`, transformOrigin: 'top left', width: `${100 / scale}%`, height: `${100 / scale}%` }}>
-                {!(this.doc instanceof Doc) || !this.treeChildren ? null : this.doc.treeViewHasOverlay ? (
+                {!(this.doc instanceof Doc) || !this.treeChildren ? null : this.doc.treeView_HasOverlay ? (
                     <CollectionFreeFormView
                         {...this.props}
                         setContentView={emptyFunction}
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index c33519afb..88f892efc 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -41,7 +41,7 @@ interface CollectionViewProps_ extends FieldViewProps {
     isAnnotationOverlayScrollable?: boolean; // whether the annotation overlay can be vertically scrolled (just for tree views, currently)
     layoutEngine?: () => string;
     setPreviewCursor?: (func: (x: number, y: number, drag: boolean, hide: boolean) => void) => void;
-    setBrushViewer?: (func?: (view: { width: number; height: number; panX: number; panY: number }) => void) => void;
+    setBrushViewer?: (func?: (view: { width: number; height: number; panX: number; panY: number }, transTime: number) => void) => void;
     ignoreUnrendered?: boolean;
 
     // property overrides for child documents
diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
index d787f5262..ea473d5cf 100644
--- a/src/client/views/collections/TabDocView.tsx
+++ b/src/client/views/collections/TabDocView.tsx
@@ -256,46 +256,47 @@ export class TabDocView extends React.Component<TabDocViewProps> {
                 return;
             }
             const anchorDoc = DocumentManager.Instance.getDocumentView(doc)?.ComponentView?.getAnchor?.(false, pinProps);
-            const pinDoc = Doc.MakeDelegate(anchorDoc && anchorDoc !== doc ? anchorDoc : doc);
-            pinDoc.presentationTargetDoc = anchorDoc ?? doc;
+            const pinDoc = anchorDoc?.type === DocumentType.CONFIG ? anchorDoc : Doc.MakeDelegate(anchorDoc && anchorDoc !== doc ? anchorDoc : doc);
+            pinDoc.presentation_targetDoc = anchorDoc ?? doc;
             pinDoc.title = doc.title + ' - Slide';
             pinDoc.data = new List<Doc>(); // the children of the embedding's layout are the presentation slide children.  the embedding's data field might be children of a collection, PDF data, etc -- in any case we don't want the tree view to "see" this data
-            pinDoc.presMovement = doc.type === DocumentType.SCRIPTING || pinProps?.pinDocLayout ? PresMovement.None : PresMovement.Zoom;
-            pinDoc.presDuration = pinDoc.presDuration ?? 1000;
-            pinDoc.groupWithUp = false;
+            pinDoc.presentation_movement = doc.type === DocumentType.SCRIPTING || pinProps?.pinDocLayout ? PresMovement.None : PresMovement.Zoom;
+            pinDoc.presentation_duration = pinDoc.presentation_duration ?? 1000;
+            pinDoc.presentation_groupWithUp = false;
             Doc.SetContainer(pinDoc, curPres);
             // these should potentially all be props passed down by the CollectionTreeView to the TreeView elements.  That way the PresBox could configure all of its children at render time
-            pinDoc.treeViewRenderAsBulletHeader = true; // forces a tree view to render the document next to the bullet in the header area
-            pinDoc.treeViewHeaderWidth = '100%'; // forces the header to grow to be the same size as its largest sibling.
-            pinDoc.treeViewChildrenOnRoot = true; // tree view will look for hierarchical children on the root doc, not the data doc.
-            pinDoc.treeViewFieldKey = 'data'; // tree view will treat the 'data' field as the field where the hierarchical children are located instead of using the document's layout string field
-            pinDoc.treeViewExpandedView = 'data'; // in case the data doc has an expandedView set, this will mask that field and use the 'data' field when expanding the tree view
-            pinDoc.treeViewHideHeaderIfTemplate = true; // this will force the document to render itself as the tree view header
+            pinDoc.treeView = ''; // not really needed, but makes key value pane look better
+            pinDoc.treeView_RenderAsBulletHeader = true; // forces a tree view to render the document next to the bullet in the header area
+            pinDoc.treeView_HeaderWidth = '100%'; // forces the header to grow to be the same size as its largest sibling.
+            pinDoc.treeView_ChildrenOnRoot = true; // tree view will look for hierarchical children on the root doc, not the data doc.
+            pinDoc.treeView_FieldKey = 'data'; // tree view will treat the 'data' field as the field where the hierarchical children are located instead of using the document's layout string field
+            pinDoc.treeView_ExpandedView = 'data'; // in case the data doc has an expandedView set, this will mask that field and use the 'data' field when expanding the tree view
+            pinDoc.treeView_HideHeaderIfTemplate = true; // this will force the document to render itself as the tree view header
             const duration = NumCast(doc[`${Doc.LayoutFieldKey(pinDoc)}_duration`], null);
 
             if (pinProps.pinViewport) PresBox.pinDocView(pinDoc, pinProps, anchorDoc ?? doc);
             if (!pinProps?.audioRange && duration !== undefined) {
                 pinDoc.mediaStart = 'manual';
                 pinDoc.mediaStop = 'manual';
-                pinDoc.presStartTime = NumCast(doc.clipStart);
-                pinDoc.presEndTime = NumCast(doc.clipEnd, duration);
+                pinDoc.config_clipStart = NumCast(doc.clipStart);
+                pinDoc.config_clipEnd = NumCast(doc.clipEnd, duration);
             }
             if (pinProps?.activeFrame !== undefined) {
-                pinDoc.presActiveFrame = pinProps?.activeFrame;
+                pinDoc.config_activeFrame = pinProps?.activeFrame;
                 pinDoc.title = doc.title + ' (move)';
-                pinDoc.presMovement = PresMovement.Pan;
+                pinDoc.presentation_movement = PresMovement.Pan;
             }
             if (pinProps?.currentFrame !== undefined) {
-                pinDoc.presCurrentFrame = pinProps?.currentFrame;
+                pinDoc.config_currentFrame = pinProps?.currentFrame;
                 pinDoc.title = doc.title + ' (move)';
-                pinDoc.presMovement = PresMovement.Pan;
+                pinDoc.presentation_movement = PresMovement.Pan;
             }
             if (pinDoc.stroke_isInkMask) {
-                pinDoc.presHideAfter = true;
-                pinDoc.presHideBefore = true;
-                pinDoc.presMovement = PresMovement.None;
+                pinDoc.presentation_hideAfter = true;
+                pinDoc.presentation_hideBefore = true;
+                pinDoc.presentation_movement = PresMovement.None;
             }
-            if (curPres.expandBoolean) pinDoc.presExpandInlineButton = true;
+            if (curPres.expandBoolean) pinDoc.presentation_expandInlineButton = true;
             Doc.AddDocToList(curPres, 'data', pinDoc, PresBox.Instance?.sortArray()?.lastElement());
             PresBox.Instance?.clearSelectedArray();
             pinDoc && PresBox.Instance?.addToSelectedArray(pinDoc); //Update selected array
@@ -393,7 +394,7 @@ export class TabDocView extends React.Component<TabDocViewProps> {
     };
 
     getCurrentFrame = () => {
-        return NumCast(Cast(PresBox.Instance.activeItem.presentationTargetDoc, Doc, null)._currentFrame);
+        return NumCast(Cast(PresBox.Instance.activeItem.presentation_targetDoc, Doc, null)._currentFrame);
     };
     static Activate = (tabDoc: Doc) => {
         const tab = Array.from(CollectionDockingView.Instance?.tabMap!).find(tab => tab.DashDoc === tabDoc && !tab.contentItem.config.props.keyValue);
diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx
index 25a547066..27f9ebc49 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -87,8 +87,8 @@ export enum TreeSort {
  * Renders a treeView of a collection of documents
  *
  * special fields:
- * treeViewOpen : flag denoting whether the documents sub-tree (contents) is visible or hidden
- * treeViewExpandedView : name of field whose contents are being displayed as the document's subtree
+ * treeView_Open : flag denoting whether the documents sub-tree (contents) is visible or hidden
+ * treeView_ExpandedView : name of field whose contents are being displayed as the document's subtree
  */
 @observer
 export class TreeView extends React.Component<TreeViewProps> {
@@ -104,16 +104,16 @@ export class TreeView extends React.Component<TreeViewProps> {
     private _treedropDisposer?: DragManager.DragDropDisposer;
 
     get treeViewOpenIsTransient() {
-        return this.props.treeView.doc.treeViewOpenIsTransient || Doc.IsDataProto(this.doc);
+        return this.props.treeView.doc.treeView_OpenIsTransient || Doc.IsDataProto(this.doc);
     }
     set treeViewOpen(c: boolean) {
         if (this.treeViewOpenIsTransient) this._transientOpenState = c;
         else {
-            this.doc.treeViewOpen = c;
+            this.doc.treeView_Open = c;
             this._transientOpenState = false;
         }
     }
-    @observable _transientOpenState = false; // override of the treeViewOpen field allowing the display state to be independent of the document's state
+    @observable _transientOpenState = false; // override of the treeView_Open field allowing the display state to be independent of the document's state
     @observable _editTitle: boolean = false;
     @observable _dref: DocumentView | undefined | null;
     get displayName() {
@@ -132,29 +132,29 @@ export class TreeView extends React.Component<TreeViewProps> {
             ? this.fieldKey
             : Doc.noviceMode
             ? 'layout'
-            : StrCast(this.props.treeView.doc.treeViewExpandedView, 'fields');
+            : StrCast(this.props.treeView.doc.treeView_ExpandedView, 'fields');
     }
 
     @computed get doc() {
         return this.props.document;
     }
     @computed get treeViewOpen() {
-        return (!this.treeViewOpenIsTransient && Doc.GetT(this.doc, 'treeViewOpen', 'boolean', true)) || this._transientOpenState;
+        return (!this.treeViewOpenIsTransient && Doc.GetT(this.doc, 'treeView_Open', 'boolean', true)) || this._transientOpenState;
     }
     @computed get treeViewExpandedView() {
-        return this.validExpandViewTypes.includes(StrCast(this.doc.treeViewExpandedView)) ? StrCast(this.doc.treeViewExpandedView) : this.defaultExpandedView;
+        return this.validExpandViewTypes.includes(StrCast(this.doc.treeView_ExpandedView)) ? StrCast(this.doc.treeView_ExpandedView) : this.defaultExpandedView;
     }
     @computed get MAX_EMBED_HEIGHT() {
         return NumCast(this.props.treeViewParent.maxEmbedHeight, 200);
     }
     @computed get dataDoc() {
-        return this.props.document.treeViewChildrenOnRoot ? this.doc : this.doc[DocData];
+        return this.props.document.treeView_ChildrenOnRoot ? this.doc : this.doc[DocData];
     }
     @computed get layoutDoc() {
         return Doc.Layout(this.doc);
     }
     @computed get fieldKey() {
-        return StrCast(this.doc._treeViewFieldKey, Doc.LayoutFieldKey(this.doc));
+        return StrCast(this.doc._treeView_FieldKey, Doc.LayoutFieldKey(this.doc));
     }
     @computed get childDocs() {
         return this.childDocList(this.fieldKey);
@@ -308,13 +308,13 @@ export class TreeView extends React.Component<TreeViewProps> {
         const bullet = Docs.Create.TextDocument('', {
             layout: CollectionView.LayoutString('data'),
             title: '-title-',
-            treeViewExpandedViewLock: true,
-            treeViewExpandedView: 'data',
+            treeView_ExpandedViewLock: true,
+            treeView_ExpandedView: 'data',
             _type_collection: CollectionViewType.Tree,
             layout_hideLinkButton: true,
             _layout_showSidebar: true,
             _layout_fitWidth: true,
-            treeViewType: TreeViewType.outline,
+            treeView_Type: TreeViewType.outline,
             x: 0,
             y: 0,
             _xMargin: 0,
@@ -395,7 +395,7 @@ export class TreeView extends React.Component<TreeViewProps> {
         };
         const addDoc = inside ? localAdd : parentAddDoc;
         const move = (!dropAction || dropAction === 'proto' || dropAction === 'move' || dropAction === 'same') && moveDocument;
-        const canAdd = (!this.props.treeView.outlineMode && !StrCast((inside ? this.props.document : this.props.treeViewParent)?.treeViewFreezeChildren).includes('add')) || forceAdd;
+        const canAdd = (!this.props.treeView.outlineMode && !StrCast((inside ? this.props.document : this.props.treeViewParent)?.treeView_FreezeChildren).includes('add')) || forceAdd;
         if (canAdd) {
             this.props.parentTreeView instanceof TreeView && (this.props.parentTreeView.dropping = true);
             const res = droppedDocuments.reduce((added, d) => (move ? move(d, undefined, addDoc) || (dropAction === 'proto' ? addDoc(d) : false) : addDoc(d)) || added, false);
@@ -438,7 +438,7 @@ export class TreeView extends React.Component<TreeViewProps> {
         doc && Object.keys(doc).forEach(key => !(key in ids) && doc[key] !== ComputedField.undefined && (ids[key] = key));
 
         for (const key of Object.keys(ids).slice().sort()) {
-            if (this.props.skipFields?.includes(key) || key === 'title' || key === 'treeViewOpen') continue;
+            if (this.props.skipFields?.includes(key) || key === 'title' || key === 'treeView_Open') continue;
             const contents = doc[key];
             let contentElement: (JSX.Element | null)[] | JSX.Element = [];
 
@@ -538,7 +538,7 @@ export class TreeView extends React.Component<TreeViewProps> {
         const expandKey = this.treeViewExpandedView;
         const sortings = (this.props.styleProvider?.(this.doc, this.props.treeView.props, StyleProp.TreeViewSortings) as { [key: string]: { color: string; icon: JSX.Element | string } }) ?? {};
         if (['links', 'annotations', 'embeddings', this.fieldKey].includes(expandKey)) {
-            const sorting = StrCast(this.doc.treeViewSortCriterion, TreeSort.None);
+            const sorting = StrCast(this.doc.treeView_SortCriterion, TreeSort.None);
             const sortKeys = Object.keys(sortings);
             const curSortIndex = Math.max(
                 0,
@@ -550,7 +550,7 @@ export class TreeView extends React.Component<TreeViewProps> {
             const localAdd = (doc: Doc, addBefore?: Doc, before?: boolean) => {
                 // if there's a sort ordering specified that can be modified on drop (eg, zorder can be modified, alphabetical can't),
                 // then the modification would be done here
-                const ordering = StrCast(this.doc.treeViewSortCriterion);
+                const ordering = StrCast(this.doc.treeView_SortCriterion);
                 if (ordering === TreeSort.Zindex) {
                     const docs = TreeView.sortDocs(this.childDocs || ([] as Doc[]), ordering);
                     doc.zIndex = addBefore ? NumCast(addBefore.zIndex) + (before ? -0.5 : 0.5) : 1000;
@@ -590,7 +590,7 @@ export class TreeView extends React.Component<TreeViewProps> {
                                 }}
                                 onClick={undoable(e => {
                                     if (this.props.isContentActive() && Math.abs(e.clientX - downX) < 3 && Math.abs(e.clientY - downY) < 3) {
-                                        !this.props.treeView.outlineMode && (this.doc.treeViewSortCriterion = sortKeys[(curSortIndex + 1) % sortKeys.length]);
+                                        !this.props.treeView.outlineMode && (this.doc.treeView_SortCriterion = sortKeys[(curSortIndex + 1) % sortKeys.length]);
                                         e.stopPropagation();
                                     }
                                 }, 'sort order')}
@@ -601,7 +601,7 @@ export class TreeView extends React.Component<TreeViewProps> {
                         style={{ cursor: 'inherit' }}
                         key={expandKey + 'more'}
                         title="click to change sort order"
-                        className={''} //this.doc.treeViewHideTitle ? 'no-indent' : ''}
+                        className={''} //this.doc.treeView_HideTitle ? 'no-indent' : ''}
                         onPointerDown={e => {
                             downX = e.clientX;
                             downY = e.clientY;
@@ -609,7 +609,7 @@ export class TreeView extends React.Component<TreeViewProps> {
                         }}
                         onClick={undoable(e => {
                             if (this.props.isContentActive() && Math.abs(e.clientX - downX) < 3 && Math.abs(e.clientY - downY) < 3) {
-                                !this.props.treeView.outlineMode && (this.doc.treeViewSortCriterion = sortKeys[(curSortIndex + 1) % sortKeys.length]);
+                                !this.props.treeView.outlineMode && (this.doc.treeView_SortCriterion = sortKeys[(curSortIndex + 1) % sortKeys.length]);
                                 e.stopPropagation();
                             }
                         }, 'sort order')}>
@@ -683,7 +683,7 @@ export class TreeView extends React.Component<TreeViewProps> {
                 {
                     this: this.doc.isTemplateForField && this.props.dataDoc ? this.props.dataDoc : this.doc,
                     heading: this.props.treeViewParent.title,
-                    checked: this.doc.treeViewChecked === 'check' ? 'x' : this.doc.treeViewChecked === 'x' ? 'remove' : 'check',
+                    checked: this.doc.treeView_Checked === 'check' ? 'x' : this.doc.treeView_Checked === 'x' ? 'remove' : 'check',
                     containingTreeView: this.props.treeView.props.Document,
                 },
                 console.log
@@ -698,7 +698,7 @@ export class TreeView extends React.Component<TreeViewProps> {
         TraceMobx();
         const iconType = this.props.treeView.props.styleProvider?.(this.doc, this.props.treeView.props, StyleProp.TreeViewIcon + (this.treeViewOpen ? ':open' : !this.childDocs.length ? ':empty' : '')) || 'question';
         const color = StrCast(Doc.UserDoc().userColor);
-        const checked = this.onCheckedClick ? this.doc.treeViewChecked ?? 'unchecked' : undefined;
+        const checked = this.onCheckedClick ? this.doc.treeView_Checked ?? 'unchecked' : undefined;
         return (
             <div
                 className={`bullet${this.props.treeView.outlineMode ? '-outline' : ''}`}
@@ -748,9 +748,9 @@ export class TreeView extends React.Component<TreeViewProps> {
     }
     @action
     expandNextviewType = () => {
-        if (this.treeViewOpen && !this.doc.isFolder && !this.props.treeView.outlineMode && !this.doc.treeViewExpandedViewLock) {
+        if (this.treeViewOpen && !this.doc.isFolder && !this.props.treeView.outlineMode && !this.doc.treeView_ExpandedViewLock) {
             const next = (modes: any[]) => modes[(modes.indexOf(StrCast(this.treeViewExpandedView)) + 1) % modes.length];
-            this.doc.treeViewExpandedView = next(this.validExpandViewTypes);
+            this.doc.treeView_ExpandedView = next(this.validExpandViewTypes);
         }
         this.treeViewOpen = true;
     };
@@ -759,7 +759,7 @@ export class TreeView extends React.Component<TreeViewProps> {
     @computed get titleButtons() {
         const customHeaderButtons = this.props.styleProvider?.(this.doc, this.props.treeView.props, StyleProp.Decorations);
         const color = StrCast(Doc.UserDoc().userColor);
-        return this.props.treeViewHideHeaderFields() || this.doc.treeViewHideHeaderFields ? null : (
+        return this.props.treeViewHideHeaderFields() || this.doc.treeView_HideHeaderFields ? null : (
             <>
                 {customHeaderButtons} {/* e.g.,. hide button is set by dashboardStyleProvider */}
                 <IconButton
@@ -771,7 +771,7 @@ export class TreeView extends React.Component<TreeViewProps> {
                         e.stopPropagation();
                     }}
                 />
-                {Doc.noviceMode ? null : this.doc.treeViewExpandedViewLock || Doc.IsSystem(this.doc) ? null : (
+                {Doc.noviceMode ? null : this.doc.treeView_ExpandedViewLock || Doc.IsSystem(this.doc) ? null : (
                     <span className="collectionTreeView-keyHeader" title="type of expanded data" key={this.treeViewExpandedView} onPointerDown={this.expandNextviewType}>
                         {this.treeViewExpandedView}
                     </span>
@@ -815,7 +815,7 @@ export class TreeView extends React.Component<TreeViewProps> {
 
     onChildClick = () => this.props.onChildClick?.() ?? (this._editTitleScript?.() || ScriptField.MakeFunction(`DocFocusOrOpen(self)`)!);
 
-    onChildDoubleClick = () => ScriptCast(this.props.treeView.Document.treeViewChildDoubleClick, !this.props.treeView.outlineMode ? this._openScript?.() : null);
+    onChildDoubleClick = () => ScriptCast(this.props.treeView.Document.treeView_ChildDoubleClick, !this.props.treeView.outlineMode ? this._openScript?.() : null);
 
     refocus = () => this.props.treeView.props.focus(this.props.treeView.props.Document, {});
     ignoreEvent = (e: any) => {
@@ -861,7 +861,7 @@ export class TreeView extends React.Component<TreeViewProps> {
         return this.props?.treeView?.props.styleProvider?.(doc, props, property); // properties are inherited from the CollectionTreeView, not the hierarchical parent in the treeView
     };
     onKeyDown = (e: React.KeyboardEvent, fieldProps: FieldViewProps) => {
-        if (this.doc.treeViewHideHeader || (this.doc.treeViewHideHeaderIfTemplate && this.props.treeView.props.childLayoutTemplate?.()) || this.props.treeView.outlineMode) {
+        if (this.doc.treeView_HideHeader || (this.doc.treeView_HideHeaderIfTemplate && this.props.treeView.props.childLayoutTemplate?.()) || this.props.treeView.outlineMode) {
             switch (e.key) {
                 case 'Tab':
                     e.stopPropagation?.();
@@ -1068,7 +1068,7 @@ export class TreeView extends React.Component<TreeViewProps> {
 
     // renders the text version of a document as the header.  This is used in the file system mode and in other vanilla tree views.
     @computed get renderTitleAsHeader() {
-        return this.props.treeView.Document.treeViewHideUnrendered && this.doc.layout_unrendered && !this.doc.treeViewFieldKey ? (
+        return this.props.treeView.Document.treeView_HideUnrendered && this.doc.layout_unrendered && !this.doc.treeView_FieldKey ? (
             <div></div>
         ) : (
             <>
@@ -1089,7 +1089,7 @@ export class TreeView extends React.Component<TreeViewProps> {
     };
 
     @computed get renderBorder() {
-        const sorting = StrCast(this.doc.treeViewSortCriterion, TreeSort.None);
+        const sorting = StrCast(this.doc.treeView_SortCriterion, TreeSort.None);
         const sortings = (this.props.styleProvider?.(this.doc, this.props.treeView.props, StyleProp.TreeViewSortings) ?? {}) as { [key: string]: { color: string; label: string } };
         return (
             <div className={`treeView-border${this.props.treeView.outlineMode ? TreeViewType.outline : ''}`} style={{ borderColor: sortings[sorting]?.color }}>
@@ -1109,7 +1109,7 @@ export class TreeView extends React.Component<TreeViewProps> {
 
     render() {
         TraceMobx();
-        const hideTitle = this.doc.treeViewHideHeader || (this.doc.treeViewHideHeaderIfTemplate && this.props.treeView.props.childLayoutTemplate?.()) || this.props.treeView.outlineMode;
+        const hideTitle = this.doc.treeView_HideHeader || (this.doc.treeView_HideHeaderIfTemplate && this.props.treeView.props.childLayoutTemplate?.()) || this.props.treeView.outlineMode;
         return this.props.renderedIds?.indexOf(this.doc[Id]) !== -1 ? (
             '<' + this.doc.title + '>' // just print the title of documents we've previously rendered in this hierarchical path to avoid cycles
         ) : (
@@ -1121,9 +1121,9 @@ export class TreeView extends React.Component<TreeViewProps> {
                 // onKeyDown={this.onKeyDown}
             >
                 <li className="collection-child">
-                    {hideTitle && this.doc.type !== DocumentType.RTF && !this.doc.treeViewRenderAsBulletHeader // should test for prop 'treeViewRenderDocWithBulletAsHeader"
+                    {hideTitle && this.doc.type !== DocumentType.RTF && !this.doc.treeView_RenderAsBulletHeader // should test for prop 'treeView_RenderDocWithBulletAsHeader"
                         ? this.renderEmbeddedDocument(false, returnFalse)
-                        : this.renderBulletHeader(hideTitle ? this.renderDocumentAsHeader(!this.doc.treeViewRenderAsBulletHeader) : this.renderTitleAsHeader, this._editTitle)}
+                        : this.renderBulletHeader(hideTitle ? this.renderDocumentAsHeader(!this.doc.treeView_RenderAsBulletHeader) : this.renderTitleAsHeader, this._editTitle)}
                 </li>
             </div>
         );
@@ -1162,7 +1162,7 @@ export class TreeView extends React.Component<TreeViewProps> {
         childDocs: Doc[],
         treeView: CollectionTreeView,
         parentTreeView: CollectionTreeView | TreeView | undefined,
-        treeViewParent: Doc,
+        treeView_Parent: Doc,
         dataDoc: Doc | undefined,
         parentCollectionDoc: Doc | undefined,
         containerPrevSibling: Doc | undefined,
@@ -1176,7 +1176,7 @@ export class TreeView extends React.Component<TreeViewProps> {
         isContentActive: (outsideReaction?: boolean) => boolean,
         panelWidth: () => number,
         renderDepth: number,
-        treeViewHideHeaderFields: () => boolean,
+        treeView_HideHeaderFields: () => boolean,
         renderedIds: string[],
         onCheckedClick: undefined | (() => ScriptField),
         onChildClick: undefined | (() => ScriptField),
@@ -1193,19 +1193,19 @@ export class TreeView extends React.Component<TreeViewProps> {
         hierarchyIndex?: number[],
         renderCount?: number
     ) {
-        const viewSpecScript = Cast(treeViewParent.viewSpecScript, ScriptField);
+        const viewSpecScript = Cast(treeView_Parent.viewSpecScript, ScriptField);
         if (viewSpecScript) {
             childDocs = childDocs.filter(d => viewSpecScript.script.run({ doc: d }, console.log).result);
         }
 
-        const docs = TreeView.sortDocs(childDocs, StrCast(treeViewParent.treeViewSortCriterion, TreeSort.None));
+        const docs = TreeView.sortDocs(childDocs, StrCast(treeView_Parent.treeView_SortCriterion, TreeSort.None));
         const rowWidth = () => panelWidth() - treeBulletWidth() * (treeView.props.NativeDimScaling?.() || 1);
-        const treeViewRefs = new Map<Doc, TreeView | undefined>();
+        const treeView_Refs = new Map<Doc, TreeView | undefined>();
         return docs
             .filter(child => child instanceof Doc)
             .map((child, i) => {
                 if (renderCount && i > renderCount) return null;
-                const pair = Doc.GetLayoutDataDocPair(treeViewParent, dataDoc, child);
+                const pair = Doc.GetLayoutDataDocPair(treeView_Parent, dataDoc, child);
                 if (!pair.layout || pair.data instanceof Promise) {
                     return null;
                 }
@@ -1218,11 +1218,11 @@ export class TreeView extends React.Component<TreeViewProps> {
                         FormattedTextBox.SelectOnLoad = child[Id];
                         TreeView._editTitleOnLoad = editTitle ? { id: child[Id], parent } : undefined;
                         Doc.AddDocToList(newParent, fieldKey, child, addAfter, false);
-                        newParent.treeViewOpen = true;
+                        newParent.treeView_Open = true;
                         Doc.SetContainer(child, treeView.Document);
                     }
                 };
-                const indent = i === 0 ? undefined : (editTitle: boolean) => dentDoc(editTitle, docs[i - 1], undefined, treeViewRefs.get(docs[i - 1]));
+                const indent = i === 0 ? undefined : (editTitle: boolean) => dentDoc(editTitle, docs[i - 1], undefined, treeView_Refs.get(docs[i - 1]));
                 const outdent = !parentCollectionDoc ? undefined : (editTitle: boolean) => dentDoc(editTitle, parentCollectionDoc, containerPrevSibling, parentTreeView instanceof TreeView ? parentTreeView.props.parentTreeView : undefined);
                 const addDocument = (doc: Doc | Doc[], annotationKey?: string, relativeTo?: Doc, before?: boolean) => add(doc, relativeTo ?? docs[i], before !== undefined ? before : false);
                 const childLayout = Doc.Layout(pair.layout);
@@ -1233,10 +1233,10 @@ export class TreeView extends React.Component<TreeViewProps> {
                 return (
                     <TreeView
                         key={child[Id]}
-                        ref={r => treeViewRefs.set(child, r ? r : undefined)}
+                        ref={r => treeView_Refs.set(child, r ? r : undefined)}
                         document={pair.layout}
                         dataDoc={pair.data}
-                        treeViewParent={treeViewParent}
+                        treeViewParent={treeView_Parent}
                         prevSibling={docs[i]}
                         // TODO: [AL] add these
                         hierarchyIndex={hierarchyIndex ? [...hierarchyIndex, i + 1] : undefined}
@@ -1248,7 +1248,7 @@ export class TreeView extends React.Component<TreeViewProps> {
                         onCheckedClick={onCheckedClick}
                         onChildClick={onChildClick}
                         renderDepth={renderDepth}
-                        removeDoc={StrCast(treeViewParent.treeViewFreezeChildren).includes('remove') ? undefined : remove}
+                        removeDoc={StrCast(treeView_Parent.treeView_FreezeChildren).includes('remove') ? undefined : remove}
                         addDocument={addDocument}
                         styleProvider={styleProvider}
                         panelWidth={rowWidth}
@@ -1259,7 +1259,7 @@ export class TreeView extends React.Component<TreeViewProps> {
                         addDocTab={addDocTab}
                         ScreenToLocalTransform={screenToLocalXf}
                         isContentActive={isContentActive}
-                        treeViewHideHeaderFields={treeViewHideHeaderFields}
+                        treeViewHideHeaderFields={treeView_HideHeaderFields}
                         renderedIds={renderedIds}
                         skipFields={skipFields}
                         firstLevel={firstLevel}
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss
index c6419885b..e4ae251c8 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss
@@ -153,7 +153,12 @@
     overflow-y: auto;
     overflow-x: hidden;
 }
-
+.collectionFreeFormView-brushView {
+    pointer-events: none;
+    position: absolute;
+    transition: opacity 0.5s;
+    z-index: 1000;
+}
 .collectionfreeformview-container {
     // touch action none means that the browser will handle none of the touch actions. this allows us to implement our own actions.
     touch-action: none;
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index e1455525e..ffcf0999c 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -319,7 +319,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
         // focus on the document in the collection
         const didMove = !cantTransform && !anchor.z && (panX !== savedState.panX || panY !== savedState.panY || scale !== savedState.scale);
         if (didMove) options.didMove = true;
-        // glr: freeform transform speed can be set by adjusting presTransition field - needs a way of knowing when presentation is not active...
+        // glr: freeform transform speed can be set by adjusting presentation_transition field - needs a way of knowing when presentation is not active...
         if (didMove) {
             const focusTime = options?.instant ? 0 : options.zoomTime ?? 500;
             (options.zoomScale ?? options.willZoomCentered) && scale && (this.Document[this.scaleFieldKey] = scale);
@@ -681,6 +681,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
             case GestureUtils.Gestures.Stroke:
                 const points = ge.points;
                 const B = this.getTransform().transformBounds(ge.bounds.left, ge.bounds.top, ge.bounds.width, ge.bounds.height);
+                console.log(ge.bounds.left, ge.bounds.top, ge.bounds.width, ge.bounds.height);
                 const inkDoc = Docs.Create.InkDocument(
                     ActiveInkColor(),
                     ActiveInkWidth() * this.props.ScreenToLocalTransform().Scale,
@@ -1050,7 +1051,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
     onPointerWheel = (e: React.WheelEvent): void => {
         if (this.Document._isGroup || !this.isContentActive()) return; // group style collections neither pan nor zoom
         PresBox.Instance?.pauseAutoPres();
-        if (this.layoutDoc._Transform || this.props.Document.treeViewOutlineMode === TreeViewType.outline) return;
+        if (this.layoutDoc._Transform || this.props.Document.treeView_OutlineMode === TreeViewType.outline) return;
         e.stopPropagation();
         const docHeight = NumCast(this.rootDoc[Doc.LayoutFieldKey(this.rootDoc) + '_nativeHeight'], this.nativeHeight);
         const scrollable = NumCast(this.layoutDoc[this.scaleFieldKey], 1) === 1 && docHeight > this.props.PanelHeight() / this.nativeDimScaling + 1e-4;
@@ -1318,7 +1319,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
                 layout_showTitle={this.props.childlayout_showTitle}
                 dontRegisterView={this.props.dontRenderDocuments || this.props.dontRegisterView}
                 pointerEvents={this.pointerEvents}
-                //fitContentsToBox={this.props.fitContentsToBox || BoolCast(this.props.treeViewFreezeChildDimensions)} // bcz: check this
+                //fitContentsToBox={this.props.fitContentsToBox || BoolCast(this.props.treeView_FreezeChildDimensions)} // bcz: check this
             />
         );
     }
@@ -1537,7 +1538,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
 
     getAnchor = (addAsAnnotation: boolean, pinProps?: PinProps) => {
         // create an anchor that saves information about the current state of the freeform view (pan, zoom, view type)
-        const anchor = Docs.Create.ConfigDocument({ title: 'ViewSpec - ' + StrCast(this.layoutDoc._type_collection), layout_unrendered: true, presTransition: 500, annotationOn: this.rootDoc });
+        const anchor = Docs.Create.ConfigDocument({ title: 'ViewSpec - ' + StrCast(this.layoutDoc._type_collection), layout_unrendered: true, presentation_transition: 500, annotationOn: this.rootDoc });
         PresBox.pinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: { ...(pinProps?.pinData ?? {}), pannable: !this.Document._isGroup, type_collection: true, filters: true } }, this.rootDoc);
 
         if (addAsAnnotation) {
@@ -1866,6 +1867,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
 
     showPresPaths = () => (CollectionFreeFormView.ShowPresPaths ? PresBox.Instance.getPaths(this.rootDoc) : null);
 
+    brushedView = () => this._brushedView;
     @computed get marqueeView() {
         TraceMobx();
         return (
@@ -1908,13 +1910,13 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
                         </div>
                     ) : null}
                     <CollectionFreeFormViewPannableContents
-                        brushView={this._brushedView}
+                        brushedView={this.brushedView}
                         isAnnotationOverlay={this.isAnnotationOverlay}
                         isAnnotationOverlayScrollable={this.props.isAnnotationOverlayScrollable}
                         transform={this.contentTransform}
                         zoomScaling={this.zoomScaling}
                         presPaths={this.showPresPaths}
-                        presPinView={BoolCast(this.Document.presPinView)}
+                        presPinView={BoolCast(this.Document.config_pinView)}
                         transition={this._panZoomTransition ? `transform ${this._panZoomTransition}ms` : Cast(this.layoutDoc._viewTransition, 'string', Cast(this.props.DocumentView?.()?.rootDoc._viewTransition, 'string', null))}
                         viewDefDivClick={this.props.viewDefDivClick}>
                         {this.children}
@@ -1945,19 +1947,19 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
     };
 
     @action
-    brushView = (viewport: { width: number; height: number; panX: number; panY: number }) => {
-        this._brushedView = { ...viewport, panX: viewport.panX - viewport.width / 2, panY: viewport.panY - viewport.height / 2, opacity: 1 };
+    brushView = (viewport: { width: number; height: number; panX: number; panY: number }, transTime: number) => {
         this._brushtimer1 && clearTimeout(this._brushtimer1);
         this._brushtimer && clearTimeout(this._brushtimer);
+        this._brushedView = { width: 0, height: 0, panX: 0, panY: 0, opacity: 0 };
         this._brushtimer1 = setTimeout(
             action(() => {
-                this._brushedView.opacity = 0;
+                this._brushedView = { ...viewport, panX: viewport.panX - viewport.width / 2, panY: viewport.panY - viewport.height / 2, opacity: 1 };
                 this._brushtimer = setTimeout(
-                    action(() => (this._brushedView = { width: 0, height: 0, panX: 0, panY: 0, opacity: 0 })),
-                    500
+                    action(() => (this._brushedView.opacity = 0)),
+                    2500
                 );
             }),
-            1000
+            transTime + 1
         );
     };
     lightboxPanelWidth = () => Math.max(0, this.props.PanelWidth() - 30);
@@ -2084,7 +2086,7 @@ interface CollectionFreeFormViewPannableContentsProps {
     presPinView?: boolean;
     isAnnotationOverlay: boolean | undefined;
     isAnnotationOverlayScrollable: boolean | undefined;
-    brushView: { panX: number; panY: number; width: number; height: number; opacity: number };
+    brushedView: () => { panX: number; panY: number; width: number; height: number; opacity: number };
 }
 
 @observer
@@ -2156,6 +2158,7 @@ class CollectionFreeFormViewPannableContents extends React.Component<CollectionF
     }
 
     render() {
+        const brushedView = this.props.brushedView();
         return (
             <div
                 className={'collectionfreeformview' + (this.props.viewDefDivClick ? '-viewDef' : '-none')}
@@ -2173,21 +2176,18 @@ class CollectionFreeFormViewPannableContents extends React.Component<CollectionF
                     //willChange: "transform"
                 }}>
                 {this.props.children}
-                {!this.props.brushView.width ? null : (
+                {
                     <div
                         className="collectionFreeFormView-brushView"
                         style={{
-                            zIndex: 1000,
-                            opacity: this.props.brushView.opacity,
-                            border: 'orange solid 2px',
-                            position: 'absolute',
-                            transform: `translate(${this.props.brushView.panX}px, ${this.props.brushView.panY}px)`,
-                            width: this.props.brushView.width,
-                            height: this.props.brushView.height,
-                            transition: 'opacity 2s',
+                            opacity: brushedView.opacity,
+                            transform: `translate(${brushedView.panX}px, ${brushedView.panY}px)`,
+                            width: brushedView.width,
+                            height: brushedView.height,
+                            border: `orange solid ${brushedView.width * 0.005}px`,
                         }}
                     />
-                )}
+                }
                 {this.presPaths}
             </div>
         );
diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx
index 737d675aa..a81707ea4 100644
--- a/src/client/views/linking/LinkMenuItem.tsx
+++ b/src/client/views/linking/LinkMenuItem.tsx
@@ -84,7 +84,7 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
             },
             emptyFunction,
             action(() => {
-                const trail = DocCast(this.props.docView.rootDoc.presTrail);
+                const trail = DocCast(this.props.docView.rootDoc.presentationTrail);
                 if (trail) {
                     Doc.ActivePresentation = trail;
                     DocumentViewInternal.addDocTabFunc(trail, OpenWhere.replaceRight);
diff --git a/src/client/views/nodes/DataVizBox/DataVizBox.tsx b/src/client/views/nodes/DataVizBox/DataVizBox.tsx
index 0cc73f32f..059c39c68 100644
--- a/src/client/views/nodes/DataVizBox/DataVizBox.tsx
+++ b/src/client/views/nodes/DataVizBox/DataVizBox.tsx
@@ -20,7 +20,7 @@ export enum DataVizView {
     TABLE = 'table',
     LINECHART = 'lineChart',
     HISTOGRAM = 'histogram',
-    PIECHART = 'pieChart'
+    PIECHART = 'pieChart',
 }
 
 @observer
@@ -39,20 +39,22 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
 
     // current displayed chart type
     @computed get dataVizView(): DataVizView {
-        return StrCast(this.layoutDoc._dataVizView, 'table') as DataVizView;
+        return StrCast(this.layoutDoc._dataViz, 'table') as DataVizView;
     }
 
     @action // pinned / linked anchor doc includes selected rows, graph titles, and graph colors
     restoreView = (data: Doc) => {
-        const changedView = this.dataVizView !== data.presDataVizView && (this.layoutDoc._dataVizView = data.presDataVizView);
-        const changedAxes = this.axes.join('') !== StrListCast(data.presDataVizAxes).join('') && (this.layoutDoc._data_vizAxes = new List<string>(StrListCast(data.presDataVizAxes)));
-        this.layoutDoc.selected = Field.Copy(data.selected);
+        const changedView = this.dataVizView !== data.config_dataViz && (this.layoutDoc._dataViz = data.config_dataViz);
+        const changedAxes = this.axes.join('') !== StrListCast(data.config_dataVizAxes).join('') && (this.layoutDoc._dataViz_axes = new List<string>(StrListCast(data.config_dataVizAxes)));
+        this.layoutDoc.dataViz_selectedRows = Field.Copy(data.dataViz_selectedRows);
         this.layoutDoc.histogramBarColors = Field.Copy(data.histogramBarColors);
         this.layoutDoc.defaultHistogramColor = data.defaultHistogramColor;
         this.layoutDoc.pieSliceColors = Field.Copy(data.pieSliceColors);
         Object.keys(this.layoutDoc).map(key => {
-            if (key.startsWith('histogram-title') || key.startsWith('lineChart-title') || key.startsWith('pieChart-title')){ this.layoutDoc['_'+key] = data[key]; }
-        })
+            if (key.startsWith('histogram_title') || key.startsWith('lineChart_title') || key.startsWith('pieChart_title')) {
+                this.layoutDoc['_' + key] = data[key];
+            }
+        });
         const func = () => this._chartRenderer?.restoreView(data);
         if (changedView || changedAxes) {
             setTimeout(func, 100);
@@ -69,23 +71,25 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
                   // this is for when we want the whole doc (so when the chartBox getAnchor returns without a marker)
                   /*put in some options*/
               });
-        anchor.presDataVizView = this.dataVizView;
-        anchor.presDataVizAxes = this.axes.length ? new List<string>(this.axes) : undefined;
-        anchor.selected = Field.Copy(this.layoutDoc.selected);
+        anchor.config_dataViz = this.dataVizView;
+        anchor.config_dataVizAxes = this.axes.length ? new List<string>(this.axes) : undefined;
+        anchor.dataViz_selectedRows = Field.Copy(this.layoutDoc.dataViz_selectedRows);
         anchor.histogramBarColors = Field.Copy(this.layoutDoc.histogramBarColors);
         anchor.defaultHistogramColor = this.layoutDoc.defaultHistogramColor;
         anchor.pieSliceColors = Field.Copy(this.layoutDoc.pieSliceColors);
         Object.keys(this.layoutDoc).map(key => {
-            if (key.startsWith('histogram-title') || key.startsWith('lineChart-title') || key.startsWith('pieChart-title')){ anchor[key] = this.layoutDoc[key]; }
-        })
+            if (key.startsWith('histogram_title') || key.startsWith('lineChart_title') || key.startsWith('pieChart_title')) {
+                anchor[key] = this.layoutDoc[key];
+            }
+        });
         this.addDocument(anchor);
         return anchor;
     };
 
     @computed.struct get axes() {
-        return StrListCast(this.layoutDoc.data_vizAxes);
+        return StrListCast(this.layoutDoc.dataViz_axes);
     }
-    selectAxes = (axes: string[]) => (this.layoutDoc.data_vizAxes = new List<string>(axes));
+    selectAxes = (axes: string[]) => (this.layoutDoc.dataViz_axes = new List<string>(axes));
 
     // toggles for user to decide which chart type to view the data in
     @computed get selectView() {
@@ -94,10 +98,53 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
         const margin = { top: 10, right: 25, bottom: 75, left: 45 };
         if (!this.pairs) return 'no data';
         switch (this.dataVizView) {
-            case DataVizView.TABLE:     return <TableBox layoutDoc={this.layoutDoc} pairs={this.pairs} axes={this.axes} height={height} width={width} margin={margin} rootDoc={this.rootDoc} docView={this.props.DocumentView} selectAxes={this.selectAxes}/>;
-            case DataVizView.LINECHART: return <LineChart layoutDoc={this.layoutDoc} ref={r => (this._chartRenderer = r ?? undefined)} height={height} width={width} fieldKey={this.fieldKey} margin={margin} rootDoc={this.rootDoc} axes={this.axes} pairs={this.pairs} dataDoc={this.dataDoc} />;
-            case DataVizView.HISTOGRAM: return <Histogram layoutDoc={this.layoutDoc} ref={r => (this._chartRenderer = r ?? undefined)} height={height} width={width} fieldKey={this.fieldKey} margin={margin} rootDoc={this.rootDoc} axes={this.axes} pairs={this.pairs} dataDoc={this.dataDoc} />;
-            case DataVizView.PIECHART: return <PieChart layoutDoc={this.layoutDoc} ref={r => (this._chartRenderer = r ?? undefined)} height={height} width={width} fieldKey={this.fieldKey} margin={margin} rootDoc={this.rootDoc} axes={this.axes} pairs={this.pairs} dataDoc={this.dataDoc} />;
+            case DataVizView.TABLE:
+                return <TableBox layoutDoc={this.layoutDoc} pairs={this.pairs} axes={this.axes} height={height} width={width} margin={margin} rootDoc={this.rootDoc} docView={this.props.DocumentView} selectAxes={this.selectAxes} />;
+            case DataVizView.LINECHART:
+                return (
+                    <LineChart
+                        layoutDoc={this.layoutDoc}
+                        ref={r => (this._chartRenderer = r ?? undefined)}
+                        height={height}
+                        width={width}
+                        fieldKey={this.fieldKey}
+                        margin={margin}
+                        rootDoc={this.rootDoc}
+                        axes={this.axes}
+                        pairs={this.pairs}
+                        dataDoc={this.dataDoc}
+                    />
+                );
+            case DataVizView.HISTOGRAM:
+                return (
+                    <Histogram
+                        layoutDoc={this.layoutDoc}
+                        ref={r => (this._chartRenderer = r ?? undefined)}
+                        height={height}
+                        width={width}
+                        fieldKey={this.fieldKey}
+                        margin={margin}
+                        rootDoc={this.rootDoc}
+                        axes={this.axes}
+                        pairs={this.pairs}
+                        dataDoc={this.dataDoc}
+                    />
+                );
+            case DataVizView.PIECHART:
+                return (
+                    <PieChart
+                        layoutDoc={this.layoutDoc}
+                        ref={r => (this._chartRenderer = r ?? undefined)}
+                        height={height}
+                        width={width}
+                        fieldKey={this.fieldKey}
+                        margin={margin}
+                        rootDoc={this.rootDoc}
+                        axes={this.axes}
+                        pairs={this.pairs}
+                        dataDoc={this.dataDoc}
+                    />
+                );
         }
     }
 
@@ -118,14 +165,10 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
     }
 
     render() {
-        if (!this.layoutDoc._dataVizView) this.layoutDoc._dataVizView = this.dataVizView;
+        if (!this.layoutDoc._dataViz) this.layoutDoc._dataViz = this.dataVizView;
         return !this.pairs?.length ? (
             // displays how to get data into the DataVizBox if its empty
-            <div className="start-message">
-                To create a DataViz box, either import / drag a CSV file into your canvas
-                or copy a data table and use the command 'ctrl + p' to bring the data table
-                to your canvas.
-            </div>
+            <div className="start-message">To create a DataViz box, either import / drag a CSV file into your canvas or copy a data table and use the command 'ctrl + p' to bring the data table to your canvas.</div>
         ) : (
             <div
                 className="dataViz"
@@ -141,22 +184,10 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
                     )
                 }>
                 <div className={'datatype-button'}>
-                    <Toggle text={"TABLE"} toggleType={ToggleType.BUTTON} type={Type.SEC} color={"black"} 
-                        onClick={e => this.layoutDoc._dataVizView = DataVizView.TABLE} 
-                        toggleStatus={this.layoutDoc._dataVizView == DataVizView.TABLE} 
-                    />
-                    <Toggle text={"LINECHART"} toggleType={ToggleType.BUTTON} type={Type.SEC} color={"black"} 
-                        onClick={e => this.layoutDoc._dataVizView = DataVizView.LINECHART} 
-                        toggleStatus={this.layoutDoc._dataVizView == DataVizView.LINECHART} 
-                    />
-                    <Toggle text={"HISTOGRAM"} toggleType={ToggleType.BUTTON} type={Type.SEC} color={"black"} 
-                        onClick={e => this.layoutDoc._dataVizView = DataVizView.HISTOGRAM} 
-                        toggleStatus={this.layoutDoc._dataVizView == DataVizView.HISTOGRAM} 
-                    />
-                    <Toggle text={"PIE CHART"} toggleType={ToggleType.BUTTON} type={Type.SEC} color={"black"} 
-                        onClick={e => this.layoutDoc._dataVizView = DataVizView.PIECHART} 
-                        toggleStatus={this.layoutDoc._dataVizView == DataVizView.PIECHART} 
-                    />
+                    <Toggle text={'TABLE'} toggleType={ToggleType.BUTTON} type={Type.SEC} color={'black'} onClick={e => (this.layoutDoc._dataViz = DataVizView.TABLE)} toggleStatus={this.layoutDoc._dataViz == DataVizView.TABLE} />
+                    <Toggle text={'LINECHART'} toggleType={ToggleType.BUTTON} type={Type.SEC} color={'black'} onClick={e => (this.layoutDoc._dataViz = DataVizView.LINECHART)} toggleStatus={this.layoutDoc._dataViz == DataVizView.LINECHART} />
+                    <Toggle text={'HISTOGRAM'} toggleType={ToggleType.BUTTON} type={Type.SEC} color={'black'} onClick={e => (this.layoutDoc._dataViz = DataVizView.HISTOGRAM)} toggleStatus={this.layoutDoc._dataViz == DataVizView.HISTOGRAM} />
+                    <Toggle text={'PIE CHART'} toggleType={ToggleType.BUTTON} type={Type.SEC} color={'black'} onClick={e => (this.layoutDoc._dataViz = DataVizView.PIECHART)} toggleStatus={this.layoutDoc._dataViz == DataVizView.PIECHART} />
                 </div>
                 {this.selectView}
             </div>
diff --git a/src/client/views/nodes/DataVizBox/components/Histogram.tsx b/src/client/views/nodes/DataVizBox/components/Histogram.tsx
index df6aac6bc..086db2a47 100644
--- a/src/client/views/nodes/DataVizBox/components/Histogram.tsx
+++ b/src/client/views/nodes/DataVizBox/components/Histogram.tsx
@@ -1,20 +1,20 @@
-import { observer } from "mobx-react";
-import { Doc, StrListCast } from "../../../../../fields/Doc";
+import { observer } from 'mobx-react';
+import { Doc, StrListCast } from '../../../../../fields/Doc';
 import * as React from 'react';
 import * as d3 from 'd3';
-import { IReactionDisposer, action, computed, observable, reaction } from "mobx";
-import { LinkManager } from "../../../../util/LinkManager";
-import { Cast, DocCast, StrCast} from "../../../../../fields/Types";
-import { PinProps, PresBox } from "../../trails";
-import { Docs } from "../../../../documents/Documents";
-import { List } from "../../../../../fields/List";
+import { IReactionDisposer, action, computed, observable, reaction } from 'mobx';
+import { LinkManager } from '../../../../util/LinkManager';
+import { Cast, DocCast, StrCast } from '../../../../../fields/Types';
+import { PinProps, PresBox } from '../../trails';
+import { Docs } from '../../../../documents/Documents';
+import { List } from '../../../../../fields/List';
 import './Chart.scss';
-import { ColorPicker, EditableText, IconButton, Size, Type } from "browndash-components";
-import { FaFillDrip } from "react-icons/fa";
-import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
-import { listSpec } from "../../../../../fields/Schema";
-import { scaleCreatorNumerical, yAxisCreator } from "../utils/D3Utils";
-import { undoBatch, undoable } from "../../../../util/UndoManager";
+import { ColorPicker, EditableText, IconButton, Size, Type } from 'browndash-components';
+import { FaFillDrip } from 'react-icons/fa';
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { listSpec } from '../../../../../fields/Schema';
+import { scaleCreatorNumerical, yAxisCreator } from '../utils/D3Utils';
+import { undoBatch, undoable } from '../../../../util/UndoManager';
 
 export interface HistogramProps {
     rootDoc: Doc;
@@ -35,7 +35,6 @@ export interface HistogramProps {
 
 @observer
 export class Histogram extends React.Component<HistogramProps> {
-
     private _disposers: { [key: string]: IReactionDisposer } = {};
     private _histogramRef: React.RefObject<HTMLDivElement> = React.createRef();
     private _histogramSvg: d3.Selection<SVGGElement, unknown, null, undefined> | undefined;
@@ -49,32 +48,37 @@ export class Histogram extends React.Component<HistogramProps> {
 
     // filters all data to just display selected data if brushed (created from an incoming link)
     @computed get _histogramData() {
-        var guids = StrListCast(this.props.layoutDoc.rowGuids);
+        var guids = StrListCast(this.props.layoutDoc.dataViz_rowGuids);
         if (this.props.axes.length < 1) return [];
         if (this.props.axes.length < 2) {
             var ax0 = this.props.axes[0];
-            if (/\d/.test(this.props.pairs[0][ax0])){ this.numericalXData = true }
+            if (/\d/.test(this.props.pairs[0][ax0])) {
+                this.numericalXData = true;
+            }
             return this.props.pairs
-                ?.filter(pair => (!this.incomingLinks.length ? true : this.incomingLinks[0]!.selected && StrListCast(this.incomingLinks[0].selected).includes(guids[this.props.pairs.indexOf(pair)])))
-                .map(pair => ({ [ax0]: (pair[this.props.axes[0]])}))
-        };
+                ?.filter(pair => (!this.incomingLinks.length ? true : this.incomingLinks[0]!.dataViz_selectedRows && StrListCast(this.incomingLinks[0].dataViz_selectedRows).includes(guids[this.props.pairs.indexOf(pair)])))
+                .map(pair => ({ [ax0]: pair[this.props.axes[0]] }));
+        }
         var ax0 = this.props.axes[0];
         var ax1 = this.props.axes[1];
-        if (/\d/.test(this.props.pairs[0][ax0])) { this.numericalXData = true;}
-        if (/\d/.test(this.props.pairs[0][ax1]) ) { this.numericalYData = true;}
+        if (/\d/.test(this.props.pairs[0][ax0])) {
+            this.numericalXData = true;
+        }
+        if (/\d/.test(this.props.pairs[0][ax1])) {
+            this.numericalYData = true;
+        }
         return this.props.pairs
-            ?.filter(pair => (!this.incomingLinks.length ? true : this.incomingLinks[0]!.selected && StrListCast(this.incomingLinks[0].selected).includes(guids[this.props.pairs.indexOf(pair)])))
-            .map(pair => ({ [ax0]: (pair[this.props.axes[0]]), [ax1]: (pair[this.props.axes[1]]) }))
+            ?.filter(pair => (!this.incomingLinks.length ? true : this.incomingLinks[0]!.dataViz_selectedRows && StrListCast(this.incomingLinks[0].dataViz_selectedRows).includes(guids[this.props.pairs.indexOf(pair)])))
+            .map(pair => ({ [ax0]: pair[this.props.axes[0]], [ax1]: pair[this.props.axes[1]] }));
     }
 
-    @computed get defaultGraphTitle(){
+    @computed get defaultGraphTitle() {
         var ax0 = this.props.axes[0];
-        var ax1 = (this.props.axes.length>1)? this.props.axes[1] : undefined;
-        if (this.props.axes.length<2 || !ax1 || !/\d/.test(this.props.pairs[0][ax1]) || !this.numericalYData){
-            return ax0 + " Histogram";
-        }
-        else return ax0 + " by " + ax1 + " Histogram";
-    }    
+        var ax1 = this.props.axes.length > 1 ? this.props.axes[1] : undefined;
+        if (this.props.axes.length < 2 || !ax1 || !/\d/.test(this.props.pairs[0][ax1]) || !this.numericalYData) {
+            return ax0 + ' Histogram';
+        } else return ax0 + ' by ' + ax1 + ' Histogram';
+    }
 
     @computed get incomingLinks() {
         return LinkManager.Instance.getAllRelatedLinks(this.props.rootDoc) // out of all links
@@ -83,11 +87,11 @@ export class Histogram extends React.Component<HistogramProps> {
     }
 
     @computed get rangeVals(): { xMin?: number; xMax?: number; yMin?: number; yMax?: number } {
-        if (this.numericalXData){
+        if (this.numericalXData) {
             const data = this.data(this._histogramData);
-            return {xMin: Math.min.apply(null, data), xMax: Math.max.apply(null, data), yMin:0, yMax:0}
+            return { xMin: Math.min.apply(null, data), xMax: Math.max.apply(null, data), yMin: 0, yMax: 0 };
         }
-        return {xMin:0, xMax:0, yMin:0, yMax:0}
+        return { xMin: 0, xMax: 0, yMin: 0, yMax: 0 };
     }
 
     componentWillUnmount() {
@@ -97,7 +101,7 @@ export class Histogram extends React.Component<HistogramProps> {
         this._disposers.chartData = reaction(
             () => ({ dataSet: this._histogramData, w: this.width, h: this.height }),
             ({ dataSet, w, h }) => {
-                if (dataSet!.length>0) {
+                if (dataSet!.length > 0) {
                     this.drawChart(dataSet, w, h);
                 }
             },
@@ -113,7 +117,7 @@ export class Histogram extends React.Component<HistogramProps> {
             //
             title: 'histogram doc selection' + this._currSelected,
         });
-        PresBox.pinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: pinProps?.pinData }, this.props.dataDoc);
+        PresBox.pinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: pinProps?.pinData }, this.props.rootDoc);
         return anchor;
     };
 
@@ -127,20 +131,22 @@ export class Histogram extends React.Component<HistogramProps> {
 
     // cleans data by converting numerical data to numbers and taking out empty cells
     data = (dataSet: any) => {
-        var validData = dataSet.filter((d: { [x: string]: unknown; }) => {
+        var validData = dataSet.filter((d: { [x: string]: unknown }) => {
             var valid = true;
             Object.keys(dataSet[0]).map(key => {
                 if (!d[key] || Number.isNaN(d[key])) valid = false;
-            })
+            });
             return valid;
-        })
-        var field = dataSet[0]? Object.keys(dataSet[0])[0] : undefined;
-        const data = validData.map((d: { [x: string]: any; }) => {
-            if (this.numericalXData) { return +d[field!].replace(/\$/g, '').replace(/\%/g, '').replace(/\</g, '') }
-            return d[field!]
-        })
+        });
+        var field = dataSet[0] ? Object.keys(dataSet[0])[0] : undefined;
+        const data = validData.map((d: { [x: string]: any }) => {
+            if (this.numericalXData) {
+                return +d[field!].replace(/\$/g, '').replace(/\%/g, '').replace(/\</g, '');
+            }
+            return d[field!];
+        });
         return data;
-    }
+    };
 
     // outlines the bar selected / hovered over
     highlightSelectedBar = (changeSelectedVariables: boolean, svg: any, eachRectWidth: any, pointerX: any, xAxisTitle: any, yAxisTitle: any, histDataSet: any) => {
@@ -148,35 +154,31 @@ export class Histogram extends React.Component<HistogramProps> {
         var barCounter = -1;
         const selected = svg.selectAll('.histogram-bar').filter((d: any) => {
             barCounter++; // uses the order of bars and width of each bar to find which one the pointer is over
-            if ((barCounter*eachRectWidth ) <= pointerX && pointerX <= ((barCounter+1)*eachRectWidth)){
-                var showSelected = this.numericalYData? this._histogramData.filter((data: { [x: string]: any; }) => StrCast(data[xAxisTitle]).replace(/\$/g, '').replace(/\%/g, '').replace(/\</g, '')==d[0])[0] 
-                : histDataSet.filter((data: { [x: string]: any; }) => data[xAxisTitle].replace(/\$/g, '').replace(/\%/g, '').replace(/\</g, '')==d[0])[0];
-                if (this.numericalXData){
+            if (barCounter * eachRectWidth <= pointerX && pointerX <= (barCounter + 1) * eachRectWidth) {
+                var showSelected = this.numericalYData
+                    ? this._histogramData.filter((data: { [x: string]: any }) => StrCast(data[xAxisTitle]).replace(/\$/g, '').replace(/\%/g, '').replace(/\</g, '') == d[0])[0]
+                    : histDataSet.filter((data: { [x: string]: any }) => data[xAxisTitle].replace(/\$/g, '').replace(/\%/g, '').replace(/\</g, '') == d[0])[0];
+                if (this.numericalXData) {
                     // calculating frequency
-                    if (d[0] && d[1] && d[0]!=d[1]){
-                        showSelected = {[xAxisTitle]: (d3.min(d) + " to " + d3.max(d)), frequency: d.length}
-                    }
-                    else if (!this.numericalYData) showSelected = {[xAxisTitle]: showSelected[xAxisTitle], frequency: d.length}
-                } 
-                if (changeSelectedVariables){
-                    // for when a bar is selected - not just hovered over
-                    sameAsCurrent = this._currSelected? 
-                        (showSelected[xAxisTitle]==this._currSelected![xAxisTitle] 
-                    && showSelected[yAxisTitle]==this._currSelected![yAxisTitle])
-                        : false;
-                    this._currSelected = sameAsCurrent? undefined: showSelected;
-                    this.selectedData = sameAsCurrent? undefined: d;
+                    if (d[0] && d[1] && d[0] != d[1]) {
+                        showSelected = { [xAxisTitle]: d3.min(d) + ' to ' + d3.max(d), frequency: d.length };
+                    } else if (!this.numericalYData) showSelected = { [xAxisTitle]: showSelected[xAxisTitle], frequency: d.length };
                 }
-                else this.hoverOverData = d;
-                return true
+                if (changeSelectedVariables) {
+                    // for when a bar is selected - not just hovered over
+                    sameAsCurrent = this._currSelected ? showSelected[xAxisTitle] == this._currSelected![xAxisTitle] && showSelected[yAxisTitle] == this._currSelected![yAxisTitle] : false;
+                    this._currSelected = sameAsCurrent ? undefined : showSelected;
+                    this.selectedData = sameAsCurrent ? undefined : d;
+                } else this.hoverOverData = d;
+                return true;
             }
             return false;
         });
-        if (changeSelectedVariables){
+        if (changeSelectedVariables) {
             if (sameAsCurrent!) this.curBarSelected = undefined;
             else this.curBarSelected = selected;
         }
-    }
+    };
 
     // draws the histogram
     drawChart = (dataSet: any, width: number, height: number) => {
@@ -184,306 +186,338 @@ export class Histogram extends React.Component<HistogramProps> {
         d3.select(this._histogramRef.current).select('.tooltip').remove();
 
         var data = this.data(dataSet);
-        var xAxisTitle = Object.keys(dataSet[0])[0]
+        var xAxisTitle = Object.keys(dataSet[0])[0];
         var yAxisTitle = this.numericalYData ? Object.keys(dataSet[0])[1] : 'frequency';
-        let uniqueArr: unknown[] = [...new Set(data)]
-        var numBins = (this.numericalXData && Number.isInteger(data[0]))? (this.rangeVals.xMax! - this.rangeVals.xMin! ) : uniqueArr.length
-        var translateXAxis = !this.numericalXData || numBins<this.maxBins ?  width/(numBins+1)/2 : 0;
-        if (numBins>this.maxBins) numBins = this.maxBins;
-        var startingPoint = this.numericalXData? this.rangeVals.xMin! : 0;
-        var endingPoint = this.numericalXData? this.rangeVals.xMax! : numBins;
+        let uniqueArr: unknown[] = [...new Set(data)];
+        var numBins = this.numericalXData && Number.isInteger(data[0]) ? this.rangeVals.xMax! - this.rangeVals.xMin! : uniqueArr.length;
+        var translateXAxis = !this.numericalXData || numBins < this.maxBins ? width / (numBins + 1) / 2 : 0;
+        if (numBins > this.maxBins) numBins = this.maxBins;
+        var startingPoint = this.numericalXData ? this.rangeVals.xMin! : 0;
+        var endingPoint = this.numericalXData ? this.rangeVals.xMax! : numBins;
 
         // converts data into Objects
-        var histDataSet = dataSet.filter((d: { [x: string]: unknown; }) => {
+        var histDataSet = dataSet.filter((d: { [x: string]: unknown }) => {
             var valid = true;
             Object.keys(dataSet[0]).map(key => {
                 if (!d[key] || Number.isNaN(d[key])) valid = false;
-            })
+            });
             return valid;
         });
         if (!this.numericalXData) {
-            var histStringDataSet: { [x: string]: unknown; }[] = [];
-            if (this.numericalYData){
-                for (let i=0; i<dataSet.length; i++){
-                    histStringDataSet.push({[yAxisTitle]: dataSet[i][yAxisTitle], [xAxisTitle]: dataSet[i][xAxisTitle]})
+            var histStringDataSet: { [x: string]: unknown }[] = [];
+            if (this.numericalYData) {
+                for (let i = 0; i < dataSet.length; i++) {
+                    histStringDataSet.push({ [yAxisTitle]: dataSet[i][yAxisTitle], [xAxisTitle]: dataSet[i][xAxisTitle] });
                 }
-            }
-            else{
-                for (let i=0; i<uniqueArr.length; i++){
-                    histStringDataSet.push({[yAxisTitle]: 0, [xAxisTitle]: uniqueArr[i]})
+            } else {
+                for (let i = 0; i < uniqueArr.length; i++) {
+                    histStringDataSet.push({ [yAxisTitle]: 0, [xAxisTitle]: uniqueArr[i] });
                 }
-                for (let i=0; i<data.length; i++){
-                    let barData = histStringDataSet.filter(each => each[xAxisTitle]==data[i])
-                    histStringDataSet.filter(each => each[xAxisTitle]==data[i])[0][yAxisTitle] = Number(barData[0][yAxisTitle]) + 1;
+                for (let i = 0; i < data.length; i++) {
+                    let barData = histStringDataSet.filter(each => each[xAxisTitle] == data[i]);
+                    histStringDataSet.filter(each => each[xAxisTitle] == data[i])[0][yAxisTitle] = Number(barData[0][yAxisTitle]) + 1;
                 }
             }
-            histDataSet = histStringDataSet
+            histDataSet = histStringDataSet;
         }
 
         // initial graph and binning data for histogram
         var svg = (this._histogramSvg = d3
             .select(this._histogramRef.current)
-            .append("svg")
-                .attr("class", "graph")
-                .attr("width", width + this.props.margin.right + this.props.margin.left)
-                .attr("height", height + this.props.margin.top + this.props.margin.bottom)
-            .append("g")
-                .attr("transform",
-                      "translate(" + this.props.margin.left + "," + this.props.margin.top + ")"));
-        var x = d3.scaleLinear()
-                .domain(this.numericalXData? [startingPoint!, endingPoint!] : [0, numBins])
-                .range([0, width ]);
-        var histogram = d3.histogram()
-            .value(function(d) {return d})
+            .append('svg')
+            .attr('class', 'graph')
+            .attr('width', width + this.props.margin.right + this.props.margin.left)
+            .attr('height', height + this.props.margin.top + this.props.margin.bottom)
+            .append('g')
+            .attr('transform', 'translate(' + this.props.margin.left + ',' + this.props.margin.top + ')'));
+        var x = d3
+            .scaleLinear()
+            .domain(this.numericalXData ? [startingPoint!, endingPoint!] : [0, numBins])
+            .range([0, width]);
+        var histogram = d3
+            .histogram()
+            .value(function (d) {
+                return d;
+            })
             .domain([startingPoint!, endingPoint!])
-            .thresholds(x.ticks(numBins))
-        var bins = histogram(data)
-        var eachRectWidth = width/(bins.length)
-        var graphStartingPoint = (bins[0].x1 && bins[1])? bins[0].x1! - (bins[1].x1! - bins[1].x0!) : 0;
+            .thresholds(x.ticks(numBins));
+        var bins = histogram(data);
+        var eachRectWidth = width / bins.length;
+        var graphStartingPoint = bins[0].x1 && bins[1] ? bins[0].x1! - (bins[1].x1! - bins[1].x0!) : 0;
         bins[0].x0 = graphStartingPoint;
-        x = x.domain([graphStartingPoint, endingPoint])
-             .range([0, Number.isInteger(this.rangeVals.xMin!)? (width-eachRectWidth) : width ])
+        x = x.domain([graphStartingPoint, endingPoint]).range([0, Number.isInteger(this.rangeVals.xMin!) ? width - eachRectWidth : width]);
         var xAxis;
 
         // more calculations based on bins
         // x-axis
-        if (!this.numericalXData) { // reorganize to match data if the data is strings rather than numbers
+        if (!this.numericalXData) {
+            // reorganize to match data if the data is strings rather than numbers
             // uniqueArr.sort()
-            histDataSet.sort()
-            for (let i=0; i<data.length; i++){
-                var index = 0
-                for (let j=0; j<uniqueArr.length; j++){
-                    if (uniqueArr[j] == data[i]){
+            histDataSet.sort();
+            for (let i = 0; i < data.length; i++) {
+                var index = 0;
+                for (let j = 0; j < uniqueArr.length; j++) {
+                    if (uniqueArr[j] == data[i]) {
                         index = j;
                     }
                 }
-                if (bins[index]) bins[index].push(data[i])
+                if (bins[index]) bins[index].push(data[i]);
             }
             bins.pop();
-            eachRectWidth = width/(bins.length)
-            bins.forEach(d => d.x0 = d.x0!)
-            xAxis = d3.axisBottom(x)
-                .ticks(bins.length>1? bins.length-1: 1)
-                .tickFormat( i => uniqueArr[i.valueOf()] as string)
-                .tickPadding(10)
-            x.range([0, width-eachRectWidth])
-            x.domain([0, bins.length-1])
+            eachRectWidth = width / bins.length;
+            bins.forEach(d => (d.x0 = d.x0!));
+            xAxis = d3
+                .axisBottom(x)
+                .ticks(bins.length > 1 ? bins.length - 1 : 1)
+                .tickFormat(i => uniqueArr[i.valueOf()] as string)
+                .tickPadding(10);
+            x.range([0, width - eachRectWidth]);
+            x.domain([0, bins.length - 1]);
             translateXAxis = eachRectWidth / 2;
-        }
-        else {
+        } else {
             var allSame = true;
-            for (var i=0; i<bins.length; i++){
-                if (bins[i] && bins[i][0]){
+            for (var i = 0; i < bins.length; i++) {
+                if (bins[i] && bins[i][0]) {
                     var compare = bins[i][0];
-                    for (let j=1; j<bins[i].length; j++){
+                    for (let j = 1; j < bins[i].length; j++) {
                         if (bins[i][j] != compare) allSame = false;
                     }
                 }
             }
-            if (allSame){ 
+            if (allSame) {
                 translateXAxis = eachRectWidth / 2;
-                eachRectWidth = width/(bins.length)
-            }
-            else {
-                eachRectWidth = width/(bins.length+1)
-                var tickDiff = (bins.length>=2? (bins[bins.length-2].x1!-bins[bins.length-2].x0!): 0)
+                eachRectWidth = width / bins.length;
+            } else {
+                eachRectWidth = width / (bins.length + 1);
+                var tickDiff = bins.length >= 2 ? bins[bins.length - 2].x1! - bins[bins.length - 2].x0! : 0;
                 var curDomain = x.domain();
-                x.domain([curDomain[0], curDomain[0] + tickDiff*bins.length])
+                x.domain([curDomain[0], curDomain[0] + tickDiff * bins.length]);
             }
 
-            xAxis = d3.axisBottom(x)
-                .ticks(bins.length-1)
-            x.range([0, width-eachRectWidth])
+            xAxis = d3.axisBottom(x).ticks(bins.length - 1);
+            x.range([0, width - eachRectWidth]);
         }
         // y-axis
-        const maxFrequency = this.numericalYData? d3.max(histDataSet, function(d: any) { 
-            return d[yAxisTitle]? Number(d[yAxisTitle]!.replace(/\$/g, '').replace(/\%/g, '').replace(/\</g, '')) : 0})
-                    : d3.max(bins, function(d) { return d.length; })
-        var y = d3.scaleLinear()
-            .range([height, 0]);
-            y.domain([0, +maxFrequency!]);
-        var yAxis = d3.axisLeft(y)
-            .ticks(maxFrequency!)
-        if (this.numericalYData){
+        const maxFrequency = this.numericalYData
+            ? d3.max(histDataSet, function (d: any) {
+                  return d[yAxisTitle] ? Number(d[yAxisTitle]!.replace(/\$/g, '').replace(/\%/g, '').replace(/\</g, '')) : 0;
+              })
+            : d3.max(bins, function (d) {
+                  return d.length;
+              });
+        var y = d3.scaleLinear().range([height, 0]);
+        y.domain([0, +maxFrequency!]);
+        var yAxis = d3.axisLeft(y).ticks(maxFrequency!);
+        if (this.numericalYData) {
             const yScale = scaleCreatorNumerical(0, Number(maxFrequency), height, 0);
             yAxisCreator(svg.append('g'), width, yScale);
+        } else {
+            svg.append('g').call(yAxis);
         }
-        else{
-            svg.append("g")
-            .call(yAxis);
-        }
-        svg.append("g")
-            .attr("transform", "translate(" + translateXAxis + ", " + height + ")")
-            .call(xAxis)
+        svg.append('g')
+            .attr('transform', 'translate(' + translateXAxis + ', ' + height + ')')
+            .call(xAxis);
 
         // click/hover
         const onPointClick = action((e: any) => this.highlightSelectedBar(true, svg, eachRectWidth, d3.pointer(e)[0], xAxisTitle, yAxisTitle, histDataSet));
         const onHover = action((e: any) => {
-            const selected = this.highlightSelectedBar(false, svg, eachRectWidth, d3.pointer(e)[0], xAxisTitle, yAxisTitle, histDataSet)
+            const selected = this.highlightSelectedBar(false, svg, eachRectWidth, d3.pointer(e)[0], xAxisTitle, yAxisTitle, histDataSet);
             updateHighlights();
-        })
+        });
         const mouseOut = action((e: any) => {
             this.hoverOverData = undefined;
             updateHighlights();
-        })
+        });
         const updateHighlights = () => {
             const hoverOverBar = this.hoverOverData;
             const selectedData = this.selectedData;
-            svg.selectAll('rect').attr("class", function(d: any) { return ((hoverOverBar && hoverOverBar[0]==d[0]) || selectedData && selectedData[0]==d[0])? 'histogram-bar hover' : 'histogram-bar'; })
-        }
-        svg.on('click', onPointClick)
-            .on('mouseover', onHover)
-            .on('mouseout', mouseOut)
+            svg.selectAll('rect').attr('class', function (d: any) {
+                return (hoverOverBar && hoverOverBar[0] == d[0]) || (selectedData && selectedData[0] == d[0]) ? 'histogram-bar hover' : 'histogram-bar';
+            });
+        };
+        svg.on('click', onPointClick).on('mouseover', onHover).on('mouseout', mouseOut);
 
         // axis titles
-        svg.append("text")
-            .attr("transform", "translate(" + (width/2) + " ," + (height+40) + ")")
-            .style("text-anchor", "middle")
+        svg.append('text')
+            .attr('transform', 'translate(' + width / 2 + ' ,' + (height + 40) + ')')
+            .style('text-anchor', 'middle')
             .text(xAxisTitle);
-        svg.append("text")
-            .attr("transform", "rotate(-90)" + " " + "translate( 0, " + -10 + ")")
-            .attr("x", -(height/2))
-            .attr("y", -20)
-            .style("text-anchor", "middle")
+        svg.append('text')
+            .attr('transform', 'rotate(-90)' + ' ' + 'translate( 0, ' + -10 + ')')
+            .attr('x', -(height / 2))
+            .attr('y', -20)
+            .style('text-anchor', 'middle')
             .text(yAxisTitle);
-        d3.format('.0f')
+        d3.format('.0f');
 
         // draw bars
         var selected = this.selectedData;
-        svg.selectAll("rect")
+        svg.selectAll('rect')
             .data(bins)
             .enter()
-            .append("rect")
-              .attr("transform", this.numericalYData?
-                    function (d) {
-                        var eachData = histDataSet.filter((data: { [x: string]: number; }) => {return data[xAxisTitle]==d[0]}) 
-                        var length = eachData.length? eachData[0][yAxisTitle].replace(/\$/g, '').replace(/\%/g, '').replace(/\</g, '') : 0;
-                        return "translate(" + x(d.x0!) + "," + y(length) + ")";
-                    }
-                    : function(d) { return "translate(" + x(d.x0!) + "," + y(d.length) + ")"; })
-              .attr("height", this.numericalYData? 
-                    function(d) {
-                        var eachData = histDataSet.filter((data: { [x: string]: number; }) => {return data[xAxisTitle]==d[0]}) 
-                        var length = eachData.length? eachData[0][yAxisTitle].replace(/\$/g, '').replace(/\%/g, '').replace(/\</g, '') : 0;
-                        return height-y(length)}
-                    : function(d) { 
-                        return height - y(d.length)})
-              .attr("width", eachRectWidth)
-              .attr("class", selected? 
-                    function(d) {
-                        return (selected && selected[0]==d[0])? 'histogram-bar hover' : 'histogram-bar';
-                    }: function(d) {return 'histogram-bar'})
-              .attr("fill", (d)=>{ 
+            .append('rect')
+            .attr(
+                'transform',
+                this.numericalYData
+                    ? function (d) {
+                          var eachData = histDataSet.filter((data: { [x: string]: number }) => {
+                              return data[xAxisTitle] == d[0];
+                          });
+                          var length = eachData.length ? eachData[0][yAxisTitle].replace(/\$/g, '').replace(/\%/g, '').replace(/\</g, '') : 0;
+                          return 'translate(' + x(d.x0!) + ',' + y(length) + ')';
+                      }
+                    : function (d) {
+                          return 'translate(' + x(d.x0!) + ',' + y(d.length) + ')';
+                      }
+            )
+            .attr(
+                'height',
+                this.numericalYData
+                    ? function (d) {
+                          var eachData = histDataSet.filter((data: { [x: string]: number }) => {
+                              return data[xAxisTitle] == d[0];
+                          });
+                          var length = eachData.length ? eachData[0][yAxisTitle].replace(/\$/g, '').replace(/\%/g, '').replace(/\</g, '') : 0;
+                          return height - y(length);
+                      }
+                    : function (d) {
+                          return height - y(d.length);
+                      }
+            )
+            .attr('width', eachRectWidth)
+            .attr(
+                'class',
+                selected
+                    ? function (d) {
+                          return selected && selected[0] == d[0] ? 'histogram-bar hover' : 'histogram-bar';
+                      }
+                    : function (d) {
+                          return 'histogram-bar';
+                      }
+            )
+            .attr('fill', d => {
                 var barColor;
                 var barColors = StrListCast(this.props.layoutDoc.histogramBarColors).map(each => each.split('::'));
-                barColors.map(each => { 
-                    if (d[0] && d[0].toString() && each[0]==d[0].toString()) barColor = each[1]; 
+                barColors.map(each => {
+                    if (d[0] && d[0].toString() && each[0] == d[0].toString()) barColor = each[1];
                     else {
-                        var range = StrCast(each[0]).split(" to ");
-                        if (Number(range[0])<=d[0] && d[0]<=Number(range[1])) barColor = each[1];
+                        var range = StrCast(each[0]).split(' to ');
+                        if (Number(range[0]) <= d[0] && d[0] <= Number(range[1])) barColor = each[1];
                     }
                 });
-                return barColor? StrCast(barColor) : StrCast(this.props.layoutDoc.defaultHistogramColor)})
+                return barColor ? StrCast(barColor) : StrCast(this.props.layoutDoc.defaultHistogramColor);
+            });
     };
 
     @action changeSelectedColor = (color: string) => {
-        this.curBarSelected.attr("fill", color);
-        var barName = StrCast(this._currSelected[this.props.axes[0]].replace(/\$/g, '').replace(/\%/g, '').replace(/\</g, ''))
+        this.curBarSelected.attr('fill', color);
+        var barName = StrCast(this._currSelected[this.props.axes[0]].replace(/\$/g, '').replace(/\%/g, '').replace(/\</g, ''));
 
-        const barColors = Cast(this.props.layoutDoc.histogramBarColors, listSpec("string"), null);
-        barColors.map(each => { if (each.split('::')[0] == barName) barColors.splice(barColors.indexOf(each), 1) });
+        const barColors = Cast(this.props.layoutDoc.histogramBarColors, listSpec('string'), null);
+        barColors.map(each => {
+            if (each.split('::')[0] == barName) barColors.splice(barColors.indexOf(each), 1);
+        });
         barColors.push(StrCast(barName + '::' + color));
     };
-    
-    @action eraseSelectedColor= () => {
-        this.curBarSelected.attr("fill", this.props.layoutDoc.defaultHistogramColor);
-        var barName = StrCast(this._currSelected[this.props.axes[0]].replace(/\$/g, '').replace(/\%/g, '').replace(/\</g, ''))
 
-        const barColors = Cast(this.props.layoutDoc.histogramBarColors, listSpec("string"), null);
-        barColors.map(each => { if (each.split('::')[0] == barName) barColors.splice(barColors.indexOf(each), 1) });
+    @action eraseSelectedColor = () => {
+        this.curBarSelected.attr('fill', this.props.layoutDoc.defaultHistogramColor);
+        var barName = StrCast(this._currSelected[this.props.axes[0]].replace(/\$/g, '').replace(/\%/g, '').replace(/\</g, ''));
+
+        const barColors = Cast(this.props.layoutDoc.histogramBarColors, listSpec('string'), null);
+        barColors.map(each => {
+            if (each.split('::')[0] == barName) barColors.splice(barColors.indexOf(each), 1);
+        });
     };
 
     render() {
-        this._histogramData
-        var curSelectedBarName;
-        var titleAccessor: any='';
-        if (this.props.axes.length==2) titleAccessor = 'histogram-title-'+this.props.axes[0]+'-'+this.props.axes[1];
-        else if (this.props.axes.length>0) titleAccessor = 'histogram-title-'+this.props.axes[0];
+        this._histogramData;
+        var curSelectedBarName = '';
+        var titleAccessor: any = '';
+        if (this.props.axes.length == 2) titleAccessor = 'dataViz_title_histogram_' + this.props.axes[0] + '-' + this.props.axes[1];
+        else if (this.props.axes.length > 0) titleAccessor = 'dataViz_title_histogram_' + this.props.axes[0];
         if (!this.props.layoutDoc[titleAccessor]) this.props.layoutDoc[titleAccessor] = this.defaultGraphTitle;
         if (!this.props.layoutDoc.defaultHistogramColor) this.props.layoutDoc.defaultHistogramColor = '#69b3a2';
         if (!this.props.layoutDoc.histogramBarColors) this.props.layoutDoc.histogramBarColors = new List<string>();
         var selected: string;
-        if (this._currSelected){
-            curSelectedBarName = StrCast(this._currSelected![this.props.axes[0]].replace(/\$/g, '').replace(/\%/g, '').replace(/\</g, ''))
+        if (this._currSelected) {
+            curSelectedBarName = StrCast(this._currSelected![this.props.axes[0]].replace(/\$/g, '').replace(/\%/g, '').replace(/\</g, ''));
             selected = '{ ';
             Object.keys(this._currSelected).map(key => {
-                key!=''? selected += key + ': ' + this._currSelected[key] + ', ': '';
-            })
-            selected = selected.substring(0, selected.length-2);
+                key != '' ? (selected += key + ': ' + this._currSelected[key] + ', ') : '';
+            });
+            selected = selected.substring(0, selected.length - 2);
             selected += ' }';
-        }
-        else selected = 'none';
+        } else selected = 'none';
         var selectedBarColor;
         var barColors = StrListCast(this.props.layoutDoc.histogramBarColors).map(each => each.split('::'));
-        barColors.map(each => {if (each[0]==curSelectedBarName!) selectedBarColor = each[1]});
+        barColors.map(each => {
+            if (each[0] == curSelectedBarName!) selectedBarColor = each[1];
+        });
 
         this.componentDidMount();
 
-        if (this._histogramData.length>0){
-            return (
-                this.props.axes.length >= 1 ? (
-                <div className="chart-container" >
-                    <div className="graph-title"> 
+        if (this._histogramData.length > 0) {
+            return this.props.axes.length >= 1 ? (
+                <div className="chart-container">
+                    <div className="graph-title">
                         <EditableText
                             val={StrCast(this.props.layoutDoc[titleAccessor])}
-                            setVal={undoable (action(val => this.props.layoutDoc[titleAccessor] = val as string), "Change Graph Title")}
-                            color={"black"}
+                            setVal={undoable(
+                                action(val => (this.props.layoutDoc[titleAccessor] = val as string)),
+                                'Change Graph Title'
+                            )}
+                            color={'black'}
                             size={Size.LARGE}
                             fillWidth
                         />
-                        &nbsp; &nbsp; 
+                        &nbsp; &nbsp;
                         <ColorPicker
-                            tooltip={'Change Default Bar Color'} 
-                            type={Type.SEC} 
-                            icon={<FaFillDrip/>}
+                            tooltip={'Change Default Bar Color'}
+                            type={Type.SEC}
+                            icon={<FaFillDrip />}
                             selectedColor={StrCast(this.props.layoutDoc.defaultHistogramColor)}
-                            setSelectedColor={undoable (color => this.props.layoutDoc.defaultHistogramColor = color, "Change Default Bar Color")}
+                            setFinalColor={undoable(color => (this.props.layoutDoc.defaultHistogramColor = color), 'Change Default Bar Color')}
+                            setSelectedColor={undoable(color => (this.props.layoutDoc.defaultHistogramColor = color), 'Change Default Bar Color')}
                             size={Size.XSMALL}
                         />
                     </div>
                     <div ref={this._histogramRef} />
-                    {selected != 'none' ? 
+                    {selected != 'none' ? (
                         <div className={'selected-data'}>
                             Selected: {selected}
                             &nbsp; &nbsp;
                             <ColorPicker
-                                tooltip={'Change Bar Color'} 
-                                type={Type.SEC} 
-                                icon={<FaFillDrip/>}
-                                selectedColor={selectedBarColor? selectedBarColor : this.curBarSelected.attr("fill")}
-                                setSelectedColor={undoable (color => this.changeSelectedColor(color), "Change Selected Bar Color")}
+                                tooltip={'Change Bar Color'}
+                                type={Type.SEC}
+                                icon={<FaFillDrip />}
+                                selectedColor={selectedBarColor ? selectedBarColor : this.curBarSelected.attr('fill')}
+                                setFinalColor={undoable(color => this.changeSelectedColor(color), 'Change Selected Bar Color')}
+                                setSelectedColor={undoable(color => this.changeSelectedColor(color), 'Change Selected Bar Color')}
                                 size={Size.XSMALL}
                             />
                             &nbsp;
                             <IconButton
-                                icon={<FontAwesomeIcon icon={'eraser'} />} 
-                                size={Size.XSMALL} 
-                                color={'black'} 
+                                icon={<FontAwesomeIcon icon={'eraser'} />}
+                                size={Size.XSMALL}
+                                color={'black'}
                                 type={Type.SEC}
                                 tooltip={'Revert to the default bar color'}
-                                onClick={undoable (action(() => this.eraseSelectedColor()), "Change Selected Bar Color")}
+                                onClick={undoable(
+                                    action(() => this.eraseSelectedColor()),
+                                    'Change Selected Bar Color'
+                                )}
                             />
                         </div>
-                    : null}
+                    ) : null}
                 </div>
-                ) : <span className="chart-container"> {'first use table view to select a column to graph'}</span>
+            ) : (
+                <span className="chart-container"> {'first use table view to select a column to graph'}</span>
+            );
+        } else
+            return (
+                // when it is a brushed table and the incoming table doesn't have any rows selected
+                <div className="chart-container">Selected rows of data from the incoming DataVizBox to display.</div>
             );
-        }
-        else return (
-            // when it is a brushed table and the incoming table doesn't have any rows selected
-            <div className='chart-container'>
-                Selected rows of data from the incoming DataVizBox to display.
-            </div>
-        )
     }
-}
\ No newline at end of file
+}
diff --git a/src/client/views/nodes/DataVizBox/components/LineChart.tsx b/src/client/views/nodes/DataVizBox/components/LineChart.tsx
index 8bace941f..8e549adbe 100644
--- a/src/client/views/nodes/DataVizBox/components/LineChart.tsx
+++ b/src/client/views/nodes/DataVizBox/components/LineChart.tsx
@@ -50,20 +50,21 @@ export class LineChart extends React.Component<LineChartProps> {
     // TODO: nda - some sort of mapping that keeps track of the annotated points so we can easily remove when annotations list updates
 
     @computed get _lineChartData() {
-        var guids = StrListCast(this.props.layoutDoc.rowGuids);
+        var guids = StrListCast(this.props.layoutDoc.dataViz_rowGuids);
         if (this.props.axes.length <= 1) return [];
         return this.props.pairs
-            ?.filter(pair => (!this.incomingLinks.length ? true : this.incomingLinks[0]!.selected && StrListCast(this.incomingLinks[0].selected).includes(guids[this.props.pairs.indexOf(pair)])))
+            ?.filter(pair => (!this.incomingLinks.length ? true : this.incomingLinks[0]!.dataViz_selectedRows && StrListCast(this.incomingLinks[0].dataViz_selectedRows).includes(guids[this.props.pairs.indexOf(pair)])))
             .map(pair => ({ x: Number(pair[this.props.axes[0]]), y: Number(pair[this.props.axes[1]]) }))
             .sort((a, b) => (a.x < b.x ? -1 : 1));
     }
-    @computed get graphTitle(){
-        return this.props.axes[1] + " vs. " + this.props.axes[0] + " Line Chart";
-    }  
+    @computed get graphTitle() {
+        return this.props.axes[1] + ' vs. ' + this.props.axes[0] + ' Line Chart';
+    }
     @computed get incomingLinks() {
         return LinkManager.Instance.getAllRelatedLinks(this.props.rootDoc) // out of all links
             .filter(link => {
-                return link.link_anchor_1 == this.props.rootDoc.draggedFrom}) // get links where this chart doc is the target of the link
+                return link.link_anchor_1 == this.props.rootDoc.draggedFrom;
+            }) // get links where this chart doc is the target of the link
             .map(link => DocCast(link.link_anchor_1)); // then return the source of the link
     }
     @computed get incomingSelected() {
@@ -158,7 +159,7 @@ export class LineChart extends React.Component<LineChartProps> {
 
     @action
     restoreView = (data: Doc) => {
-        const coords = Cast(data.presDataVizSelection, listSpec('number'), null);
+        const coords = Cast(data.config_dataVizSelection, listSpec('number'), null);
         if (coords?.length > 1 && (this._currSelected?.x !== coords[0] || this._currSelected?.y !== coords[1])) {
             this.setCurrSelected(coords[0], coords[1]);
             return true;
@@ -176,8 +177,8 @@ export class LineChart extends React.Component<LineChartProps> {
             //
             title: 'line doc selection' + this._currSelected?.x,
         });
-        PresBox.pinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: pinProps?.pinData }, this.props.dataDoc);
-        anchor.presDataVizSelection = this._currSelected ? new List<number>([this._currSelected.x, this._currSelected.y]) : undefined;
+        PresBox.pinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: pinProps?.pinData }, this.props.rootDoc);
+        anchor.config_dataVizSelection = this._currSelected ? new List<number>([this._currSelected.x, this._currSelected.y]) : undefined;
         return anchor;
     };
 
@@ -189,14 +190,13 @@ export class LineChart extends React.Component<LineChartProps> {
         return this.props.width - this.props.margin.left - this.props.margin.right;
     }
 
-    @computed get defaultGraphTitle(){
+    @computed get defaultGraphTitle() {
         var ax0 = this.props.axes[0];
-        var ax1 = (this.props.axes.length>1)? this.props.axes[1] : undefined;
-        if (this.props.axes.length<2 || !/\d/.test(this.props.pairs[0][ax0]) || !ax1){
-            return ax0 + " Line Chart";
-        }
-        else return ax1 + " by " + ax0 + " Line Chart";
-    } 
+        var ax1 = this.props.axes.length > 1 ? this.props.axes[1] : undefined;
+        if (this.props.axes.length < 2 || !/\d/.test(this.props.pairs[0][ax0]) || !ax1) {
+            return ax0 + ' Line Chart';
+        } else return ax1 + ' by ' + ax0 + ' Line Chart';
+    }
 
     setupTooltip() {
         return d3
@@ -215,7 +215,7 @@ export class LineChart extends React.Component<LineChartProps> {
     @action
     setCurrSelected(x?: number, y?: number) {
         // TODO: nda - get rid of svg element in the list?
-        if (this._currSelected && this._currSelected.x==x && this._currSelected.y==y) this._currSelected = undefined;
+        if (this._currSelected && this._currSelected.x == x && this._currSelected.y == y) this._currSelected = undefined;
         else this._currSelected = x !== undefined && y !== undefined ? { x, y } : undefined;
         this.props.pairs.forEach(pair => pair[this.props.axes[0]] === x && pair[this.props.axes[1]] === y && (pair.selected = true));
     }
@@ -256,7 +256,7 @@ export class LineChart extends React.Component<LineChartProps> {
         const svg = (this._lineChartSvg = d3
             .select(this._lineChartRef.current)
             .append('svg')
-            .attr("class", "graph")
+            .attr('class', 'graph')
             .attr('width', `${width + margin.left + margin.right}`)
             .attr('height', `${height + margin.top + margin.bottom}`)
             .append('g')
@@ -271,13 +271,13 @@ export class LineChart extends React.Component<LineChartProps> {
         // get valid data points
         const data = dataSet[0];
         const lineGen = createLineGenerator(xScale, yScale);
-        var validData = data.filter((d => {
+        var validData = data.filter(d => {
             var valid = true;
             Object.keys(data[0]).map(key => {
                 if (!d[key] || Number.isNaN(d[key])) valid = false;
-            })
+            });
             return valid;
-        }))
+        });
         // draw the plot line
         drawLine(svg.append('path'), validData, lineGen);
         // draw the datapoint circle
@@ -321,17 +321,17 @@ export class LineChart extends React.Component<LineChartProps> {
             .on('click', onPointClick);
 
         // axis titles
-        svg.append("text")
-            .attr("transform", "translate(" + (width/2) + " ," + (height+40) + ")")
-            .style("text-anchor", "middle")
+        svg.append('text')
+            .attr('transform', 'translate(' + width / 2 + ' ,' + (height + 40) + ')')
+            .style('text-anchor', 'middle')
             .text(this.props.axes[0]);
-        svg.append("text")
-            .attr("transform", "rotate(-90)" + " " + "translate( 0, " + -10 + ")")
-            .attr("x", -(height/2))
-            .attr("y", -20)
-            .attr("height", 20)
-            .attr("width", 20)
-            .style("text-anchor", "middle")
+        svg.append('text')
+            .attr('transform', 'rotate(-90)' + ' ' + 'translate( 0, ' + -10 + ')')
+            .attr('x', -(height / 2))
+            .attr('y', -20)
+            .attr('height', 20)
+            .attr('width', 20)
+            .style('text-anchor', 'middle')
             .text(this.props.axes[1]);
     };
 
@@ -348,42 +348,41 @@ export class LineChart extends React.Component<LineChartProps> {
         tooltip
             .html(() => `<b>(${d0.x},${d0.y})</b>`) // text content for tooltip
             .style('pointer-events', 'none')
-            .style('transform', `translate(${xScale(d0.x)-this.width}px,${yScale(d0.y)}px)`);
+            .style('transform', `translate(${xScale(d0.x) - this.width}px,${yScale(d0.y)}px)`);
     }
 
     render() {
         this.componentDidMount();
-        var titleAccessor:any = '';
-        if (this.props.axes.length==2) titleAccessor = 'lineChart-title-'+this.props.axes[0]+'-'+this.props.axes[1];
-        else if (this.props.axes.length>0) titleAccessor = 'lineChart-title-'+this.props.axes[0];
+        var titleAccessor: any = '';
+        if (this.props.axes.length == 2) titleAccessor = 'dataViz_title_lineChart_' + this.props.axes[0] + '-' + this.props.axes[1];
+        else if (this.props.axes.length > 0) titleAccessor = 'dataViz_title_lineChart_' + this.props.axes[0];
         if (!this.props.layoutDoc[titleAccessor]) this.props.layoutDoc[titleAccessor] = this.defaultGraphTitle;
         const selectedPt = this._currSelected ? `{ ${this.props.axes[0]}: ${this._currSelected.x} ${this.props.axes[1]}: ${this._currSelected.y} }` : 'none';
-        if (this._lineChartData.length>0){
-            return (
-                this.props.axes.length>=2 && /\d/.test(this.props.pairs[0][this.props.axes[0]]) && /\d/.test(this.props.pairs[0][this.props.axes[1]]) ? (
-                <div className="chart-container" >
-                    <div className="graph-title"> 
+        if (this._lineChartData.length > 0) {
+            return this.props.axes.length >= 2 && /\d/.test(this.props.pairs[0][this.props.axes[0]]) && /\d/.test(this.props.pairs[0][this.props.axes[1]]) ? (
+                <div className="chart-container">
+                    <div className="graph-title">
                         <EditableText
                             val={StrCast(this.props.layoutDoc[titleAccessor])}
-                            setVal={undoable (action(val => this.props.layoutDoc[titleAccessor] = val as string), "Change Graph Title")}
-                            color={"black"}
+                            setVal={undoable(
+                                action(val => (this.props.layoutDoc[titleAccessor] = val as string)),
+                                'Change Graph Title'
+                            )}
+                            color={'black'}
                             size={Size.LARGE}
                             fillWidth
                         />
                     </div>
                     <div ref={this._lineChartRef} />
-                    {selectedPt!='none'? 
-                        <div className={'selected-data'}> {`Selected: ${selectedPt}`}</div>
-                    : null}
+                    {selectedPt != 'none' ? <div className={'selected-data'}> {`Selected: ${selectedPt}`}</div> : null}
                 </div>
-                ) : <span className="chart-container"> {'first use table view to select two numerical axes to plot'}</span>
+            ) : (
+                <span className="chart-container"> {'first use table view to select two numerical axes to plot'}</span>
+            );
+        } else
+            return (
+                // when it is a brushed table and the incoming table doesn't have any rows selected
+                <div className="chart-container">Selected rows of data from the incoming DataVizBox to display.</div>
             );
-        }
-        else return (
-            // when it is a brushed table and the incoming table doesn't have any rows selected
-            <div className='chart-container'>
-                Selected rows of data from the incoming DataVizBox to display.
-            </div>
-        )
     }
 }
diff --git a/src/client/views/nodes/DataVizBox/components/PieChart.tsx b/src/client/views/nodes/DataVizBox/components/PieChart.tsx
index 0c54d0a4e..fe77293f0 100644
--- a/src/client/views/nodes/DataVizBox/components/PieChart.tsx
+++ b/src/client/views/nodes/DataVizBox/components/PieChart.tsx
@@ -1,18 +1,18 @@
-import { observer } from "mobx-react";
-import { Doc, StrListCast } from "../../../../../fields/Doc";
+import { observer } from 'mobx-react';
+import { Doc, StrListCast } from '../../../../../fields/Doc';
 import * as React from 'react';
 import * as d3 from 'd3';
-import { IReactionDisposer, action, computed, observable, reaction } from "mobx";
-import { LinkManager } from "../../../../util/LinkManager";
-import { Cast, DocCast, StrCast} from "../../../../../fields/Types";
-import { PinProps, PresBox } from "../../trails";
-import { Docs } from "../../../../documents/Documents";
-import { List } from "../../../../../fields/List";
+import { IReactionDisposer, action, computed, observable, reaction } from 'mobx';
+import { LinkManager } from '../../../../util/LinkManager';
+import { Cast, DocCast, StrCast } from '../../../../../fields/Types';
+import { PinProps, PresBox } from '../../trails';
+import { Docs } from '../../../../documents/Documents';
+import { List } from '../../../../../fields/List';
 import './Chart.scss';
-import { ColorPicker, EditableText, Size, Type } from "browndash-components";
-import { FaFillDrip } from "react-icons/fa";
-import { listSpec } from "../../../../../fields/Schema";
-import { undoable } from "../../../../util/UndoManager";
+import { ColorPicker, EditableText, Size, Type } from 'browndash-components';
+import { FaFillDrip } from 'react-icons/fa';
+import { listSpec } from '../../../../../fields/Schema';
+import { undoable } from '../../../../util/UndoManager';
 
 export interface PieChartProps {
     rootDoc: Doc;
@@ -33,7 +33,6 @@ export interface PieChartProps {
 
 @observer
 export class PieChart extends React.Component<PieChartProps> {
-
     private _disposers: { [key: string]: IReactionDisposer } = {};
     private _piechartRef: React.RefObject<HTMLDivElement> = React.createRef();
     private _piechartSvg: d3.Selection<SVGGElement, unknown, null, undefined> | undefined;
@@ -45,31 +44,34 @@ export class PieChart extends React.Component<PieChartProps> {
 
     // filters all data to just display selected data if brushed (created from an incoming link)
     @computed get _piechartData() {
-        var guids = StrListCast(this.props.layoutDoc.rowGuids);
+        var guids = StrListCast(this.props.layoutDoc.dataViz_rowGuids);
         if (this.props.axes.length < 1) return [];
         if (this.props.axes.length < 2) {
             var ax0 = this.props.axes[0];
-            if (/\d/.test(this.props.pairs[0][ax0])){ this.byCategory = false }
+            if (/\d/.test(this.props.pairs[0][ax0])) {
+                this.byCategory = false;
+            }
             return this.props.pairs
-                ?.filter(pair => (!this.incomingLinks.length ? true :  this.incomingLinks[0]!.selected && StrListCast(this.incomingLinks[0].selected).includes(guids[this.props.pairs.indexOf(pair)])))
-                .map(pair => ({ [ax0]: (pair[this.props.axes[0]])}))
-        };
+                ?.filter(pair => (!this.incomingLinks.length ? true : this.incomingLinks[0]!.dataViz_selectedRows && StrListCast(this.incomingLinks[0].dataViz_selectedRows).includes(guids[this.props.pairs.indexOf(pair)])))
+                .map(pair => ({ [ax0]: pair[this.props.axes[0]] }));
+        }
         var ax0 = this.props.axes[0];
         var ax1 = this.props.axes[1];
-        if (/\d/.test(this.props.pairs[0][ax0])) { this.byCategory = false; }
+        if (/\d/.test(this.props.pairs[0][ax0])) {
+            this.byCategory = false;
+        }
         return this.props.pairs
-            ?.filter(pair => (!this.incomingLinks.length ? true :  this.incomingLinks[0]!.selected && StrListCast(this.incomingLinks[0].selected).includes(guids[this.props.pairs.indexOf(pair)])))
-            .map(pair => ({ [ax0]: (pair[this.props.axes[0]]), [ax1]: (pair[this.props.axes[1]]) }))
+            ?.filter(pair => (!this.incomingLinks.length ? true : this.incomingLinks[0]!.dataViz_selectedRows && StrListCast(this.incomingLinks[0].dataViz_selectedRows).includes(guids[this.props.pairs.indexOf(pair)])))
+            .map(pair => ({ [ax0]: pair[this.props.axes[0]], [ax1]: pair[this.props.axes[1]] }));
     }
 
-    @computed get defaultGraphTitle(){
+    @computed get defaultGraphTitle() {
         var ax0 = this.props.axes[0];
-        var ax1 = (this.props.axes.length>1)? this.props.axes[1] : undefined;
-        if (this.props.axes.length<2 || !/\d/.test(this.props.pairs[0][ax0]) || !ax1){
-            return ax0 + " Pie Chart";
-        }
-        else return ax1 + " by " + ax0 + " Pie Chart";
-    }    
+        var ax1 = this.props.axes.length > 1 ? this.props.axes[1] : undefined;
+        if (this.props.axes.length < 2 || !/\d/.test(this.props.pairs[0][ax0]) || !ax1) {
+            return ax0 + ' Pie Chart';
+        } else return ax1 + ' by ' + ax0 + ' Pie Chart';
+    }
 
     @computed get incomingLinks() {
         return LinkManager.Instance.getAllRelatedLinks(this.props.rootDoc) // out of all links
@@ -84,7 +86,7 @@ export class PieChart extends React.Component<PieChartProps> {
         this._disposers.chartData = reaction(
             () => ({ dataSet: this._piechartData, w: this.width, h: this.height }),
             ({ dataSet, w, h }) => {
-                if (dataSet!.length>0) {
+                if (dataSet!.length > 0) {
                     this.drawChart(dataSet, w, h);
                 }
             },
@@ -100,7 +102,7 @@ export class PieChart extends React.Component<PieChartProps> {
             //
             title: 'piechart doc selection' + this._currSelected,
         });
-        PresBox.pinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: pinProps?.pinData }, this.props.dataDoc);
+        PresBox.pinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: pinProps?.pinData }, this.props.rootDoc);
         return anchor;
     };
 
@@ -114,167 +116,177 @@ export class PieChart extends React.Component<PieChartProps> {
 
     // cleans data by converting numerical data to numbers and taking out empty cells
     data = (dataSet: any) => {
-        var validData = dataSet.filter((d: { [x: string]: unknown; }) => {
+        var validData = dataSet.filter((d: { [x: string]: unknown }) => {
             var valid = true;
             Object.keys(dataSet[0]).map(key => {
                 if (!d[key] || Number.isNaN(d[key])) valid = false;
-            })
+            });
             return valid;
-        })
-        var field = dataSet[0]? Object.keys(dataSet[0])[0] : undefined;
-        const data = validData.map((d: { [x: string]: any; }) => {
-            if (!this.byCategory) { return +d[field!].replace(/\$/g, '').replace(/\%/g, '').replace(/\</g, '') }
-            return d[field!]
-        })
+        });
+        var field = dataSet[0] ? Object.keys(dataSet[0])[0] : undefined;
+        const data = validData.map((d: { [x: string]: any }) => {
+            if (!this.byCategory) {
+                return +d[field!].replace(/\$/g, '').replace(/\%/g, '').replace(/\</g, '');
+            }
+            return d[field!];
+        });
         return data;
-    }
+    };
 
     // outlines the slice selected / hovered over
     highlightSelectedSlice = (changeSelectedVariables: boolean, svg: any, arc: any, radius: any, pointer: any, pieDataSet: any) => {
-            var index = -1;
-            var sameAsCurrent: boolean;
-            const selected = svg.selectAll('.slice').filter((d: any) => {
-                index++;
-                var p1 = [0,0]; // center of pie
-                var p3 = [arc.centroid(d)[0]*2, arc.centroid(d)[1]*2]; // outward peak of arc
-                var p2 = [radius*Math.sin(d.startAngle), -radius*Math.cos(d.startAngle)]; // start of arc
-                var p4 = [radius*Math.sin(d.endAngle), -radius*Math.cos(d.endAngle)]; // end of arc
+        var index = -1;
+        var sameAsCurrent: boolean;
+        const selected = svg.selectAll('.slice').filter((d: any) => {
+            index++;
+            var p1 = [0, 0]; // center of pie
+            var p3 = [arc.centroid(d)[0] * 2, arc.centroid(d)[1] * 2]; // outward peak of arc
+            var p2 = [radius * Math.sin(d.startAngle), -radius * Math.cos(d.startAngle)]; // start of arc
+            var p4 = [radius * Math.sin(d.endAngle), -radius * Math.cos(d.endAngle)]; // end of arc
 
-                // draw an imaginary horizontal line from the pointer to see how many times it crosses a slice edge
-                var lineCrossCount = 0;
-                // if for all 4 lines
-                if (Math.min(p1[1], p2[1])<=pointer[1] && pointer[1]<=Math.max(p1[1], p2[1])){ // within y bounds
-                    if (pointer[0] <= (pointer[1]-p1[1])*(p2[0]-p1[0])/(p2[1]-p1[1])+p1[0]) lineCrossCount++; } // intercepts x
-                if (Math.min(p2[1], p3[1])<=pointer[1] && pointer[1]<=Math.max(p2[1], p3[1])){
-                    if (pointer[0] <= (pointer[1]-p2[1])*(p3[0]-p2[0])/(p3[1]-p2[1])+p2[0]) lineCrossCount++; }
-                if (Math.min(p3[1], p4[1])<=pointer[1] && pointer[1]<=Math.max(p3[1], p4[1])){
-                    if (pointer[0] <= (pointer[1]-p3[1])*(p4[0]-p3[0])/(p4[1]-p3[1])+p3[0]) lineCrossCount++; }
-                if (Math.min(p4[1], p1[1])<=pointer[1] && pointer[1]<=Math.max(p4[1], p1[1])){
-                    if (pointer[0] <= (pointer[1]-p4[1])*(p1[0]-p4[0])/(p1[1]-p4[1])+p4[0]) lineCrossCount++; }
-                if (lineCrossCount % 2 != 0) { // inside the slice of it crosses an odd number of edges
-                    var showSelected = this.byCategory? pieDataSet[index] : this._piechartData[index];
-                    if (changeSelectedVariables){
-                        // for when a bar is selected - not just hovered over
-                        sameAsCurrent = (this._currSelected)? 
-                            (showSelected[Object.keys(showSelected)[0]]==this._currSelected![Object.keys(showSelected)[0]] 
-                        && showSelected[Object.keys(showSelected)[1]]==this._currSelected![Object.keys(showSelected)[1]])
-                            : 
-                            this._currSelected===showSelected;
-                        this._currSelected = sameAsCurrent? undefined: showSelected;
-                        this.selectedData = sameAsCurrent? undefined: d;
-                    }
-                    else this.hoverOverData = d;
-                    return true;
-                }
-                return false;
-            });
-            if (changeSelectedVariables){
-                if (sameAsCurrent!) this.curSliceSelected = undefined;
-                else  this.curSliceSelected = selected;
+            // draw an imaginary horizontal line from the pointer to see how many times it crosses a slice edge
+            var lineCrossCount = 0;
+            // if for all 4 lines
+            if (Math.min(p1[1], p2[1]) <= pointer[1] && pointer[1] <= Math.max(p1[1], p2[1])) {
+                // within y bounds
+                if (pointer[0] <= ((pointer[1] - p1[1]) * (p2[0] - p1[0])) / (p2[1] - p1[1]) + p1[0]) lineCrossCount++;
+            } // intercepts x
+            if (Math.min(p2[1], p3[1]) <= pointer[1] && pointer[1] <= Math.max(p2[1], p3[1])) {
+                if (pointer[0] <= ((pointer[1] - p2[1]) * (p3[0] - p2[0])) / (p3[1] - p2[1]) + p2[0]) lineCrossCount++;
             }
-    }
+            if (Math.min(p3[1], p4[1]) <= pointer[1] && pointer[1] <= Math.max(p3[1], p4[1])) {
+                if (pointer[0] <= ((pointer[1] - p3[1]) * (p4[0] - p3[0])) / (p4[1] - p3[1]) + p3[0]) lineCrossCount++;
+            }
+            if (Math.min(p4[1], p1[1]) <= pointer[1] && pointer[1] <= Math.max(p4[1], p1[1])) {
+                if (pointer[0] <= ((pointer[1] - p4[1]) * (p1[0] - p4[0])) / (p1[1] - p4[1]) + p4[0]) lineCrossCount++;
+            }
+            if (lineCrossCount % 2 != 0) {
+                // inside the slice of it crosses an odd number of edges
+                var showSelected = this.byCategory ? pieDataSet[index] : this._piechartData[index];
+                if (changeSelectedVariables) {
+                    // for when a bar is selected - not just hovered over
+                    sameAsCurrent = this._currSelected
+                        ? showSelected[Object.keys(showSelected)[0]] == this._currSelected![Object.keys(showSelected)[0]] && showSelected[Object.keys(showSelected)[1]] == this._currSelected![Object.keys(showSelected)[1]]
+                        : this._currSelected === showSelected;
+                    this._currSelected = sameAsCurrent ? undefined : showSelected;
+                    this.selectedData = sameAsCurrent ? undefined : d;
+                } else this.hoverOverData = d;
+                return true;
+            }
+            return false;
+        });
+        if (changeSelectedVariables) {
+            if (sameAsCurrent!) this.curSliceSelected = undefined;
+            else this.curSliceSelected = selected;
+        }
+    };
 
     // draws the pie chart
     drawChart = (dataSet: any, width: number, height: number) => {
         d3.select(this._piechartRef.current).select('svg').remove();
         d3.select(this._piechartRef.current).select('.tooltip').remove();
-        
-        var percentField = Object.keys(dataSet[0])[0]
-        var descriptionField = Object.keys(dataSet[0])[1]!
-        var radius = Math.min(width, height-this.props.margin.top-this.props.margin.bottom) /2
+
+        var percentField = Object.keys(dataSet[0])[0];
+        var descriptionField = Object.keys(dataSet[0])[1]!;
+        var radius = Math.min(width, height - this.props.margin.top - this.props.margin.bottom) / 2;
 
         // converts data into Objects
         var data = this.data(dataSet);
-        var pieDataSet = dataSet.filter((d: { [x: string]: unknown; }) => {
+        var pieDataSet = dataSet.filter((d: { [x: string]: unknown }) => {
             var valid = true;
             Object.keys(dataSet[0]).map(key => {
                 if (!d[key] || Number.isNaN(d[key])) valid = false;
-            })
+            });
             return valid;
         });
-        if (this.byCategory){
-            let uniqueCategories = [...new Set(data)]
+        if (this.byCategory) {
+            let uniqueCategories = [...new Set(data)];
             var pieStringDataSet: { frequency: number }[] = [];
-            for (let i=0; i<uniqueCategories.length; i++){
-                pieStringDataSet.push({frequency: 0, [percentField]: uniqueCategories[i]})
+            for (let i = 0; i < uniqueCategories.length; i++) {
+                pieStringDataSet.push({ frequency: 0, [percentField]: uniqueCategories[i] });
             }
-            for (let i=0; i<data.length; i++){
-                let sliceData = pieStringDataSet.filter((each: any) => each[percentField]==data[i])
+            for (let i = 0; i < data.length; i++) {
+                let sliceData = pieStringDataSet.filter((each: any) => each[percentField] == data[i]);
                 sliceData[0].frequency = sliceData[0].frequency + 1;
             }
-            pieDataSet = pieStringDataSet
-            percentField = Object.keys(pieDataSet[0])[0]
-            descriptionField = Object.keys(pieDataSet[0])[1]!
-            data = this.data(pieStringDataSet)
+            pieDataSet = pieStringDataSet;
+            percentField = Object.keys(pieDataSet[0])[0];
+            descriptionField = Object.keys(pieDataSet[0])[1]!;
+            data = this.data(pieStringDataSet);
         }
-        var trackDuplicates : {[key: string]: any} = {};
-        data.forEach((eachData: any) => !trackDuplicates[eachData]? trackDuplicates[eachData] = 0: null)
+        var trackDuplicates: { [key: string]: any } = {};
+        data.forEach((eachData: any) => (!trackDuplicates[eachData] ? (trackDuplicates[eachData] = 0) : null));
 
         // initial chart
         var svg = (this._piechartSvg = d3
             .select(this._piechartRef.current)
-            .append("svg")
-                .attr("class", "graph")
-                .attr("width", width + this.props.margin.right + this.props.margin.left)
-                .attr("height", height + this.props.margin.top + this.props.margin.bottom)
-            .append("g"));
-        let g = svg.append("g")
-            .attr("transform",
-                    "translate(" + (width/2 + this.props.margin.left) + "," + height/2 + ")");
+            .append('svg')
+            .attr('class', 'graph')
+            .attr('width', width + this.props.margin.right + this.props.margin.left)
+            .attr('height', height + this.props.margin.top + this.props.margin.bottom)
+            .append('g'));
+        let g = svg.append('g').attr('transform', 'translate(' + (width / 2 + this.props.margin.left) + ',' + height / 2 + ')');
         var pie = d3.pie();
-        var arc = d3.arc()
-            .innerRadius(0)
-            .outerRadius(radius);
+        var arc = d3.arc().innerRadius(0).outerRadius(radius);
 
         // click/hover
         const onPointClick = action((e: any) => this.highlightSelectedSlice(true, svg, arc, radius, d3.pointer(e), pieDataSet));
         const onHover = action((e: any) => {
-            const selected = this.highlightSelectedSlice(false, svg, arc, radius, d3.pointer(e), pieDataSet)
+            const selected = this.highlightSelectedSlice(false, svg, arc, radius, d3.pointer(e), pieDataSet);
             updateHighlights();
-        })
+        });
         const mouseOut = action((e: any) => {
             this.hoverOverData = undefined;
             updateHighlights();
-        })
+        });
         const updateHighlights = () => {
             const hoverOverSlice = this.hoverOverData;
             const selectedData = this.selectedData;
-            svg.selectAll('path').attr("class", function(d: any) { 
-                return ((selectedData && d.startAngle==selectedData.startAngle && d.endAngle==selectedData.endAngle)
-                    || ((hoverOverSlice && d.startAngle==hoverOverSlice.startAngle && d.endAngle==hoverOverSlice.endAngle)))? 'slice hover' : 'slice'; })
-        }
+            svg.selectAll('path').attr('class', function (d: any) {
+                return (selectedData && d.startAngle == selectedData.startAngle && d.endAngle == selectedData.endAngle) || (hoverOverSlice && d.startAngle == hoverOverSlice.startAngle && d.endAngle == hoverOverSlice.endAngle)
+                    ? 'slice hover'
+                    : 'slice';
+            });
+        };
 
         // drawing the slices
         var selected = this.selectedData;
-        var arcs = g.selectAll("arc")
-            .data(pie(data))
-            .enter()
-            .append("g")
-        arcs.append("path")
-            .attr("fill", (d, i)=>{ 
-                var possibleDataPoints = pieDataSet.filter((each: { [x: string]: any | { valueOf(): number; }; }) => {
+        var arcs = g.selectAll('arc').data(pie(data)).enter().append('g');
+        arcs.append('path')
+            .attr('fill', (d, i) => {
+                var possibleDataPoints = pieDataSet.filter((each: { [x: string]: any | { valueOf(): number } }) => {
                     try {
-                        return Number(each[percentField].replace(/\$/g, '').replace(/\%/g, '').replace(/\</g, ''))==Number(d.data)
+                        return Number(each[percentField].replace(/\$/g, '').replace(/\%/g, '').replace(/\</g, '')) == Number(d.data);
                     } catch (error) {
-                        return each[percentField]==d.data
-                    }})
+                        return each[percentField] == d.data;
+                    }
+                });
                 var dataPoint;
-                if (possibleDataPoints.length==1) dataPoint = possibleDataPoints[0];
-                else{
-                    dataPoint = possibleDataPoints[trackDuplicates[d.data.toString()]]
+                if (possibleDataPoints.length == 1) dataPoint = possibleDataPoints[0];
+                else {
+                    dataPoint = possibleDataPoints[trackDuplicates[d.data.toString()]];
                     trackDuplicates[d.data.toString()] = trackDuplicates[d.data.toString()] + 1;
                 }
                 var sliceColor;
-                if (dataPoint){
+                if (dataPoint) {
                     var accessByName = dataPoint[this.props.axes[0]].replace(/\$/g, '').replace(/\%/g, '').replace(/\</g, '');
                     var sliceColors = StrListCast(this.props.layoutDoc.pieSliceColors).map(each => each.split('::'));
-                    sliceColors.map(each => {if (each[0]==StrCast(accessByName)) sliceColor = each[1]});
+                    sliceColors.map(each => {
+                        if (each[0] == StrCast(accessByName)) sliceColor = each[1];
+                    });
                 }
-                return sliceColor? StrCast(sliceColor) : d3.schemeSet3[i]? d3.schemeSet3[i]: d3.schemeSet3[i%(d3.schemeSet3.length)] })
-                .attr("class", selected? 
-                function(d) {
-                    return (selected && d.startAngle==selected.startAngle && d.endAngle==selected.endAngle)? 'slice hover' : 'slice';
-                }: function(d) {return 'slice'})
+                return sliceColor ? StrCast(sliceColor) : d3.schemeSet3[i] ? d3.schemeSet3[i] : d3.schemeSet3[i % d3.schemeSet3.length];
+            })
+            .attr(
+                'class',
+                selected
+                    ? function (d) {
+                          return selected && d.startAngle == selected.startAngle && d.endAngle == selected.endAngle ? 'slice hover' : 'slice';
+                      }
+                    : function (d) {
+                          return 'slice';
+                      }
+            )
             .attr('d', arc)
             .on('click', onPointClick)
             .on('mouseover', onHover)
@@ -282,99 +294,106 @@ export class PieChart extends React.Component<PieChartProps> {
 
         // adding labels
         trackDuplicates = {};
-        data.forEach((eachData: any) => !trackDuplicates[eachData]? trackDuplicates[eachData] = 0: null)
-        arcs.append("text")
-            .attr("transform",function(d){ 
-                var centroid = arc.centroid(d as unknown as d3.DefaultArcObject)
-                var heightOffset = (centroid[1]/radius) * Math.abs(centroid[1])
-                return "translate("+ (centroid[0]+centroid[0]/(radius*.02)) + "," + (centroid[1]+heightOffset)  + ")"; })
-            .attr("text-anchor", "middle")
-            .text(function(d){ 
-                var possibleDataPoints = pieDataSet.filter((each: { [x: string]: any | { valueOf(): number; }; }) => {
+        data.forEach((eachData: any) => (!trackDuplicates[eachData] ? (trackDuplicates[eachData] = 0) : null));
+        arcs.append('text')
+            .attr('transform', function (d) {
+                var centroid = arc.centroid(d as unknown as d3.DefaultArcObject);
+                var heightOffset = (centroid[1] / radius) * Math.abs(centroid[1]);
+                return 'translate(' + (centroid[0] + centroid[0] / (radius * 0.02)) + ',' + (centroid[1] + heightOffset) + ')';
+            })
+            .attr('text-anchor', 'middle')
+            .text(function (d) {
+                var possibleDataPoints = pieDataSet.filter((each: { [x: string]: any | { valueOf(): number } }) => {
                     try {
-                        return Number(each[percentField].replace(/\$/g, '').replace(/\%/g, '').replace(/\</g, ''))==Number(d.data)
+                        return Number(each[percentField].replace(/\$/g, '').replace(/\%/g, '').replace(/\</g, '')) == Number(d.data);
                     } catch (error) {
-                        return each[percentField]==d.data
-                    }})
+                        return each[percentField] == d.data;
+                    }
+                });
                 var dataPoint;
-                if (possibleDataPoints.length==1) dataPoint = possibleDataPoints[0];
-                else{
-                    dataPoint = possibleDataPoints[trackDuplicates[d.data.toString()]]
+                if (possibleDataPoints.length == 1) dataPoint = possibleDataPoints[0];
+                else {
+                    dataPoint = possibleDataPoints[trackDuplicates[d.data.toString()]];
                     trackDuplicates[d.data.toString()] = trackDuplicates[d.data.toString()] + 1;
                 }
-                return dataPoint? dataPoint[percentField]! + (!descriptionField? '' : (' - ' + dataPoint[descriptionField]))! : ''})
+                return dataPoint ? dataPoint[percentField]! + (!descriptionField ? '' : ' - ' + dataPoint[descriptionField])! : '';
+            });
     };
 
     @action changeSelectedColor = (color: string) => {
-        this.curSliceSelected.attr("fill", color);
-        var sliceName = this._currSelected[this.props.axes[0]].replace(/\$/g, '').replace(/\%/g, '').replace(/\</g, '')
-        
-        const sliceColors = Cast(this.props.layoutDoc.pieSliceColors, listSpec("string"), null);
-        sliceColors.map(each => { if (each.split('::')[0] == sliceName) sliceColors.splice(sliceColors.indexOf(each), 1) });
+        this.curSliceSelected.attr('fill', color);
+        var sliceName = this._currSelected[this.props.axes[0]].replace(/\$/g, '').replace(/\%/g, '').replace(/\</g, '');
+
+        const sliceColors = Cast(this.props.layoutDoc.pieSliceColors, listSpec('string'), null);
+        sliceColors.map(each => {
+            if (each.split('::')[0] == sliceName) sliceColors.splice(sliceColors.indexOf(each), 1);
+        });
         sliceColors.push(StrCast(sliceName + '::' + color));
     };
 
     render() {
         this.componentDidMount();
-        var titleAccessor: any='';
-        if (this.props.axes.length==2) titleAccessor = 'pieChart-title-'+this.props.axes[0]+'-'+this.props.axes[1];
-        else if (this.props.axes.length>0) titleAccessor = 'pieChart-title-'+this.props.axes[0];
+        var titleAccessor: any = '';
+        if (this.props.axes.length == 2) titleAccessor = 'dataViz_title_pieChart_' + this.props.axes[0] + '-' + this.props.axes[1];
+        else if (this.props.axes.length > 0) titleAccessor = 'dataViz_title_pieChart_' + this.props.axes[0];
         if (!this.props.layoutDoc[titleAccessor]) this.props.layoutDoc[titleAccessor] = this.defaultGraphTitle;
         if (!this.props.layoutDoc.pieSliceColors) this.props.layoutDoc.pieSliceColors = new List<string>();
         var selected: string;
-        var curSelectedSliceName;
-        if (this._currSelected){
-            curSelectedSliceName = StrCast(this._currSelected![this.props.axes[0]].replace(/\$/g, '').replace(/\%/g, '').replace(/\</g, ''))
+        var curSelectedSliceName = '';
+        if (this._currSelected) {
+            curSelectedSliceName = StrCast(this._currSelected![this.props.axes[0]].replace(/\$/g, '').replace(/\%/g, '').replace(/\</g, ''));
             selected = '{ ';
             Object.keys(this._currSelected).map(key => {
-                key!=''? selected += key + ': ' + this._currSelected[key] + ', ': '';
-            })
-            selected = selected.substring(0, selected.length-2);
+                key != '' ? (selected += key + ': ' + this._currSelected[key] + ', ') : '';
+            });
+            selected = selected.substring(0, selected.length - 2);
             selected += ' }';
-        }
-        else selected = 'none';
+        } else selected = 'none';
         var selectedSliceColor;
         var sliceColors = StrListCast(this.props.layoutDoc.pieSliceColors).map(each => each.split('::'));
-        sliceColors.map(each => {if (each[0]==curSelectedSliceName!) selectedSliceColor = each[1]});
+        sliceColors.map(each => {
+            if (each[0] == curSelectedSliceName!) selectedSliceColor = each[1];
+        });
 
-        if (this._piechartData.length>0){
-            return (
-                this.props.axes.length >= 1 ? (
+        if (this._piechartData.length > 0) {
+            return this.props.axes.length >= 1 ? (
                 <div className="chart-container">
-                    <div className="graph-title"> 
+                    <div className="graph-title">
                         <EditableText
                             val={StrCast(this.props.layoutDoc[titleAccessor])}
-                            setVal={undoable (action(val => this.props.layoutDoc[titleAccessor] = val as string), "Change Graph Title")}
-                            color={"black"}
+                            setVal={undoable(
+                                action(val => (this.props.layoutDoc[titleAccessor] = val as string)),
+                                'Change Graph Title'
+                            )}
+                            color={'black'}
                             size={Size.LARGE}
                             fillWidth
                         />
                     </div>
                     <div ref={this._piechartRef} />
-                    {selected != 'none' ? 
+                    {selected != 'none' ? (
                         <div className={'selected-data'}>
                             Selected: {selected}
                             &nbsp; &nbsp;
                             <ColorPicker
-                                tooltip={'Change Slice Color'} 
-                                type={Type.SEC} 
-                                icon={<FaFillDrip/>}
-                                selectedColor={selectedSliceColor? selectedSliceColor : this.curSliceSelected.attr("fill")}
-                                setSelectedColor={undoable (color => this.changeSelectedColor(color), "Change Selected Slice Color")}
+                                tooltip={'Change Slice Color'}
+                                type={Type.SEC}
+                                icon={<FaFillDrip />}
+                                selectedColor={selectedSliceColor ? selectedSliceColor : this.curSliceSelected.attr('fill')}
+                                setFinalColor={undoable(color => this.changeSelectedColor(color), 'Change Selected Slice Color')}
+                                setSelectedColor={undoable(color => this.changeSelectedColor(color), 'Change Selected Slice Color')}
                                 size={Size.XSMALL}
                             />
                         </div>
-                    : null}
+                    ) : null}
                 </div>
-                ) : <span className="chart-container"> {'first use table view to select a column to graph'}</span>
+            ) : (
+                <span className="chart-container"> {'first use table view to select a column to graph'}</span>
+            );
+        } else
+            return (
+                // when it is a brushed table and the incoming table doesn't have any rows selected
+                <div className="chart-container">Selected rows of data from the incoming DataVizBox to display.</div>
             );
-        }
-        else return (
-            // when it is a brushed table and the incoming table doesn't have any rows selected
-            <div className='chart-container'>
-                Selected rows of data from the incoming DataVizBox to display.
-            </div>
-        )
     }
-
-}
\ No newline at end of file
+}
diff --git a/src/client/views/nodes/DataVizBox/components/TableBox.tsx b/src/client/views/nodes/DataVizBox/components/TableBox.tsx
index f56d34fa6..5579d6d80 100644
--- a/src/client/views/nodes/DataVizBox/components/TableBox.tsx
+++ b/src/client/views/nodes/DataVizBox/components/TableBox.tsx
@@ -1,4 +1,4 @@
-import { action, computed, } from 'mobx';
+import { action, computed } from 'mobx';
 import { observer } from 'mobx-react';
 import * as React from 'react';
 import { Doc, Field, StrListCast } from '../../../../../fields/Doc';
@@ -31,44 +31,45 @@ interface TableBoxProps {
 
 @observer
 export class TableBox extends React.Component<TableBoxProps> {
-
     // filters all data to just display selected data if brushed (created from an incoming link)
     @computed get _tableData() {
         if (this.incomingLinks.length! <= 0) return this.props.pairs;
-        var guids = StrListCast(this.props.layoutDoc.rowGuids);
-        return this.props.pairs?.filter(pair => this.incomingLinks[0]!.selected && StrListCast(this.incomingLinks[0].selected).includes(guids[this.props.pairs.indexOf(pair)]))
+        var guids = StrListCast(this.props.layoutDoc.dataViz_rowGuids);
+        return this.props.pairs?.filter(pair => this.incomingLinks[0]!.dataViz_selectedRows && StrListCast(this.incomingLinks[0].dataViz_selectedRows).includes(guids[this.props.pairs.indexOf(pair)]));
     }
 
     @computed get incomingLinks() {
         return LinkManager.Instance.getAllRelatedLinks(this.props.rootDoc) // out of all links
             .filter(link => {
-                return link.link_anchor_1 == this.props.rootDoc.draggedFrom}) // get links where this chart doc is the target of the link
+                return link.link_anchor_1 == this.props.rootDoc.draggedFrom;
+            }) // get links where this chart doc is the target of the link
             .map(link => DocCast(link.link_anchor_1)); // then return the source of the link
     }
 
     @computed get columns() {
-        if (!this.props.layoutDoc.rowGuids) this.props.layoutDoc.rowGuids = new List<string>();
-        const guids = Cast(this.props.layoutDoc.rowGuids, listSpec("string"), null);
-        if (guids.length==0) this.props.pairs.map(row => guids.push(Utils.GenerateGuid()));
-        return this._tableData.length ? Array.from(Object.keys(this._tableData[0])).filter(header => header!='' && header!=undefined) : [];
+        if (!this.props.layoutDoc.dataViz_rowGuids) this.props.layoutDoc.dataViz_rowGuids = new List<string>();
+        const guids = Cast(this.props.layoutDoc.dataViz_rowGuids, listSpec('string'), null);
+        if (guids.length == 0) this.props.pairs.map(row => guids.push(Utils.GenerateGuid()));
+        return this._tableData.length ? Array.from(Object.keys(this._tableData[0])).filter(header => header != '' && header != undefined) : [];
     }
 
     // updates the 'selected' field to no longer include rows that aren't in the table
     filterSelectedRowsDown() {
-        if (!this.props.layoutDoc.selected) this.props.layoutDoc.selected = new List<string>();
-        const selected = Cast(this.props.layoutDoc.selected, listSpec("string"), null);
-        const incomingSelected = this.incomingLinks.length? StrListCast(this.incomingLinks[0].selected) : undefined;
-        if (incomingSelected){
+        if (!this.props.layoutDoc.dataViz_selectedRows) this.props.layoutDoc.dataViz_selectedRows = new List<string>();
+        const selected = Cast(this.props.layoutDoc.dataViz_selectedRows, listSpec('string'), null);
+        const incomingSelected = this.incomingLinks.length ? StrListCast(this.incomingLinks[0].dataViz_selectedRows) : undefined;
+        if (incomingSelected) {
             selected.map(guid => {
-                if (!incomingSelected.includes(guid)) selected.splice(selected.indexOf(guid), 1)}); // filters through selected to remove guids that were removed in the incoming data
+                if (!incomingSelected.includes(guid)) selected.splice(selected.indexOf(guid), 1);
+            }); // filters through selected to remove guids that were removed in the incoming data
         }
     }
 
     render() {
         this.filterSelectedRowsDown();
-        if (this._tableData.length>0){
+        if (this._tableData.length > 0) {
             return (
-                <div className="table-container" style={{height: this.props.height}}>
+                <div className="table-container" style={{ height: this.props.height }}>
                     <table className="table">
                         <thead>
                             <tr className="table-row">
@@ -83,7 +84,8 @@ export class TableBox extends React.Component<TableBoxProps> {
                                                 style={{
                                                     color: this.props.axes.slice().reverse().lastElement() === col ? 'darkgreen' : this.props.axes.lastElement() === col ? 'darkred' : undefined,
                                                     background: this.props.axes.slice().reverse().lastElement() === col ? '#E3fbdb' : this.props.axes.lastElement() === col ? '#Fbdbdb' : undefined,
-                                                    fontWeight: 'bolder', border: '3px solid black'
+                                                    fontWeight: 'bolder',
+                                                    border: '3px solid black',
                                                 }}
                                                 onPointerDown={e => {
                                                     const downX = e.clientX;
@@ -91,12 +93,13 @@ export class TableBox extends React.Component<TableBoxProps> {
                                                     setupMoveUpEvents(
                                                         {},
                                                         e,
-                                                        e => { // dragging off a column to create a brushed DataVizBox
+                                                        e => {
+                                                            // dragging off a column to create a brushed DataVizBox
                                                             const sourceAnchorCreator = () => this.props.docView?.()!.rootDoc!;
                                                             const targetCreator = (annotationOn: Doc | undefined) => {
                                                                 const embedding = Doc.MakeEmbedding(this.props.docView?.()!.rootDoc!);
-                                                                embedding._dataVizView = DataVizView.TABLE;
-                                                                embedding._data_vizAxes = new List<string>([col, col]);
+                                                                embedding._dataViz = DataVizView.TABLE;
+                                                                embedding._dataViz_axes = new List<string>([col, col]);
                                                                 embedding._draggedFrom = this.props.docView?.()!.rootDoc!;
                                                                 embedding.annotationOn = annotationOn; //this.props.docView?.()!.rootDoc!;
                                                                 embedding.histogramBarColors = Field.Copy(this.props.layoutDoc.histogramBarColors);
@@ -142,25 +145,33 @@ export class TableBox extends React.Component<TableBoxProps> {
                         <tbody>
                             {this._tableData?.map((p, i) => {
                                 var containsData = false;
-                                var guid = StrListCast(this.props.layoutDoc.rowGuids)![this.props.pairs.indexOf(p)]
-                                this.columns.map(col => {if (p[col]!='' && p[col]!=null && p[col]!=undefined) containsData = true})
-                                if (containsData){
+                                var guid = StrListCast(this.props.layoutDoc.dataViz_rowGuids)![this.props.pairs.indexOf(p)];
+                                this.columns.map(col => {
+                                    if (p[col] != '' && p[col] != null && p[col] != undefined) containsData = true;
+                                });
+                                if (containsData) {
                                     return (
-                                        <tr key={i} className="table-row" onClick={action(e => {
+                                        <tr
+                                            key={i}
+                                            className="table-row"
+                                            onClick={action(e => {
                                                 // selecting a row
-                                                const selected = Cast(this.props.layoutDoc.selected, listSpec("string"), null);
+                                                const selected = Cast(this.props.layoutDoc.dataViz_selectedRows, listSpec('string'), null);
                                                 if (selected.includes(guid)) selected.splice(selected.indexOf(guid), 1);
                                                 else {
-                                                    selected.push(guid)};
-                                            })} style={{ background: StrListCast(this.props.layoutDoc.selected).includes(guid) ? 'lightgrey' : '', width: '110%' }}>
+                                                    selected.push(guid);
+                                                }
+                                            })}
+                                            style={{ background: StrListCast(this.props.layoutDoc.dataViz_selectedRows).includes(guid) ? 'lightgrey' : '', width: '110%' }}>
                                             {this.columns.map(col => {
-                                                    // each cell
-                                                    var colSelected = this.props.axes[0]==col || this.props.axes[1]==col;
-                                                    return (
-                                                    <td key={this.columns.indexOf(col)} style={{border: colSelected? '3px solid black' : '1px solid black', fontWeight: colSelected? 'bolder' : 'normal'}}>
+                                                // each cell
+                                                var colSelected = this.props.axes[0] == col || this.props.axes[1] == col;
+                                                return (
+                                                    <td key={this.columns.indexOf(col)} style={{ border: colSelected ? '3px solid black' : '1px solid black', fontWeight: colSelected ? 'bolder' : 'normal' }}>
                                                         {p[col]}
                                                     </td>
-                                             )})}
+                                                );
+                                            })}
                                         </tr>
                                     );
                                 }
@@ -169,12 +180,10 @@ export class TableBox extends React.Component<TableBoxProps> {
                     </table>
                 </div>
             );
-        }
-        else return (
-            // when it is a brushed table and the incoming table doesn't have any rows selected
-            <div className='chart-container'>
-                Selected rows of data from the incoming DataVizBox to display.
-            </div>
-        )
+        } else
+            return (
+                // when it is a brushed table and the incoming table doesn't have any rows selected
+                <div className="chart-container">Selected rows of data from the incoming DataVizBox to display.</div>
+            );
     }
 }
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 90fb55290..c5dead708 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -113,7 +113,7 @@ export interface DocComponentView {
     getAnchor?: (addAsAnnotation: boolean, pinData?: PinProps) => Doc; // returns an Anchor Doc that represents the current state of the doc's componentview (e.g., the current playhead location of a an audio/video box)
     restoreView?: (viewSpec: Doc) => boolean;
     scrollPreview?: (docView: DocumentView, doc: Doc, focusSpeed: number, options: DocFocusOptions) => Opt<number>; // returns the duration of the focus
-    brushView?: (view: { width: number; height: number; panX: number; panY: number }) => void;
+    brushView?: (view: { width: number; height: number; panX: number; panY: number }, transTime: number) => void;
     getView?: (doc: Doc) => Promise<Opt<DocumentView>>; // returns a nested DocumentView for the specified doc or undefined
     addDocTab?: (doc: Doc, where: OpenWhere) => boolean; // determines how to add a document - used in following links to open the target ina local lightbox
     addDocument?: (doc: Doc | Doc[], annotationKey?: string) => boolean; // add a document (used only by collections)
@@ -1095,6 +1095,8 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
                     pointerEvents: this.rootDoc.ignoreClick ? 'none' : this.isContentActive() || this.props.isDocumentActive?.() ? 'all' : undefined,
                     minWidth: 50 * ffscale(),
                     maxHeight: `max(100%, ${20 * ffscale()}px)`,
+                    background: StrCast(this.layoutDoc._backgroundColor, 'rgba(0,0,0,0.2)'),
+                    color: lightOrDark(StrCast(this.layoutDoc._backgroundColor, 'black')),
                 }}>
                 <FormattedTextBox
                     {...this.props}
@@ -1112,10 +1114,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
             </div>
         );
         const targetDoc = showTitle?.startsWith('_') ? this.layoutDoc : this.rootDoc;
-        const background = StrCast(
-            SharingManager.Instance.users.find(u => u.user.email === this.dataDoc.author)?.sharingDoc.headingColor,
-            Doc.UserDoc().layout_showTitle && [DocumentType.RTF, DocumentType.COL].includes(this.rootDoc.type as any) ? StrCast(Doc.SharingDoc().headingColor) : SettingsManager.Instance.userVariantColor
-        );
+        const background = StrCast(SharingManager.Instance.users.find(u => u.user.email === this.dataDoc.author)?.sharingDoc.headingColor, StrCast(Doc.SharingDoc().headingColor, SettingsManager.Instance.userVariantColor));
         const sidebarWidthPercent = +StrCast(this.layoutDoc.layout_sidebarWidthPercent).replace('%', '');
         const titleView = !showTitle ? null : (
             <div
@@ -1204,7 +1203,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
      * @returns a function that will wrap a JSX animation element wrapping any JSX element
      */
     public static AnimationEffect(renderDoc: JSX.Element, presEffectDoc: Opt<Doc>, root: Doc) {
-        const dir = presEffectDoc?.presEffectDirection ?? presEffectDoc?.followLinkAnimDirection;
+        const dir = presEffectDoc?.presentation_effectDirection ?? presEffectDoc?.followLinkAnimDirection;
         const effectProps = {
             left: dir === PresEffectDirection.Left,
             right: dir === PresEffectDirection.Right,
@@ -1212,10 +1211,10 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
             bottom: dir === PresEffectDirection.Bottom,
             opposite: true,
             delay: 0,
-            duration: Cast(presEffectDoc?.presTransition, 'number', Cast(presEffectDoc?.followLinkTransitionTime, 'number', null)),
+            duration: Cast(presEffectDoc?.presentation_transition, 'number', Cast(presEffectDoc?.followLinkTransitionTime, 'number', null)),
         };
         //prettier-ignore
-        switch (StrCast(presEffectDoc?.presEffect, StrCast(presEffectDoc?.followLinkAnimEffect))) {
+        switch (StrCast(presEffectDoc?.presentation_effect, StrCast(presEffectDoc?.followLinkAnimEffect))) {
             default: 
             case PresEffect.None:       return renderDoc;
             case PresEffect.Zoom:       return <Zoom {...effectProps}>{renderDoc}</Zoom>;
@@ -1543,7 +1542,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
                             <div className="webBox-textHighlight">
                                 <ObserverJsxParser autoCloseVoidElements={true} key={42} onError={(e: any) => console.log('PARSE error', e)} renderInWrapper={false} jsx={StrCast(this.textHtmlOverlay)} />
                             </div>,
-                            { presEffect: this.htmlOverlayEffect ?? 'Zoom' } as any as Doc,
+                            { presentation_effect: this.htmlOverlayEffect ?? 'Zoom' } as any as Doc,
                             this.rootDoc
                         )}{' '}
                     </Fade>
diff --git a/src/client/views/nodes/FontIconBox/FontIconBox.tsx b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
index 1b2209224..bf3c79cf9 100644
--- a/src/client/views/nodes/FontIconBox/FontIconBox.tsx
+++ b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
@@ -267,7 +267,7 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
         return ScriptCast(this.rootDoc.script);
     }
 
-    colorBatch:UndoManager.Batch|undefined;
+    colorBatch: UndoManager.Batch | undefined;
     /**
      * Color button
      */
@@ -285,7 +285,7 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
                 setFinalColor={value => {
                     this.colorScript?.script.run({ this: this.layoutDoc, self: this.rootDoc, value: value, _readOnly_: false });
                     this.colorBatch?.end();
-                    this.colorBatch= undefined;
+                    this.colorBatch = undefined;
                 }}
                 selectedColor={curColor}
                 type={Type.PRIM}
diff --git a/src/client/views/nodes/FunctionPlotBox.tsx b/src/client/views/nodes/FunctionPlotBox.tsx
index 61711417f..40f48dafe 100644
--- a/src/client/views/nodes/FunctionPlotBox.tsx
+++ b/src/client/views/nodes/FunctionPlotBox.tsx
@@ -48,8 +48,8 @@ export class FunctionPlotBox extends ViewBoxAnnotatableComponent<FieldViewProps>
             annotationOn: this.rootDoc,
         });
         PresBox.pinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: { ...(pinProps?.pinData ?? {}), datarange: true } }, this.rootDoc);
-        anchor.presXRange = new List<number>(Array.from(this._plot.options.xAxis.domain));
-        anchor.presYRange = new List<number>(Array.from(this._plot.options.yAxis.domain));
+        anchor.config_xRange = new List<number>(Array.from(this._plot.options.xAxis.domain));
+        anchor.config_yRange = new List<number>(Array.from(this._plot.options.yAxis.domain));
         if (addAsAnnotation) this.addDocument(anchor);
         return anchor;
     };
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx
index d763753a5..c7ccd1ea0 100644
--- a/src/client/views/nodes/ImageBox.tsx
+++ b/src/client/views/nodes/ImageBox.tsx
@@ -22,7 +22,6 @@ import { DocumentType } from '../../documents/DocumentTypes';
 import { Networking } from '../../Network';
 import { DocumentManager } from '../../util/DocumentManager';
 import { DragManager } from '../../util/DragManager';
-import { SnappingManager } from '../../util/SnappingManager';
 import { undoBatch } from '../../util/UndoManager';
 import { ContextMenu } from '../../views/ContextMenu';
 import { CollectionFreeFormView } from '../collections/collectionFreeForm/CollectionFreeFormView';
@@ -80,10 +79,10 @@ export class ImageBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
             this._getAnchor?.(this._savedAnnotations, false) ?? // use marquee anchor, otherwise, save zoom/pan as anchor
             Docs.Create.ConfigDocument({
                 title: 'ImgAnchor:' + this.rootDoc.title,
-                presPanX: NumCast(this.layoutDoc._freeform_panX),
-                presPanY: NumCast(this.layoutDoc._freeform_panY),
-                presViewScale: Cast(this.layoutDoc._freeform_scale, 'number', null),
-                presTransition: 1000,
+                config_panX: NumCast(this.layoutDoc._freeform_panX),
+                config_panY: NumCast(this.layoutDoc._freeform_panY),
+                config_viewScale: Cast(this.layoutDoc._freeform_scale, 'number', null),
+                presentation_transition: 1000,
                 annotationOn: this.rootDoc,
             });
         if (anchor) {
@@ -295,7 +294,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
     choosePath(url: URL) {
         const lower = url.href.toLowerCase();
         if (url.protocol === 'data') return url.href;
-        if (url.href.indexOf(window.location.origin) === -1 && url.href.indexOf("dashblobstore") === -1) return Utils.CorsProxy(url.href);
+        if (url.href.indexOf(window.location.origin) === -1 && url.href.indexOf('dashblobstore') === -1) return Utils.CorsProxy(url.href);
         if (!/\.(png|jpg|jpeg|gif|webp)$/.test(lower)) return `/assets/unknown-file-icon-hi.png`;
 
         const ext = extname(url.href);
@@ -414,7 +413,8 @@ export class ImageBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
     @computed get content() {
         TraceMobx();
 
-        const backAlpha = DashColor(this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor)).alpha();
+        const backColor = DashColor(this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor));
+        const backAlpha = backColor.red() === 0 && backColor.green() === 0 && backColor.blue() === 0 ? backColor.alpha() : 1;
         const srcpath = this.layoutDoc.hideImage ? '' : this.paths[0];
         const fadepath = this.layoutDoc.hideImage ? '' : this.paths.lastElement();
         const { nativeWidth, nativeHeight, nativeOrientation } = this.nativeSize;
diff --git a/src/client/views/nodes/KeyValueBox.tsx b/src/client/views/nodes/KeyValueBox.tsx
index a6712a3db..673f711be 100644
--- a/src/client/views/nodes/KeyValueBox.tsx
+++ b/src/client/views/nodes/KeyValueBox.tsx
@@ -4,7 +4,7 @@ import { Doc, Field, FieldResult } from '../../../fields/Doc';
 import { List } from '../../../fields/List';
 import { RichTextField } from '../../../fields/RichTextField';
 import { ComputedField, ScriptField } from '../../../fields/ScriptField';
-import { DocCast, NumCast } from '../../../fields/Types';
+import { DocCast } from '../../../fields/Types';
 import { ImageField } from '../../../fields/URLField';
 import { returnAll, returnAlways, returnTrue } from '../../../Utils';
 import { Docs } from '../../documents/Documents';
@@ -13,6 +13,7 @@ import { CompiledScript, CompileScript, ScriptOptions } from '../../util/Scripti
 import { undoBatch } from '../../util/UndoManager';
 import { ContextMenu } from '../ContextMenu';
 import { ContextMenuProps } from '../ContextMenuItem';
+import { DocumentIconContainer } from './DocumentIcon';
 import { OpenWhere } from './DocumentView';
 import { FieldView, FieldViewProps } from './FieldView';
 import { FormattedTextBox } from './formattedText/FormattedTextBox';
@@ -20,10 +21,6 @@ import { ImageBox } from './ImageBox';
 import './KeyValueBox.scss';
 import { KeyValuePair } from './KeyValuePair';
 import React = require('react');
-import { DocumentManager } from '../../util/DocumentManager';
-import { ScriptingGlobals } from '../../util/ScriptingGlobals';
-import { ScriptingRepl } from '../ScriptingRepl';
-import { DocumentIconContainer } from './DocumentIcon';
 
 export type KVPScript = {
     script: CompiledScript;
@@ -147,7 +144,15 @@ export class KeyValueBox extends React.Component<FieldViewProps> {
         const self = this;
         const keys = Object.keys(ids).slice();
         //for (const key of [...keys.filter(id => id !== 'layout' && !id.includes('_')).sort(), ...keys.filter(id => id === 'layout' || id.includes('_')).sort()]) {
-        for (const key of keys.sort()) {
+        for (const key of keys.sort((a: string, b: string) => {
+            const a_ = a.split('_')[0];
+            const b_ = b.split('_')[0];
+            if (a_ < b_) return -1;
+            if (a_ > b_) return 1;
+            if (a === a_) return -1;
+            if (b === b_) return 1;
+            return a === b ? 0 : a < b ? -1 : 1;
+        })) {
             rows.push(
                 <KeyValuePair
                     doc={realDoc}
diff --git a/src/client/views/nodes/LinkBox.tsx b/src/client/views/nodes/LinkBox.tsx
index 710d41471..efb949a47 100644
--- a/src/client/views/nodes/LinkBox.tsx
+++ b/src/client/views/nodes/LinkBox.tsx
@@ -18,7 +18,7 @@ export class LinkBox extends ViewBoxBaseComponent<FieldViewProps>() {
         this.props.setContentView?.(this);
     }
     render() {
-        if (this.dataDoc.treeViewOpen === undefined) setTimeout(() => (this.dataDoc.treeViewOpen = true));
+        if (this.dataDoc.treeView_Open === undefined) setTimeout(() => (this.dataDoc.treeView_Open = true));
         return (
             <div className={`linkBox-container${this.props.isContentActive() ? '-interactive' : ''}`} style={{ background: this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.BackgroundColor) }}>
                 <ComparisonBox
diff --git a/src/client/views/nodes/MapBox/MapBox.tsx b/src/client/views/nodes/MapBox/MapBox.tsx
index 4919ee94c..cf017d746 100644
--- a/src/client/views/nodes/MapBox/MapBox.tsx
+++ b/src/client/views/nodes/MapBox/MapBox.tsx
@@ -102,7 +102,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
     }
     private _setPreviewCursor: undefined | ((x: number, y: number, drag: boolean, hide: boolean) => void);
     @computed get inlineTextAnnotations() {
-        return this.allMapMarkers.filter(a => a.textInlineAnnotations);
+        return this.allMapMarkers.filter(a => a.text_inlineAnnotations);
     }
 
     @observable private _map: google.maps.Map = null as unknown as google.maps.Map;
diff --git a/src/client/views/nodes/MapBox/MapBox2.tsx b/src/client/views/nodes/MapBox/MapBox2.tsx
index a9154c5bb..b3ae8242d 100644
--- a/src/client/views/nodes/MapBox/MapBox2.tsx
+++ b/src/client/views/nodes/MapBox/MapBox2.tsx
@@ -100,7 +100,7 @@ export class MapBox2 extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
     }
     private _setPreviewCursor: undefined | ((x: number, y: number, drag: boolean, hide: boolean) => void);
     @computed get inlineTextAnnotations() {
-        return this.allMapMarkers.filter(a => a.textInlineAnnotations);
+        return this.allMapMarkers.filter(a => a.text_inlineAnnotations);
     }
 
     @observable private _map: google.maps.Map = null as unknown as google.maps.Map;
diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx
index fd4c6366b..758b49655 100644
--- a/src/client/views/nodes/PDFBox.tsx
+++ b/src/client/views/nodes/PDFBox.tsx
@@ -213,7 +213,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
         );
     }
 
-    brushView = (view: { width: number; height: number; panX: number; panY: number }) => this._pdfViewer?.brushView(view);
+    brushView = (view: { width: number; height: number; panX: number; panY: number }, transTime: number) => this._pdfViewer?.brushView(view, transTime);
 
     sidebarAddDocTab = (doc: Doc, where: OpenWhere) => {
         if (DocListCast(this.props.Document[this.props.fieldKey + '_sidebar']).includes(doc) && !this.SidebarShown) {
@@ -224,7 +224,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
     };
     focus = (anchor: Doc, options: DocFocusOptions) => {
         this._initialScrollTarget = anchor;
-        return this._pdfViewer?.scrollFocus(anchor, NumCast(anchor.y, NumCast(anchor.presViewScroll)), options);
+        return this._pdfViewer?.scrollFocus(anchor, NumCast(anchor.y, NumCast(anchor.config_scrollTop)), options);
     };
 
     getView = async (doc: Doc) => {
@@ -247,7 +247,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
         const anchor = annoAnchor ?? docAnchor();
         PresBox.pinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: { ...(pinProps?.pinData ?? {}), scrollable: true, pannable: true } }, this.rootDoc);
         anchor.text = ele?.textContent ?? '';
-        anchor.textHtml = ele?.innerHTML;
+        anchor.text_html = ele?.innerHTML;
         if (addAsAnnotation || annoAnchor) {
             this.addDocument(anchor);
         }
diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx
index f5df42161..febf8341e 100644
--- a/src/client/views/nodes/WebBox.tsx
+++ b/src/client/views/nodes/WebBox.tsx
@@ -51,7 +51,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
     public static sidebarResizerWidth = 5;
     static webStyleSheet = addStyleSheet();
     private _setPreviewCursor: undefined | ((x: number, y: number, drag: boolean, hide: boolean) => void);
-    private _setBrushViewer: undefined | ((view: { width: number; height: number; panX: number; panY: number }) => void);
+    private _setBrushViewer: undefined | ((view: { width: number; height: number; panX: number; panY: number }, transTime: number) => void);
     private _mainCont: React.RefObject<HTMLDivElement> = React.createRef();
     private _outerRef: React.RefObject<HTMLDivElement> = React.createRef();
     private _disposers: { [name: string]: IReactionDisposer } = {};
@@ -91,7 +91,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
         return DocListCast(this.dataDoc[this.annotationKey]);
     }
     @computed get inlineTextAnnotations() {
-        return this.allAnnotations.filter(a => a.textInlineAnnotations);
+        return this.allAnnotations.filter(a => a.text_inlineAnnotations);
     }
     @computed get webField() {
         return Cast(this.rootDoc[this.props.fieldKey], WebField)?.url;
@@ -133,7 +133,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
                 (this._iframe?.contentWindow as any)?.find(searchString, false, bwd, true);
             }
         } catch (e) {
-            console.log("WebBox search error", e)
+            console.log('WebBox search error', e);
         }
         return true;
     };
@@ -281,8 +281,8 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
         return this._savedAnnotations;
     };
 
-    setBrushViewer = (func?: (view: { width: number; height: number; panX: number; panY: number }) => void) => (this._setBrushViewer = func);
-    brushView = (view: { width: number; height: number; panX: number; panY: number }) => this._setBrushViewer?.(view);
+    setBrushViewer = (func?: (view: { width: number; height: number; panX: number; panY: number }, transTime: number) => void) => (this._setBrushViewer = func);
+    brushView = (view: { width: number; height: number; panX: number; panY: number }, transTime: number) => this._setBrushViewer?.(view, transTime);
     focus = (anchor: Doc, options: DocFocusOptions) => {
         if (anchor !== this.rootDoc && this._outerRef.current) {
             const windowHeight = this.props.PanelHeight() / (this.props.NativeDimScaling?.() || 1);
@@ -303,7 +303,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
     getView = (doc: Doc) => {
         if (Doc.AreProtosEqual(doc, this.rootDoc)) return new Promise<Opt<DocumentView>>(res => res(this.props.DocumentView?.()));
         if (this.rootDoc.layout_fieldKey === 'layout_icon') this.props.DocumentView?.().iconify();
-        const webUrl = WebCast(doc.presData)?.url;
+        const webUrl = WebCast(doc.config_data)?.url;
         if (this._url && webUrl && webUrl.href !== this._url) this.setData(webUrl.href);
         if (this._sidebarRef?.current?.makeDocUnfiltered(doc) && !this.SidebarShown) this.toggleSidebar(false);
         return new Promise<Opt<DocumentView>>(res => DocumentManager.Instance.AddViewRenderedCb(doc, dv => res(dv)));
@@ -334,7 +334,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
             });
         PresBox.pinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: { ...(pinProps?.pinData ?? {}), scrollable: pinProps?.pinData ? true : false, pannable: true } }, this.rootDoc);
         anchor.text = ele?.textContent ?? '';
-        anchor.textHtml = ele?.innerHTML;
+        anchor.text_html = ele?.innerHTML;
         //addAsAnnotation &&
         this.addDocumentWrapper(anchor);
         return anchor;
@@ -761,7 +761,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
     }
 
     addDocumentWrapper = (doc: Doc | Doc[], annotationKey?: string) => {
-        (doc instanceof Doc ? [doc] : doc).forEach(doc => (doc.presData = new WebField(this._url)));
+        (doc instanceof Doc ? [doc] : doc).forEach(doc => (doc.config_data = new WebField(this._url)));
         return this.addDocument(doc, annotationKey);
     };
 
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index 1dcc445e8..eea4f513e 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -417,7 +417,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
             DocListCast(Doc.MyPublishedDocs.data).forEach(term => (tr = this.hyperlinkTerm(tr, term, newAutoLinks)));
             tr = tr.setSelection(isNodeSel && false ? new NodeSelection(tr.doc.resolve(f)) : new TextSelection(tr.doc.resolve(f), tr.doc.resolve(t)));
             this._editorView?.dispatch(tr);
-            this.prepareForTyping();
+            // this.prepareForTyping();
         }
         oldAutoLinks.filter(oldLink => !newAutoLinks.has(oldLink) && oldLink.link_anchor_2 !== this.rootDoc).forEach(LinkManager.Instance.deleteLink);
     };
@@ -730,7 +730,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
 
     @undoBatch
     showTargetTrail = (anchor: Doc) => {
-        const trail = DocCast(anchor.presTrail);
+        const trail = DocCast(anchor.presentationTrail);
         if (trail) {
             Doc.ActivePresentation = trail;
             this.props.addDocTab(trail, OpenWhere.replaceRight);
@@ -1237,7 +1237,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
         this._disposers.selected = reaction(
             () => this.props.isSelected(),
             action(selected => {
-                selected && this.prepareForTyping();
+                //selected && setTimeout(() => this.prepareForTyping());
                 if (FormattedTextBox._globalHighlights.has('Bold Text')) {
                     this.layoutDoc[DocCss] = this.layoutDoc[DocCss] + 1; // css change happens outside of mobx/react, so this will notify anyone interested in the layout that it has changed
                 }
@@ -1550,18 +1550,17 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
 
     // add user mark for any first character that was typed since the user mark that gets set in KeyPress won't have been called yet.
     prepareForTyping = () => {
-        this._editorView?.dispatch(
-            this._editorView?.state.tr.setStoredMarks([
-                ...(this._editorView.state.storedMarks?.filter(mark => ![schema.marks.em, schema.marks.underline, schema.marks.pFontFamily, schema.marks.pFontSize, schema.marks.strong, schema.marks.pFontColor].includes(mark.type)) ?? []),
-                ...[schema.marks.user_mark.create({ userid: Doc.CurrentUserEmail, modified: Math.floor(Date.now() / 1000) })],
-                ...(Doc.UserDoc().fontColor !== 'transparent' && Doc.UserDoc().fontColor ? [schema.mark(schema.marks.pFontColor, { color: StrCast(Doc.UserDoc().fontColor) })] : []),
-                ...(Doc.UserDoc().fontStyle === 'italics' ? [schema.mark(schema.marks.em)] : []),
-                ...(Doc.UserDoc().textDecoration === 'underline' ? [schema.mark(schema.marks.underline)] : []),
-                ...(Doc.UserDoc().fontFamily ? [schema.mark(schema.marks.pFontFamily, { family: this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.FontFamily) })] : []),
-                ...(Doc.UserDoc().fontSize ? [schema.mark(schema.marks.pFontSize, { fontSize: this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.FontSize) })] : []),
-                ...(Doc.UserDoc().fontWeight === 'bold' ? [schema.mark(schema.marks.strong)] : []),
-            ])
-        );
+        if (!this._editorView) return;
+        const docDefaultMarks = [
+            ...(Doc.UserDoc().fontColor !== 'transparent' && Doc.UserDoc().fontColor ? [schema.mark(schema.marks.pFontColor, { color: StrCast(Doc.UserDoc().fontColor) })] : []),
+            ...(Doc.UserDoc().fontStyle === 'italics' ? [schema.mark(schema.marks.em)] : []),
+            ...(Doc.UserDoc().textDecoration === 'underline' ? [schema.mark(schema.marks.underline)] : []),
+            ...(Doc.UserDoc().fontFamily ? [schema.mark(schema.marks.pFontFamily, { family: this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.FontFamily) })] : []),
+            ...(Doc.UserDoc().fontSize ? [schema.mark(schema.marks.pFontSize, { fontSize: this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.FontSize) })] : []),
+            ...(Doc.UserDoc().fontWeight === 'bold' ? [schema.mark(schema.marks.strong)] : []),
+            ...[schema.marks.user_mark.create({ userid: Doc.CurrentUserEmail, modified: Math.floor(Date.now() / 1000) })],
+        ];
+        this._editorView?.dispatch(this._editorView?.state.tr.setStoredMarks(docDefaultMarks));
     };
 
     @action
diff --git a/src/client/views/nodes/formattedText/ProsemirrorExampleTransfer.ts b/src/client/views/nodes/formattedText/ProsemirrorExampleTransfer.ts
index 112a0d87e..ec11079b4 100644
--- a/src/client/views/nodes/formattedText/ProsemirrorExampleTransfer.ts
+++ b/src/client/views/nodes/formattedText/ProsemirrorExampleTransfer.ts
@@ -334,7 +334,7 @@ export function buildKeymap<S extends Schema<any>>(schema: S, props: any, mapKey
 
     //Command to create a blank space
     bind('Space', (state: EditorState, dispatch: (tx: Transaction) => void) => {
-        if (GetEffectiveAcl(props.DataDoc) != AclEdit && GetEffectiveAcl(props.DataDoc) != AclAugment && GetEffectiveAcl(props.DataDoc) != AclAdmin) return true;
+        if (props.DataDoc && GetEffectiveAcl(props.DataDoc) != AclEdit && GetEffectiveAcl(props.DataDoc) != AclAugment && GetEffectiveAcl(props.DataDoc) != AclAdmin) return true;
         const marks = state.storedMarks || (state.selection.$to.parentOffset && state.selection.$from.marks());
         dispatch(splitMetadata(marks, state.tr));
         return false;
diff --git a/src/client/views/nodes/formattedText/RichTextMenu.tsx b/src/client/views/nodes/formattedText/RichTextMenu.tsx
index 7c3e4baad..9c46459b0 100644
--- a/src/client/views/nodes/formattedText/RichTextMenu.tsx
+++ b/src/client/views/nodes/formattedText/RichTextMenu.tsx
@@ -104,7 +104,7 @@ export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps> {
     _disposer: IReactionDisposer | undefined;
     componentDidMount() {
         this._disposer = reaction(
-            () => SelectionManager.Views(),
+            () => SelectionManager.Views().slice(),
             views => this.updateMenu(undefined, undefined, undefined)
         );
     }
diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx
index aaedffc77..05f59d8fe 100644
--- a/src/client/views/nodes/trails/PresBox.tsx
+++ b/src/client/views/nodes/trails/PresBox.tsx
@@ -74,7 +74,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
     constructor(props: any) {
         super(props);
         if (!PresBox.navigateToDocScript) {
-            PresBox.navigateToDocScript = ScriptField.MakeFunction('navigateToDoc(self.presentationTargetDoc, self)')!;
+            PresBox.navigateToDocScript = ScriptField.MakeFunction('navigateToDoc(self.presentation_targetDoc, self)')!;
         }
     }
 
@@ -116,7 +116,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
         return DocListCast(this.rootDoc[this.presFieldKey]);
     }
     @computed get tagDocs() {
-        return this.childDocs.map(doc => Cast(doc.presentationTargetDoc, Doc, null));
+        return this.childDocs.map(doc => Cast(doc.presentation_targetDoc, Doc, null));
     }
     @computed get itemIndex() {
         return NumCast(this.rootDoc._itemIndex);
@@ -125,10 +125,10 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
         return DocCast(this.childDocs[NumCast(this.rootDoc._itemIndex)]);
     }
     @computed get targetDoc() {
-        return Cast(this.activeItem?.presentationTargetDoc, Doc, null);
+        return Cast(this.activeItem?.presentation_targetDoc, Doc, null);
     }
     public static targetRenderedDoc = (doc: Doc) => {
-        const targetDoc = Cast(doc?.presentationTargetDoc, Doc, null);
+        const targetDoc = Cast(doc?.presentation_targetDoc, Doc, null);
         return targetDoc?.layout_unrendered ? DocCast(targetDoc.annotationOn) : targetDoc;
     };
     @computed get scrollable() {
@@ -149,7 +149,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
     @computed get selectedDoc() {
         return this.selectedDocumentView?.rootDoc;
     }
-    isActiveItemTarget = (layoutDoc: Doc) => this.activeItem?.presentationTargetDoc === layoutDoc;
+    isActiveItemTarget = (layoutDoc: Doc) => this.activeItem?.presentation_targetDoc === layoutDoc;
     clearSelectedArray = () => this.selectedArray.clear();
     addToSelectedArray = action((doc: Doc) => this.selectedArray.add(doc));
     removeFromSelectedArray = action((doc: Doc) => this.selectedArray.delete(doc));
@@ -196,18 +196,18 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
         }
         this.turnOffEdit(true);
         this._disposers.selection = reaction(
-            () => SelectionManager.Views(),
+            () => SelectionManager.Views().slice(),
             views => (!PresBox.Instance || views.some(view => view.props.Document === this.rootDoc)) && this.updateCurrentPresentation(),
             { fireImmediately: true }
         );
         this._disposers.editing = reaction(
-            () => this.layoutDoc.presStatus === PresStatus.Edit,
+            () => this.layoutDoc.presentation_status === PresStatus.Edit,
             editing => {
                 if (editing) {
                     this.childDocs.forEach(doc => {
-                        if (doc.presIndexed !== undefined) {
+                        if (doc.presentation_indexed !== undefined) {
                             this.progressivizedItems(doc)?.forEach(indexedDoc => (indexedDoc.opacity = undefined));
-                            doc.presIndexed = Math.min(this.progressivizedItems(doc)?.length ?? 0, 1);
+                            doc.presentation_indexed = Math.min(this.progressivizedItems(doc)?.length ?? 0, 1);
                         }
                     });
                 }
@@ -224,10 +224,10 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
     _mediaTimer!: [NodeJS.Timeout, Doc];
     // 'Play on next' for audio or video therefore first navigate to the audio/video before it should be played
     startTempMedia = (targetDoc: Doc, activeItem: Doc) => {
-        const duration: number = NumCast(activeItem.presEndTime) - NumCast(activeItem.presStartTime);
+        const duration: number = NumCast(activeItem.config_clipEnd) - NumCast(activeItem.config_clipStart);
         if ([DocumentType.VID, DocumentType.AUDIO].includes(targetDoc.type as any)) {
             const targMedia = DocumentManager.Instance.getDocumentView(targetDoc);
-            targMedia?.ComponentView?.playFrom?.(NumCast(activeItem.presStartTime), NumCast(activeItem.presStartTime) + duration);
+            targMedia?.ComponentView?.playFrom?.(NumCast(activeItem.config_clipStart), NumCast(activeItem.config_clipStart) + duration);
         }
     };
 
@@ -251,12 +251,12 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
             (nextSelected: number, force = false) =>
             () => {
                 if (nextSelected < this.childDocs.length) {
-                    if (force || this.childDocs[nextSelected].groupWithUp) {
+                    if (force || this.childDocs[nextSelected].presentation_groupWithUp) {
                         this.addToSelectedArray(this.childDocs[nextSelected]);
-                        const serial = nextSelected + 1 < this.childDocs.length && NumCast(this.childDocs[nextSelected + 1].groupWithUp) > 1;
+                        const serial = nextSelected + 1 < this.childDocs.length && NumCast(this.childDocs[nextSelected + 1].presentation_groupWithUp) > 1;
                         if (serial) {
                             this.gotoDocument(nextSelected, this.activeItem, true, async () => {
-                                const waitTime = NumCast(this.activeItem.presDuration) - NumCast(this.activeItem.presTransition);
+                                const waitTime = NumCast(this.activeItem.presentation_duration) - NumCast(this.activeItem.presentation_transition);
                                 await new Promise<void>(res => setTimeout(() => res(), Math.max(0, waitTime)));
                                 doGroupWithUp(nextSelected + 1)();
                             });
@@ -274,7 +274,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
     // docs within a slide target that will be progressively revealed
     progressivizedItems = (doc: Doc) => {
         const targetList = PresBox.targetRenderedDoc(doc);
-        if (doc.presIndexed !== undefined && targetList) {
+        if (doc.presentation_indexed !== undefined && targetList) {
             const listItems = (Cast(targetList[Doc.LayoutFieldKey(targetList)], listSpec(Doc), null)?.filter(d => d instanceof Doc) as Doc[]) ?? DocListCast(targetList[Doc.LayoutFieldKey(targetList) + '_annotations']);
             return listItems.filter(doc => !doc.layout_unrendered);
         }
@@ -283,7 +283,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
     @action
     next = () => {
         const progressiveReveal = (first: boolean) => {
-            const presIndexed = Cast(this.activeItem?.presIndexed, 'number', null);
+            const presIndexed = Cast(this.activeItem?.presentation_indexed, 'number', null);
             if (presIndexed !== undefined) {
                 const targetRenderedDoc = PresBox.targetRenderedDoc(this.activeItem);
                 targetRenderedDoc._dataTransition = 'all 1s';
@@ -296,8 +296,8 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                         const targetView = listItems && DocumentManager.Instance.getFirstDocumentView(listItemDoc);
                         Doc.linkFollowUnhighlight();
                         Doc.HighlightDoc(listItemDoc);
-                        listItemDoc.presEffect = this.activeItem.presBulletEffect;
-                        listItemDoc.presTransition = 500;
+                        listItemDoc.presentation_effect = this.activeItem.presBulletEffect;
+                        listItemDoc.presentation_transition = 500;
                         targetView?.setAnimEffect(listItemDoc, 500);
                         if (targetView?.docView && this.activeItem.presBulletExpand) {
                             targetView.docView._animateScalingTo = 1.2;
@@ -308,7 +308,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                             });
                         }
                         listItemDoc.opacity = undefined;
-                        this.activeItem.presIndexed = presIndexed + 1;
+                        this.activeItem.presentation_indexed = presIndexed + 1;
                     }
                     return true;
                 }
@@ -322,7 +322,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
             this.nextSlide(curLast + 1 === this.childDocs.length ? (this.layoutDoc.presLoop ? 0 : curLast) : curLast + 1);
             progressiveReveal(true); // shows first progressive document, but without a transition effect
         } else {
-            if (this.childDocs[this.itemIndex + 1] === undefined && (this.layoutDoc.presLoop || this.layoutDoc.presStatus === PresStatus.Edit)) {
+            if (this.childDocs[this.itemIndex + 1] === undefined && (this.layoutDoc.presLoop || this.layoutDoc.presentation_status === PresStatus.Edit)) {
                 // Case 2: Last slide and presLoop is toggled ON or it is in Edit mode
                 this.nextSlide(0);
                 progressiveReveal(true); // shows first progressive document, but without a transition effect
@@ -338,9 +338,9 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
         const activeItem: Doc = this.activeItem;
         let prevSelected = this.itemIndex;
         // Functionality for group with up
-        let didZoom = activeItem.presMovement;
-        for (; prevSelected > 0 && this.childDocs[Math.max(0, prevSelected - 1)].groupWithUp; prevSelected--) {
-            didZoom = didZoom === 'none' ? this.childDocs[prevSelected].presMovement : didZoom;
+        let didZoom = activeItem.presentation_movement;
+        for (; prevSelected > 0 && this.childDocs[Math.max(0, prevSelected - 1)].presentation_groupWithUp; prevSelected--) {
+            didZoom = didZoom === 'none' ? this.childDocs[prevSelected].presentation_movement : didZoom;
         }
         if (activeItem && this.childDocs[this.itemIndex - 1] !== undefined) {
             // Case 2: There are no other frames so it should go to the previous slide
@@ -361,20 +361,20 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
         Doc.UnBrushAllDocs();
         if (index >= 0 && index < this.childDocs.length) {
             this.rootDoc._itemIndex = index;
-            if (from?.mediaStopTriggerList && this.layoutDoc.presStatus !== PresStatus.Edit) {
+            if (from?.mediaStopTriggerList && this.layoutDoc.presentation_status !== PresStatus.Edit) {
                 DocListCast(from.mediaStopTriggerList).forEach(this.stopTempMedia);
             }
-            if (from?.mediaStop === 'auto' && this.layoutDoc.presStatus !== PresStatus.Edit) {
-                this.stopTempMedia(from.presentationTargetDoc);
+            if (from?.mediaStop === 'auto' && this.layoutDoc.presentation_status !== PresStatus.Edit) {
+                this.stopTempMedia(from.presentation_targetDoc);
             }
             // If next slide is audio / video 'Play automatically' then the next slide should be played
-            if (this.layoutDoc.presStatus !== PresStatus.Edit && (this.targetDoc.type === DocumentType.AUDIO || this.targetDoc.type === DocumentType.VID) && this.activeItem.mediaStart === 'auto') {
+            if (this.layoutDoc.presentation_status !== PresStatus.Edit && (this.targetDoc.type === DocumentType.AUDIO || this.targetDoc.type === DocumentType.VID) && this.activeItem.mediaStart === 'auto') {
                 this.startTempMedia(this.targetDoc, this.activeItem);
             }
             if (!group) this.clearSelectedArray();
             this.childDocs[index] && this.addToSelectedArray(this.childDocs[index]); //Update selected array
             this.turnOffEdit();
-            this.navigateToActiveItem(finished); //Handles movement to element only when presTrail is list
+            this.navigateToActiveItem(finished); //Handles movement to element only when presentationTrail is list
             this.doHideBeforeAfter(); //Handles hide after/before
         }
     });
@@ -398,33 +398,33 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
     @action
     playAnnotation = (anno: AudioField) => {};
     @action
-    static restoreTargetDocView(bestTargetView: Opt<DocumentView>, activeItem: Doc, transTime: number, pinDocLayout: boolean = BoolCast(activeItem.presPinLayout), pinDataTypes?: pinDataTypes, targetDoc?: Doc) {
+    static restoreTargetDocView(bestTargetView: Opt<DocumentView>, activeItem: Doc, transTime: number, pinDocLayout: boolean = BoolCast(activeItem.config_pinLayout), pinDataTypes?: pinDataTypes, targetDoc?: Doc) {
         const bestTarget = bestTargetView?.rootDoc ?? (targetDoc?.layout_unrendered ? DocCast(targetDoc?.annotationOn) : targetDoc);
         if (!bestTarget) return;
         let changed = false;
         if (pinDocLayout) {
             if (
-                bestTarget.x !== NumCast(activeItem.presX, NumCast(bestTarget.x)) ||
-                bestTarget.y !== NumCast(activeItem.presY, NumCast(bestTarget.y)) ||
-                bestTarget.rotation !== NumCast(activeItem.presRotation, NumCast(bestTarget.rotation)) ||
-                bestTarget.width !== NumCast(activeItem.presWidth, NumCast(bestTarget.width)) ||
-                bestTarget.height !== NumCast(activeItem.presHeight, NumCast(bestTarget.height))
+                bestTarget.x !== NumCast(activeItem.config_x, NumCast(bestTarget.x)) ||
+                bestTarget.y !== NumCast(activeItem.config_y, NumCast(bestTarget.y)) ||
+                bestTarget.rotation !== NumCast(activeItem.config_rotation, NumCast(bestTarget.rotation)) ||
+                bestTarget.width !== NumCast(activeItem.config_width, NumCast(bestTarget.width)) ||
+                bestTarget.height !== NumCast(activeItem.config_height, NumCast(bestTarget.height))
             ) {
                 bestTarget._dataTransition = `all ${transTime}ms`;
-                bestTarget.x = NumCast(activeItem.presX, NumCast(bestTarget.x));
-                bestTarget.y = NumCast(activeItem.presY, NumCast(bestTarget.y));
-                bestTarget.rotation = NumCast(activeItem.presRotation, NumCast(bestTarget.rotation));
-                bestTarget.width = NumCast(activeItem.presWidth, NumCast(bestTarget.width));
-                bestTarget.height = NumCast(activeItem.presHeight, NumCast(bestTarget.height));
+                bestTarget.x = NumCast(activeItem.config_x, NumCast(bestTarget.x));
+                bestTarget.y = NumCast(activeItem.config_y, NumCast(bestTarget.y));
+                bestTarget.rotation = NumCast(activeItem.config_rotation, NumCast(bestTarget.rotation));
+                bestTarget.width = NumCast(activeItem.config_width, NumCast(bestTarget.width));
+                bestTarget.height = NumCast(activeItem.config_height, NumCast(bestTarget.height));
                 setTimeout(() => (bestTarget._dataTransition = undefined), transTime + 10);
                 changed = true;
             }
         }
 
-        const activeFrame = activeItem.presActiveFrame ?? activeItem.presCurrentFrame;
+        const activeFrame = activeItem.config_activeFrame ?? activeItem.config_currentFrame;
         if (activeFrame !== undefined) {
-            const transTime = NumCast(activeItem.presTransition, 500);
-            const acontext = activeItem.presActiveFrame !== undefined ? DocCast(DocCast(activeItem.presentationTargetDoc).embedContainer) : DocCast(activeItem.presentationTargetDoc);
+            const transTime = NumCast(activeItem.presentation_transition, 500);
+            const acontext = activeItem.config_activeFrame !== undefined ? DocCast(DocCast(activeItem.presentation_targetDoc).embedContainer) : DocCast(activeItem.presentation_targetDoc);
             const context = DocCast(acontext)?.annotationOn ? DocCast(DocCast(acontext).annotationOn) : acontext;
             if (context) {
                 const ffview = DocumentManager.Instance.getFirstDocumentView(context)?.props.CollectionFreeFormDocumentView?.().props.CollectionFreeFormView;
@@ -434,73 +434,73 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                 }
             }
         }
-        if ((pinDataTypes?.dataview && activeItem.presData !== undefined) || (!pinDataTypes && activeItem.presData !== undefined)) {
+        if ((pinDataTypes?.dataview && activeItem.config_data !== undefined) || (!pinDataTypes && activeItem.config_data !== undefined)) {
             bestTarget._dataTransition = `all ${transTime}ms`;
             const fkey = Doc.LayoutFieldKey(bestTarget);
             const setData = bestTargetView?.ComponentView?.setData;
-            if (setData) setData(activeItem.presData);
-            else Doc.GetProto(bestTarget)[fkey] = activeItem.presData instanceof ObjectField ? activeItem.presData[Copy]() : activeItem.presData;
-            bestTarget[fkey + '_usePath'] = activeItem.presUsePath;
+            if (setData) setData(activeItem.config_data);
+            else Doc.GetProto(bestTarget)[fkey] = activeItem.config_data instanceof ObjectField ? activeItem.config_data[Copy]() : activeItem.config_data;
+            bestTarget[fkey + '_usePath'] = activeItem.config_usePath;
             setTimeout(() => (bestTarget._dataTransition = undefined), transTime + 10);
         }
-        if (pinDataTypes?.datarange || (!pinDataTypes && activeItem.presXRange !== undefined)) {
-            if (bestTarget.xRange !== activeItem.presXRange) {
-                bestTarget.xRange = (activeItem.presXRange as ObjectField)?.[Copy]();
+        if (pinDataTypes?.datarange || (!pinDataTypes && activeItem.config_xRange !== undefined)) {
+            if (bestTarget.xRange !== activeItem.config_xRange) {
+                bestTarget.xRange = (activeItem.config_xRange as ObjectField)?.[Copy]();
                 changed = true;
             }
-            if (bestTarget.yRange !== activeItem.presYRange) {
-                bestTarget.yRange = (activeItem.presYRange as ObjectField)?.[Copy]();
+            if (bestTarget.yRange !== activeItem.config_yRange) {
+                bestTarget.yRange = (activeItem.config_yRange as ObjectField)?.[Copy]();
                 changed = true;
             }
         }
-        if (pinDataTypes?.clippable || (!pinDataTypes && activeItem.presClipWidth !== undefined)) {
+        if (pinDataTypes?.clippable || (!pinDataTypes && activeItem.config_clipWidth !== undefined)) {
             const fkey = '_' + Doc.LayoutFieldKey(bestTarget);
-            if (bestTarget[fkey + '_clipWidth'] !== activeItem.presClipWidth) {
-                bestTarget[fkey + '_clipWidth'] = activeItem.presClipWidth;
+            if (bestTarget[fkey + '_clipWidth'] !== activeItem.config_clipWidth) {
+                bestTarget[fkey + '_clipWidth'] = activeItem.config_clipWidth;
                 changed = true;
             }
         }
-        if (pinDataTypes?.temporal || (!pinDataTypes && activeItem.presStartTime !== undefined)) {
-            if (bestTarget._layout_currentTimecode !== activeItem.presStartTime) {
-                bestTarget._layout_currentTimecode = activeItem.presStartTime;
+        if (pinDataTypes?.temporal || (!pinDataTypes && activeItem.config_clipStart !== undefined)) {
+            if (bestTarget._layout_currentTimecode !== activeItem.config_clipStart) {
+                bestTarget._layout_currentTimecode = activeItem.config_clipStart;
                 changed = true;
             }
         }
-        if (pinDataTypes?.inkable || (!pinDataTypes && (activeItem.presFillColor !== undefined || activeItem.color !== undefined))) {
-            if (bestTarget.fillColor !== activeItem.presFillColor) {
-                Doc.GetProto(bestTarget).fillColor = activeItem.presFillColor;
+        if (pinDataTypes?.inkable || (!pinDataTypes && (activeItem.config_fillColor !== undefined || activeItem.color !== undefined))) {
+            if (bestTarget.fillColor !== activeItem.config_fillColor) {
+                Doc.GetProto(bestTarget).fillColor = activeItem.config_fillColor;
                 changed = true;
             }
-            if (bestTarget.color !== activeItem.presColor) {
-                Doc.GetProto(bestTarget).color = activeItem.presColor;
+            if (bestTarget.color !== activeItem.config_color) {
+                Doc.GetProto(bestTarget).color = activeItem.config_color;
                 changed = true;
             }
             if (bestTarget.width !== activeItem.width) {
-                bestTarget._width = NumCast(activeItem.presWidth, NumCast(bestTarget.width));
+                bestTarget._width = NumCast(activeItem.config_width, NumCast(bestTarget.width));
                 changed = true;
             }
             if (bestTarget.height !== activeItem.height) {
-                bestTarget._height = NumCast(activeItem.presHeight, NumCast(bestTarget.height));
+                bestTarget._height = NumCast(activeItem.config_height, NumCast(bestTarget.height));
                 changed = true;
             }
         }
-        if ((pinDataTypes?.type_collection && activeItem.presViewType !== undefined) || (!pinDataTypes && activeItem.presViewType !== undefined)) {
-            if (bestTarget._type_collection !== activeItem.presViewType) {
-                bestTarget._type_collection = activeItem.presViewType;
+        if ((pinDataTypes?.type_collection && activeItem.config_viewType !== undefined) || (!pinDataTypes && activeItem.config_viewType !== undefined)) {
+            if (bestTarget._type_collection !== activeItem.config_viewType) {
+                bestTarget._type_collection = activeItem.config_viewType;
                 changed = true;
             }
         }
 
-        if ((pinDataTypes?.filters && activeItem.presDocFilters !== undefined) || (!pinDataTypes && activeItem.presDocFilters !== undefined)) {
-            if (bestTarget.childFilters !== activeItem.presDocFilters) {
-                bestTarget.childFilters = ObjectField.MakeCopy(activeItem.presDocFilters as ObjectField) || new List<string>([]);
+        if ((pinDataTypes?.filters && activeItem.config_docFilters !== undefined) || (!pinDataTypes && activeItem.config_docFilters !== undefined)) {
+            if (bestTarget.childFilters !== activeItem.config_docFilters) {
+                bestTarget.childFilters = ObjectField.MakeCopy(activeItem.config_docFilters as ObjectField) || new List<string>([]);
                 changed = true;
             }
         }
 
-        if ((pinDataTypes?.pivot && activeItem.presPivotField !== undefined) || (!pinDataTypes && activeItem.presPivotField !== undefined)) {
-            if (bestTarget.pivotField !== activeItem.presPivotField) {
-                bestTarget.pivotField = activeItem.presPivotField;
+        if ((pinDataTypes?.pivot && activeItem.config_pivotField !== undefined) || (!pinDataTypes && activeItem.config_pivotField !== undefined)) {
+            if (bestTarget.pivotField !== activeItem.config_pivotField) {
+                bestTarget.pivotField = activeItem.config_pivotField;
                 bestTarget._prevFilterIndex = 1; // need to revisit this...see CollectionTimeView
                 changed = true;
             }
@@ -509,21 +509,21 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
             changed = true;
         }
 
-        if (pinDataTypes?.scrollable || (!pinDataTypes && activeItem.presViewScroll !== undefined)) {
-            if (bestTarget._layout_scrollTop !== activeItem.presViewScroll) {
-                bestTarget._layout_scrollTop = activeItem.presViewScroll;
+        if (pinDataTypes?.scrollable || (!pinDataTypes && activeItem.config_scrollTop !== undefined)) {
+            if (bestTarget._layout_scrollTop !== activeItem.config_scrollTop) {
+                bestTarget._layout_scrollTop = activeItem.config_scrollTop;
                 changed = true;
-                const contentBounds = Cast(activeItem.presPinViewBounds, listSpec('number'));
+                const contentBounds = Cast(activeItem.config_viewBounds, listSpec('number'));
                 if (contentBounds) {
                     const dv = DocumentManager.Instance.getDocumentView(bestTarget)?.ComponentView;
-                    dv?.brushView?.({ panX: (contentBounds[0] + contentBounds[2]) / 2, panY: (contentBounds[1] + contentBounds[3]) / 2, width: contentBounds[2] - contentBounds[0], height: contentBounds[3] - contentBounds[1] });
+                    dv?.brushView?.({ panX: (contentBounds[0] + contentBounds[2]) / 2, panY: (contentBounds[1] + contentBounds[3]) / 2, width: contentBounds[2] - contentBounds[0], height: contentBounds[3] - contentBounds[1] }, transTime);
                 }
             }
         }
-        if (pinDataTypes?.dataannos || (!pinDataTypes && activeItem.presAnnotations !== undefined)) {
+        if (pinDataTypes?.dataannos || (!pinDataTypes && activeItem.config_annotations !== undefined)) {
             const fkey = Doc.LayoutFieldKey(bestTarget);
             const oldItems = DocListCast(bestTarget[fkey + '_annotations']).filter(doc => doc.layout_unrendered);
-            const newItems = DocListCast(activeItem.presAnnotations).map(doc => {
+            const newItems = DocListCast(activeItem.config_annotations).map(doc => {
                 doc.hidden = false;
                 return doc;
             });
@@ -536,11 +536,11 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
             const newList = new List<Doc>([...oldItems, ...hiddenItems, ...newItems]);
             Doc.GetProto(bestTarget)[fkey + '_annotations'] = newList;
         }
-        if (pinDataTypes?.poslayoutview || (!pinDataTypes && activeItem.presPinLayoutData !== undefined)) {
+        if (pinDataTypes?.poslayoutview || (!pinDataTypes && activeItem.config_pinLayoutData !== undefined)) {
             changed = true;
             const layoutField = Doc.LayoutFieldKey(bestTarget);
             const transitioned = new Set<Doc>();
-            StrListCast(activeItem.presPinLayoutData)
+            StrListCast(activeItem.config_pinLayoutData)
                 .map(str => JSON.parse(str) as { id: string; x: number; y: number; back: string; fill: string; w: number; h: number; data: string; text: string })
                 .forEach(async data => {
                     const doc = DocCast(DocServer.GetCachedRefField(data.id));
@@ -562,8 +562,8 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                 });
             setTimeout(() => Array.from(transitioned).forEach(action(doc => (doc._dataTransition = undefined))), transTime + 10);
         }
-        if ((pinDataTypes?.pannable || (!pinDataTypes && (activeItem.presPinViewBounds !== undefined || activeItem.presPanX !== undefined || activeItem.presViewScale !== undefined))) && !bestTarget._isGroup) {
-            const contentBounds = Cast(activeItem.presPinViewBounds, listSpec('number'));
+        if ((pinDataTypes?.pannable || (!pinDataTypes && (activeItem.config_viewBounds !== undefined || activeItem.config_panX !== undefined || activeItem.config_viewScale !== undefined))) && !bestTarget._isGroup) {
+            const contentBounds = Cast(activeItem.config_viewBounds, listSpec('number'));
             if (contentBounds) {
                 const viewport = { panX: (contentBounds[0] + contentBounds[2]) / 2, panY: (contentBounds[1] + contentBounds[3]) / 2, width: contentBounds[2] - contentBounds[0], height: contentBounds[3] - contentBounds[1] };
                 bestTarget._freeform_panX = viewport.panX;
@@ -572,14 +572,14 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                 if (dv) {
                     changed = true;
                     const computedScale = NumCast(activeItem.presZoom, 1) * Math.min(dv.props.PanelWidth() / viewport.width, dv.props.PanelHeight() / viewport.height);
-                    activeItem.presMovement === PresMovement.Zoom && (bestTarget._freeform_scale = computedScale);
-                    dv.ComponentView?.brushView?.(viewport);
+                    activeItem.presentation_movement === PresMovement.Zoom && (bestTarget._freeform_scale = computedScale);
+                    dv.ComponentView?.brushView?.(viewport, transTime);
                 }
             } else {
-                if (bestTarget._freeform_panX !== activeItem.presPanX || bestTarget._freeform_panY !== activeItem.presPanY || bestTarget._freeform_scale !== activeItem.presViewScale) {
-                    bestTarget._freeform_panX = activeItem.presPanX ?? bestTarget._freeform_panX;
-                    bestTarget._freeform_panY = activeItem.presPanY ?? bestTarget._freeform_panY;
-                    bestTarget._freeform_scale = activeItem.presViewScale ?? bestTarget._freeform_scale;
+                if (bestTarget._freeform_panX !== activeItem.config_panX || bestTarget._freeform_panY !== activeItem.config_panY || bestTarget._freeform_scale !== activeItem.config_viewScale) {
+                    bestTarget._freeform_panX = activeItem.config_panX ?? bestTarget._freeform_panX;
+                    bestTarget._freeform_panY = activeItem.config_panY ?? bestTarget._freeform_panY;
+                    bestTarget._freeform_scale = activeItem.config_viewScale ?? bestTarget._freeform_scale;
                     changed = true;
                 }
             }
@@ -594,17 +594,19 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
     /// target doc when navigating to it.
     @action
     static pinDocView(pinDoc: Doc, pinProps: PinProps, targetDoc: Doc) {
+        pinDoc.presentation = true;
+        pinDoc.config = '';
         if (pinProps.pinDocLayout) {
-            pinDoc.presPinLayout = true;
-            pinDoc.presX = NumCast(targetDoc.x);
-            pinDoc.presY = NumCast(targetDoc.y);
-            pinDoc.presRotation = NumCast(targetDoc.rotation);
-            pinDoc.presWidth = NumCast(targetDoc.width);
-            pinDoc.presHeight = NumCast(targetDoc.height);
+            pinDoc.config_pinLayout = true;
+            pinDoc.config_x = NumCast(targetDoc.x);
+            pinDoc.config_y = NumCast(targetDoc.y);
+            pinDoc.config_rotation = NumCast(targetDoc.rotation);
+            pinDoc.config_width = NumCast(targetDoc.width);
+            pinDoc.config_height = NumCast(targetDoc.height);
         }
         if (pinProps.pinAudioPlay) pinDoc.presPlayAudio = true;
         if (pinProps.pinData) {
-            pinDoc.presPinData =
+            pinDoc.config_pinData =
                 pinProps.pinData.scrollable ||
                 pinProps.pinData.temporal ||
                 pinProps.pinData.pannable ||
@@ -616,30 +618,30 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                 pinProps?.activeFrame !== undefined;
             const fkey = Doc.LayoutFieldKey(targetDoc);
             if (pinProps.pinData.dataview) {
-                pinDoc.presUsePath = targetDoc[fkey + '_usePath'];
-                pinDoc.presData = targetDoc[fkey] instanceof ObjectField ? (targetDoc[fkey] as ObjectField)[Copy]() : targetDoc.data;
+                pinDoc.config_usePath = targetDoc[fkey + '_usePath'];
+                pinDoc.config_data = targetDoc[fkey] instanceof ObjectField ? (targetDoc[fkey] as ObjectField)[Copy]() : targetDoc.data;
             }
             if (pinProps.pinData.dataannos) {
                 const fkey = Doc.LayoutFieldKey(targetDoc);
-                pinDoc.presAnnotations = new List<Doc>(DocListCast(Doc.GetProto(targetDoc)[fkey + '_annotations']).filter(doc => !doc.layout_unrendered));
+                pinDoc.config_annotations = new List<Doc>(DocListCast(Doc.GetProto(targetDoc)[fkey + '_annotations']).filter(doc => !doc.layout_unrendered));
             }
             if (pinProps.pinData.inkable) {
-                pinDoc.presFillColor = targetDoc.fillColor;
-                pinDoc.presColor = targetDoc.color;
-                pinDoc.presWidth = targetDoc._width;
-                pinDoc.presHeight = targetDoc._height;
+                pinDoc.config_fillColor = targetDoc.fillColor;
+                pinDoc.config_color = targetDoc.color;
+                pinDoc.config_width = targetDoc._width;
+                pinDoc.config_height = targetDoc._height;
             }
-            if (pinProps.pinData.scrollable) pinDoc.presViewScroll = targetDoc._layout_scrollTop;
+            if (pinProps.pinData.scrollable) pinDoc.config_scrollTop = targetDoc._layout_scrollTop;
             if (pinProps.pinData.clippable) {
                 const fkey = Doc.LayoutFieldKey(targetDoc);
-                pinDoc.presClipWidth = targetDoc[fkey + '_clipWidth'];
+                pinDoc.config_clipWidth = targetDoc[fkey + '_clipWidth'];
             }
             if (pinProps.pinData.datarange) {
-                pinDoc.presXRange = undefined; //targetDoc?.xrange;
-                pinDoc.presYRange = undefined; //targetDoc?.yrange;
+                pinDoc.config_xRange = undefined; //targetDoc?.xrange;
+                pinDoc.config_yRange = undefined; //targetDoc?.yrange;
             }
             if (pinProps.pinData.poslayoutview)
-                pinDoc.presPinLayoutData = new List<string>(
+                pinDoc.config_pinLayoutData = new List<string>(
                     DocListCast(targetDoc[fkey] as ObjectField).map(d =>
                         JSON.stringify({
                             id: d[Id],
@@ -654,28 +656,28 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                         })
                     )
                 );
-            if (pinProps.pinData.type_collection) pinDoc.presViewType = targetDoc._type_collection;
-            if (pinProps.pinData.filters) pinDoc.presDocFilters = ObjectField.MakeCopy(targetDoc.childFilters as ObjectField);
-            if (pinProps.pinData.pivot) pinDoc.presPivotField = targetDoc._pivotField;
+            if (pinProps.pinData.type_collection) pinDoc.config_viewType = targetDoc._type_collection;
+            if (pinProps.pinData.filters) pinDoc.config_docFilters = ObjectField.MakeCopy(targetDoc.childFilters as ObjectField);
+            if (pinProps.pinData.pivot) pinDoc.config_pivotField = targetDoc._pivotField;
             if (pinProps.pinData.pannable) {
-                pinDoc.presPanX = NumCast(targetDoc._freeform_panX);
-                pinDoc.presPanY = NumCast(targetDoc._freeform_panY);
-                pinDoc.presViewScale = NumCast(targetDoc._freeform_scale, 1);
+                pinDoc.config_panX = NumCast(targetDoc._freeform_panX);
+                pinDoc.config_panY = NumCast(targetDoc._freeform_panY);
+                pinDoc.config_viewScale = NumCast(targetDoc._freeform_scale, 1);
             }
             if (pinProps.pinData.temporal) {
-                pinDoc.presStartTime = targetDoc._layout_currentTimecode;
-                const duration = NumCast(pinDoc[`${Doc.LayoutFieldKey(pinDoc)}_duration`], NumCast(targetDoc.presStartTime) + 0.1);
-                pinDoc.presEndTime = NumCast(targetDoc.clipEnd, duration);
+                pinDoc.config_clipStart = targetDoc._layout_currentTimecode;
+                const duration = NumCast(pinDoc[`${Doc.LayoutFieldKey(pinDoc)}_duration`], NumCast(targetDoc.config_clipStart) + 0.1);
+                pinDoc.config_clipEnd = NumCast(targetDoc.clipEnd, duration);
             }
         }
         if (pinProps?.pinViewport) {
             // If pinWithView option set then update scale and x / y props of slide
             const bounds = pinProps.pinViewport;
-            pinDoc.presPinView = true;
-            pinDoc.presViewScale = NumCast(targetDoc._freeform_scale, 1);
-            pinDoc.presPanX = bounds.left + bounds.width / 2;
-            pinDoc.presPanY = bounds.top + bounds.height / 2;
-            pinDoc.presPinViewBounds = new List<number>([bounds.left, bounds.top, bounds.left + bounds.width, bounds.top + bounds.height]);
+            pinDoc.config_pinView = true;
+            pinDoc.config_viewScale = NumCast(targetDoc._freeform_scale, 1);
+            pinDoc.config_panX = bounds.left + bounds.width / 2;
+            pinDoc.config_panY = bounds.top + bounds.height / 2;
+            pinDoc.config_viewBounds = new List<number>([bounds.left, bounds.top, bounds.left + bounds.width, bounds.top + bounds.height]);
         }
     }
     /**
@@ -712,23 +714,23 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
     };
 
     static NavigateToTarget(targetDoc: Doc, activeItem: Doc, finished?: () => void) {
-        if (activeItem.presMovement === PresMovement.None && targetDoc.type === DocumentType.SCRIPTING) {
+        if (activeItem.presentation_movement === PresMovement.None && targetDoc.type === DocumentType.SCRIPTING) {
             (DocumentManager.Instance.getFirstDocumentView(targetDoc)?.ComponentView as ScriptingBox)?.onRun?.();
             return;
         }
-        const effect = activeItem.presEffect && activeItem.presEffect !== PresEffect.None ? activeItem.presEffect : undefined;
-        const presTime = NumCast(activeItem.presTransition, effect ? 750 : 500);
+        const effect = activeItem.presentation_effect && activeItem.presentation_effect !== PresEffect.None ? activeItem.presentation_effect : undefined;
+        const presTime = NumCast(activeItem.presentation_transition, effect ? 750 : 500);
         const options: DocFocusOptions = {
-            willPan: activeItem.presMovement !== PresMovement.None,
-            willZoomCentered: activeItem.presMovement === PresMovement.Zoom || activeItem.presMovement === PresMovement.Jump || activeItem.presMovement === PresMovement.Center,
-            zoomScale: activeItem.presMovement === PresMovement.Center ? 0 : NumCast(activeItem.presZoom, 1),
-            zoomTime: activeItem.presMovement === PresMovement.Jump ? 0 : Math.min(Math.max(effect ? 750 : 500, (effect ? 0.2 : 1) * presTime), presTime),
+            willPan: activeItem.presentation_movement !== PresMovement.None,
+            willZoomCentered: activeItem.presentation_movement === PresMovement.Zoom || activeItem.presentation_movement === PresMovement.Jump || activeItem.presentation_movement === PresMovement.Center,
+            zoomScale: activeItem.presentation_movement === PresMovement.Center ? 0 : NumCast(activeItem.presZoom, 1),
+            zoomTime: activeItem.presentation_movement === PresMovement.Jump ? 0 : Math.min(Math.max(effect ? 750 : 500, (effect ? 0.2 : 1) * presTime), presTime),
             effect: activeItem,
             noSelect: true,
             openLocation: OpenWhere.addLeft,
             anchorDoc: activeItem,
             easeFunc: StrCast(activeItem.presEaseFunc, 'ease') as any,
-            zoomTextSelections: BoolCast(activeItem.presZoomText),
+            zoomTextSelections: BoolCast(activeItem.presentation_zoomText),
             playAudio: BoolCast(activeItem.presPlayAudio),
         };
         if (activeItem.presOpenInLightbox) {
@@ -738,7 +740,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
             }
         }
         if (targetDoc) {
-            if (activeItem.presentationTargetDoc instanceof Doc) activeItem.presentationTargetDoc[Animation] = undefined;
+            if (activeItem.presentation_targetDoc instanceof Doc) activeItem.presentation_targetDoc[Animation] = undefined;
 
             DocumentManager.Instance.AddViewRenderedCb(LightboxView.LightboxDoc, dv => {
                 // if target or the doc it annotates is not in the lightbox, then close the lightbox
@@ -761,16 +763,16 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
             const tagDoc = PresBox.targetRenderedDoc(curDoc);
             const itemIndexes: number[] = this.getAllIndexes(this.tagDocs, tagDoc);
             let opacity: Opt<number> = index === this.itemIndex ? 1 : undefined;
-            if (curDoc.presHide) {
+            if (curDoc.presentation_hide) {
                 if (index !== this.itemIndex) {
                     opacity = 1;
                 }
             }
             const hidingIndBef = itemIndexes.find(item => item >= this.itemIndex) ?? itemIndexes.slice().reverse().lastElement();
-            if (curDoc.presHideBefore && index === hidingIndBef) {
+            if (curDoc.presentation_hideBefore && index === hidingIndBef) {
                 if (index > this.itemIndex) {
                     opacity = 0;
-                } else if (index === this.itemIndex || !curDoc.presHideAfter) {
+                } else if (index === this.itemIndex || !curDoc.presentation_hideAfter) {
                     opacity = 1;
                     setTimeout(() => (tagDoc._dataTransition = undefined), 1000);
                 }
@@ -780,15 +782,15 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                     .slice()
                     .reverse()
                     .find(item => item <= this.itemIndex) ?? itemIndexes.lastElement();
-            if (curDoc.presHideAfter && index === hidingIndAft) {
+            if (curDoc.presentation_hideAfter && index === hidingIndAft) {
                 if (index < this.itemIndex) {
                     opacity = 0;
-                } else if (index === this.itemIndex || !curDoc.presHideBefore) {
+                } else if (index === this.itemIndex || !curDoc.presentation_hideBefore) {
                     opacity = 1;
                 }
             }
             const hidingInd = itemIndexes.find(item => item === this.itemIndex);
-            if (curDoc.presHide && index === hidingInd) {
+            if (curDoc.presentation_hide && index === hidingInd) {
                 if (index === this.itemIndex) {
                     opacity = 0;
                 }
@@ -846,9 +848,9 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
     // The function pauses the auto presentation
     @action
     pauseAutoPres = () => {
-        if (this.layoutDoc.presStatus === PresStatus.Autoplay) {
+        if (this.layoutDoc.presentation_status === PresStatus.Autoplay) {
             if (this._presTimer) clearTimeout(this._presTimer);
-            this.layoutDoc.presStatus = PresStatus.Manual;
+            this.layoutDoc.presentation_status = PresStatus.Manual;
             this.childDocs.forEach(this.stopTempMedia);
         }
     };
@@ -879,23 +881,23 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
         runInAction(() => (this._expandBoolean = !this._expandBoolean));
         this.rootDoc.expandBoolean = this._expandBoolean;
         this.childDocs.forEach(doc => {
-            doc.presExpandInlineButton = this._expandBoolean;
+            doc.presentation_expandInlineButton = this._expandBoolean;
         });
     };
 
     initializePresState = (startIndex: number) => {
         this.childDocs.forEach((doc, index) => {
             const tagDoc = PresBox.targetRenderedDoc(doc);
-            if (doc.presHideBefore && index > startIndex) tagDoc.opacity = 0;
-            if (doc.presHideAfter && index < startIndex) tagDoc.opacity = 0;
-            if (doc.presIndexed !== undefined && index >= startIndex) {
-                const startInd = NumCast(doc.presIndexedStart);
+            if (doc.presentation_hideBefore && index > startIndex) tagDoc.opacity = 0;
+            if (doc.presentation_hideAfter && index < startIndex) tagDoc.opacity = 0;
+            if (doc.presentation_indexed !== undefined && index >= startIndex) {
+                const startInd = NumCast(doc.presentation_indexedStart);
                 this.progressivizedItems(doc)
                     ?.slice(startInd)
                     .forEach(indexedDoc => (indexedDoc.opacity = 0));
-                doc.presIndexed = Math.min(this.progressivizedItems(doc)?.length ?? 0, startInd);
+                doc.presentation_indexed = Math.min(this.progressivizedItems(doc)?.length ?? 0, startInd);
             }
-            // if (doc.presHide && this.childDocs.indexOf(doc) === startIndex)  tagDoc.opacity = 0;
+            // if (doc.presentation_hide && this.childDocs.indexOf(doc) === startIndex)  tagDoc.opacity = 0;
         });
     };
 
@@ -909,13 +911,13 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
         PresBox.Instance = this;
         clearTimeout(this._presTimer);
         if (this.childDocs.length) {
-            this.layoutDoc.presStatus = PresStatus.Autoplay;
+            this.layoutDoc.presentation_status = PresStatus.Autoplay;
             this.initializePresState(startIndex);
             const func = () => {
-                const delay = NumCast(this.activeItem.presDuration, this.activeItem.type === DocumentType.SCRIPTING ? 0 : 2500) + NumCast(this.activeItem.presTransition);
+                const delay = NumCast(this.activeItem.presentation_duration, this.activeItem.type === DocumentType.SCRIPTING ? 0 : 2500) + NumCast(this.activeItem.presentation_transition);
                 this._presTimer = setTimeout(() => {
-                    if (!this.next()) this.layoutDoc.presStatus = this._exitTrail?.() ?? PresStatus.Manual;
-                    this.layoutDoc.presStatus === PresStatus.Autoplay && func();
+                    if (!this.next()) this.layoutDoc.presentation_status = this._exitTrail?.() ?? PresStatus.Manual;
+                    this.layoutDoc.presentation_status === PresStatus.Autoplay && func();
                 }, delay);
             };
             this.gotoDocument(startIndex, this.activeItem, undefined, func);
@@ -949,7 +951,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
         doc._width = PresBox.minimizedWidth;
         Doc.AddToMyOverlay(doc);
         PresBox.Instance?.initializePresState(PresBox.Instance.itemIndex);
-        return (doc.presStatus = PresStatus.Manual);
+        return (doc.presentation_status = PresStatus.Manual);
     }
 
     /**
@@ -993,34 +995,34 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
     });
 
     movementName = action((activeItem: Doc) => {
-        if (![PresMovement.Zoom, PresMovement.Pan, PresMovement.Center, PresMovement.Jump, PresMovement.None].includes(StrCast(activeItem.presMovement) as any)) {
+        if (![PresMovement.Zoom, PresMovement.Pan, PresMovement.Center, PresMovement.Jump, PresMovement.None].includes(StrCast(activeItem.presentation_movement) as any)) {
             return PresMovement.Zoom;
         }
-        return StrCast(activeItem.presMovement);
+        return StrCast(activeItem.presentation_movement);
     });
 
     whenChildContentsActiveChanged = action((isActive: boolean) => this.props.whenChildContentsActiveChanged((this._isChildActive = isActive)));
     // For dragging documents into the presentation trail
     addDocumentFilter = (docs: Doc[]) => {
         docs.forEach((doc, i) => {
-            if (doc.presentationTargetDoc) return true;
+            if (doc.presentation_targetDoc) return true;
             if (doc.type === DocumentType.LABEL) {
                 const audio = Cast(doc.annotationOn, Doc, null);
                 if (audio) {
                     audio.mediaStart = 'manual';
                     audio.mediaStop = 'manual';
-                    audio.presStartTime = NumCast(doc._timecodeToShow /* audioStart */, NumCast(doc._timecodeToShow /* videoStart */));
-                    audio.presEndTime = NumCast(doc._timecodeToHide /* audioEnd */, NumCast(doc._timecodeToHide /* videoEnd */));
-                    audio.presDuration = audio.presStartTime - audio.presEndTime;
+                    audio.config_clipStart = NumCast(doc._timecodeToShow /* audioStart */, NumCast(doc._timecodeToShow /* videoStart */));
+                    audio.config_clipEnd = NumCast(doc._timecodeToHide /* audioEnd */, NumCast(doc._timecodeToHide /* videoEnd */));
+                    audio.presentation_duration = audio.config_clipStart - audio.config_clipEnd;
                     TabDocView.PinDoc(audio, { audioRange: true });
                     setTimeout(() => this.removeDocument(doc), 0);
                     return false;
                 }
             } else {
-                if (!doc.presentationTargetDoc) doc.title = doc.title + ' - Slide';
-                doc.presentationTargetDoc = doc.createdFrom; // dropped document will be a new embedding of an embedded document somewhere else.
-                doc.presMovement = PresMovement.Zoom;
-                if (this._expandBoolean) doc.presExpandInlineButton = true;
+                if (!doc.presentation_targetDoc) doc.title = doc.title + ' - Slide';
+                doc.presentation_targetDoc = doc.createdFrom; // dropped document will be a new embedding of an embedded document somewhere else.
+                doc.presentation_movement = PresMovement.Zoom;
+                if (this._expandBoolean) doc.presentation_expandInlineButton = true;
             }
         });
         return true;
@@ -1040,7 +1042,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
     @computed get listOfSelected() {
         return Array.from(this.selectedArray).map((doc: Doc, index: any) => {
             const curDoc = Cast(doc, Doc, null);
-            const tagDoc = Cast(curDoc.presentationTargetDoc, Doc, null);
+            const tagDoc = Cast(curDoc.presentation_targetDoc, Doc, null);
             if (curDoc && curDoc === this.activeItem)
                 return (
                     <div key={index} className="selectedList-items">
@@ -1146,7 +1148,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
         if (anchorNode && anchorNode.className?.includes('lm_title')) return;
         switch (e.key) {
             case 'Backspace':
-                if (this.layoutDoc.presStatus === 'edit') {
+                if (this.layoutDoc.presentation_status === 'edit') {
                     undoBatch(
                         action(() => {
                             for (const doc of this.selectedArray) {
@@ -1163,11 +1165,11 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
             case 'Escape':
                 if (Doc.IsInMyOverlay(this.layoutDoc)) {
                     this.exitClicked();
-                } else if (this.layoutDoc.presStatus === PresStatus.Edit) {
+                } else if (this.layoutDoc.presentation_status === PresStatus.Edit) {
                     this.clearSelectedArray();
                     this._eleArray.length = this._dragArray.length = 0;
                 } else {
-                    this.layoutDoc.presStatus = PresStatus.Edit;
+                    this.layoutDoc.presentation_status = PresStatus.Edit;
                 }
                 if (this._presTimer) clearTimeout(this._presTimer);
                 handled = true;
@@ -1184,7 +1186,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                     this.next();
                     if (this._presTimer) {
                         clearTimeout(this._presTimer);
-                        this.layoutDoc.presStatus = PresStatus.Manual;
+                        this.layoutDoc.presentation_status = PresStatus.Manual;
                     }
                 }
                 handled = true;
@@ -1201,19 +1203,19 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                     this.back();
                     if (this._presTimer) {
                         clearTimeout(this._presTimer);
-                        this.layoutDoc.presStatus = PresStatus.Manual;
+                        this.layoutDoc.presentation_status = PresStatus.Manual;
                     }
                 }
                 handled = true;
                 break;
             case 'Spacebar':
             case ' ':
-                if (this.layoutDoc.presStatus === PresStatus.Manual) this.startOrPause(true);
-                else if (this.layoutDoc.presStatus === PresStatus.Autoplay) if (this._presTimer) clearTimeout(this._presTimer);
+                if (this.layoutDoc.presentation_status === PresStatus.Manual) this.startOrPause(true);
+                else if (this.layoutDoc.presentation_status === PresStatus.Autoplay) if (this._presTimer) clearTimeout(this._presTimer);
                 handled = true;
                 break;
             case 'a':
-                if ((e.metaKey || e.altKey) && this.layoutDoc.presStatus === 'edit') {
+                if ((e.metaKey || e.altKey) && this.layoutDoc.presentation_status === 'edit') {
                     this.clearSelectedArray();
                     this.childDocs.forEach(doc => this.addToSelectedArray(doc));
                     handled = true;
@@ -1236,9 +1238,9 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
         const presCollection = DocumentManager.GetContextPath(this.activeItem).reverse().lastElement();
         const dv = DocumentManager.Instance.getDocumentView(presCollection);
         this.childDocs
-            .filter(doc => Cast(doc.presentationTargetDoc, Doc, null))
+            .filter(doc => Cast(doc.presentation_targetDoc, Doc, null))
             .forEach((doc, index) => {
-                const tagDoc = Cast(doc.presentationTargetDoc, Doc, null);
+                const tagDoc = Cast(doc.presentation_targetDoc, Doc, null);
                 const srcContext = Cast(tagDoc.embedContainer, Doc, null);
                 const width = NumCast(tagDoc._width) / 10;
                 const height = Math.max(NumCast(tagDoc._height) / 10, 15);
@@ -1271,17 +1273,17 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                             </div>
                         );
                     }
-                } else if (doc.presPinView && presCollection === tagDoc && dv) {
+                } else if (doc.config_pinView && presCollection === tagDoc && dv) {
                     // Case B: Document is presPinView and is presCollection
-                    const scale: number = 1 / NumCast(doc.presViewScale);
+                    const scale: number = 1 / NumCast(doc.config_viewScale);
                     const height: number = dv.props.PanelHeight() * scale;
                     const width: number = dv.props.PanelWidth() * scale;
                     const indWidth = width / 10;
                     const indHeight = Math.max(height / 10, 15);
                     const indEdge = Math.max(indWidth, indHeight);
                     const indFontSize = indEdge * 0.8;
-                    const xLoc: number = NumCast(doc.presPanX) - width / 2;
-                    const yLoc: number = NumCast(doc.presPanY) - height / 2;
+                    const xLoc: number = NumCast(doc.config_panX) - width / 2;
+                    const yLoc: number = NumCast(doc.config_panY) - height / 2;
                     docs.push(tagDoc);
                     order.push(
                         <>
@@ -1307,15 +1309,15 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
     @computed get paths() {
         let pathPoints = '';
         this.childDocs.forEach((doc, index) => {
-            const tagDoc = Cast(doc.presentationTargetDoc, Doc, null);
+            const tagDoc = Cast(doc.presentation_targetDoc, Doc, null);
             if (tagDoc) {
                 const n1x = NumCast(tagDoc.x) + NumCast(tagDoc._width) / 2;
                 const n1y = NumCast(tagDoc.y) + NumCast(tagDoc._height) / 2;
                 if ((index = 0)) pathPoints = n1x + ',' + n1y;
                 else pathPoints = pathPoints + ' ' + n1x + ',' + n1y;
-            } else if (doc.presPinView) {
-                const n1x = NumCast(doc.presPanX);
-                const n1y = NumCast(doc.presPanY);
+            } else if (doc.config_pinView) {
+                const n1x = NumCast(doc.config_panX);
+                const n1y = NumCast(doc.config_panY);
                 if ((index = 0)) pathPoints = n1x + ',' + n1y;
                 else pathPoints = pathPoints + ' ' + n1x + ',' + n1y;
             }
@@ -1339,7 +1341,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
     }
     getPaths = (collection: Doc) => this.paths; // needs to be smarter and figure out the paths to draw for this specific collection.  or better yet, draw everything in an overlay layer instad of within a collection
 
-    // Converts seconds to ms and updates presTransition
+    // Converts seconds to ms and updates presentation_transition
     public static SetTransitionTime = (number: String, setter: (timeInMS: number) => void, change?: number) => {
         let timeInMS = Number(number) * 1000;
         if (change) timeInMS += change;
@@ -1350,10 +1352,10 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
 
     @undoBatch
     updateTransitionTime = (number: String, change?: number) => {
-        PresBox.SetTransitionTime(number, (timeInMS: number) => this.selectedArray.forEach(doc => (doc.presTransition = timeInMS)), change);
+        PresBox.SetTransitionTime(number, (timeInMS: number) => this.selectedArray.forEach(doc => (doc.presentation_transition = timeInMS)), change);
     };
 
-    // Converts seconds to ms and updates presTransition
+    // Converts seconds to ms and updates presentation_transition
     @undoBatch
     updateZoom = (number: String, change?: number) => {
         let scale = Number(number) / 100;
@@ -1364,7 +1366,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
     };
 
     /*
-     * Converts seconds to ms and updates presDuration
+     * Converts seconds to ms and updates presentation_duration
      */
     @undoBatch
     updateDurationTime = (number: String, change?: number) => {
@@ -1372,31 +1374,31 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
         if (change) timeInMS += change;
         if (timeInMS < 100) timeInMS = 100;
         if (timeInMS > 20000) timeInMS = 20000;
-        this.selectedArray.forEach(doc => (doc.presDuration = timeInMS));
+        this.selectedArray.forEach(doc => (doc.presentation_duration = timeInMS));
     };
 
     @undoBatch
-    updateMovement = action((movement: PresMovement, all?: boolean) => (all ? this.childDocs : this.selectedArray).forEach(doc => (doc.presMovement = movement)));
+    updateMovement = action((movement: PresMovement, all?: boolean) => (all ? this.childDocs : this.selectedArray).forEach(doc => (doc.presentation_movement = movement)));
 
     @undoBatch
     @action
     updateHideBefore = (activeItem: Doc) => {
-        activeItem.presHideBefore = !activeItem.presHideBefore;
-        this.selectedArray.forEach(doc => (doc.presHideBefore = activeItem.presHideBefore));
+        activeItem.presentation_hideBefore = !activeItem.presentation_hideBefore;
+        this.selectedArray.forEach(doc => (doc.presentation_hideBefore = activeItem.presentation_hideBefore));
     };
 
     @undoBatch
     @action
     updateHide = (activeItem: Doc) => {
-        activeItem.presHide = !activeItem.presHide;
-        this.selectedArray.forEach(doc => (doc.presHide = activeItem.presHide));
+        activeItem.presentation_hide = !activeItem.presentation_hide;
+        this.selectedArray.forEach(doc => (doc.presentation_hide = activeItem.presentation_hide));
     };
 
     @undoBatch
     @action
     updateHideAfter = (activeItem: Doc) => {
-        activeItem.presHideAfter = !activeItem.presHideAfter;
-        this.selectedArray.forEach(doc => (doc.presHideAfter = activeItem.presHideAfter));
+        activeItem.presentation_hideAfter = !activeItem.presentation_hideAfter;
+        this.selectedArray.forEach(doc => (doc.presentation_hideAfter = activeItem.presentation_hideAfter));
     };
 
     @undoBatch
@@ -1415,11 +1417,11 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
 
     @undoBatch
     @action
-    updateEffectDirection = (effect: PresEffectDirection, all?: boolean) => (all ? this.childDocs : this.selectedArray).forEach(doc => (doc.presEffectDirection = effect));
+    updateEffectDirection = (effect: PresEffectDirection, all?: boolean) => (all ? this.childDocs : this.selectedArray).forEach(doc => (doc.presentation_effectDirection = effect));
 
     @undoBatch
     @action
-    updateEffect = (effect: PresEffect, bullet: boolean, all?: boolean) => (all ? this.childDocs : this.selectedArray).forEach(doc => (bullet ? (doc.presBulletEffect = effect) : (doc.presEffect = effect)));
+    updateEffect = (effect: PresEffect, bullet: boolean, all?: boolean) => (all ? this.childDocs : this.selectedArray).forEach(doc => (bullet ? (doc.presBulletEffect = effect) : (doc.presentation_effect = effect)));
 
     static _sliderBatch: any;
     public static inputter = (min: string, step: string, max: string, value: number, active: boolean, change: (val: string) => void, hmargin?: number) => {
@@ -1449,16 +1451,16 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
     @undoBatch
     @action
     applyTo = (array: Doc[]) => {
-        this.updateMovement(this.activeItem.presMovement as PresMovement, true);
-        this.updateEffect(this.activeItem.presEffect as PresEffect, false, true);
+        this.updateMovement(this.activeItem.presentation_movement as PresMovement, true);
+        this.updateEffect(this.activeItem.presentation_effect as PresEffect, false, true);
         this.updateEffect(this.activeItem.presBulletEffect as PresEffect, true, true);
-        this.updateEffectDirection(this.activeItem.presEffectDirection as PresEffectDirection, true);
-        const { presTransition, presDuration, presHideBefore, presHideAfter } = this.activeItem;
+        this.updateEffectDirection(this.activeItem.presentation_effectDirection as PresEffectDirection, true);
+        const { presentation_transition, presentation_duration, presentation_hideBefore, presentation_hideAfter } = this.activeItem;
         array.forEach(curDoc => {
-            curDoc.presTransition = presTransition;
-            curDoc.presDuration = presDuration;
-            curDoc.presHideBefore = presHideBefore;
-            curDoc.presHideAfter = presHideAfter;
+            curDoc.presentation_transition = presentation_transition;
+            curDoc.presentation_duration = presentation_duration;
+            curDoc.presentation_hideBefore = presentation_hideBefore;
+            curDoc.presentation_hideAfter = presentation_hideAfter;
         });
     };
 
@@ -1466,24 +1468,24 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
         const activeItem = this.activeItem;
         if (activeItem && this.targetDoc) {
             const targetType = this.targetDoc.type;
-            let duration = activeItem.presDuration ? NumCast(activeItem.presDuration) / 1000 : 0;
+            let duration = activeItem.presentation_duration ? NumCast(activeItem.presentation_duration) / 1000 : 0;
             if (activeItem.type === DocumentType.AUDIO) duration = NumCast(activeItem.duration);
             return (
                 <div className="presBox-ribbon">
                     <div className="ribbon-doubleButton">
                         <Tooltip title={<div className="dash-tooltip">{'Hide before presented'}</div>}>
-                            <div className={`ribbon-toggle ${activeItem.presHideBefore ? 'active' : ''}`} onClick={() => this.updateHideBefore(activeItem)}>
+                            <div className={`ribbon-toggle ${activeItem.presentation_hideBefore ? 'active' : ''}`} onClick={() => this.updateHideBefore(activeItem)}>
                                 Hide before
                             </div>
                         </Tooltip>
                         <Tooltip title={<div className="dash-tooltip">{'Hide while presented'}</div>}>
-                            <div className={`ribbon-toggle ${activeItem.presHide ? 'active' : ''}`} onClick={() => this.updateHide(activeItem)}>
+                            <div className={`ribbon-toggle ${activeItem.presentation_hide ? 'active' : ''}`} onClick={() => this.updateHide(activeItem)}>
                                 Hide
                             </div>
                         </Tooltip>
 
                         <Tooltip title={<div className="dash-tooltip">{'Hide after presented'}</div>}>
-                            <div className={`ribbon-toggle ${activeItem.presHideAfter ? 'active' : ''}`} onClick={() => this.updateHideAfter(activeItem)}>
+                            <div className={`ribbon-toggle ${activeItem.presentation_hideAfter ? 'active' : ''}`} onClick={() => this.updateHideAfter(activeItem)}>
                                 Hide after
                             </div>
                         </Tooltip>
@@ -1532,7 +1534,10 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
         if (activeItem && this.targetDoc) {
             const effect = activeItem.presBulletEffect ? activeItem.presBulletEffect : PresMovement.None;
             const bulletEffect = (effect: PresEffect) => (
-                <div className={`presBox-dropdownOption ${activeItem.presEffect === effect || (effect === PresEffect.None && !activeItem.presEffect) ? 'active' : ''}`} onPointerDown={StopEvent} onClick={() => this.updateEffect(effect, true)}>
+                <div
+                    className={`presBox-dropdownOption ${activeItem.presentation_effect === effect || (effect === PresEffect.None && !activeItem.presentation_effect) ? 'active' : ''}`}
+                    onPointerDown={StopEvent}
+                    onClick={() => this.updateEffect(effect, true)}>
                     {effect}
                 </div>
             );
@@ -1545,25 +1550,31 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                             style={{ margin: 10 }}
                             type="checkbox"
                             onChange={() => {
-                                activeItem.presIndexed = activeItem.presIndexed === undefined ? 0 : undefined;
-                                activeItem.presHideBefore = activeItem.presIndexed !== undefined;
+                                activeItem.presentation_indexed = activeItem.presentation_indexed === undefined ? 0 : undefined;
+                                activeItem.presentation_hideBefore = activeItem.presentation_indexed !== undefined;
                                 const tagDoc = PresBox.targetRenderedDoc(this.activeItem);
                                 const type = DocCast(tagDoc?.annotationOn)?.type ?? tagDoc.type;
-                                activeItem.presIndexedStart = type === DocumentType.COL ? 1 : 0;
+                                activeItem.presentation_indexedStart = type === DocumentType.COL ? 1 : 0;
                                 // a progressivized slide doesn't have sub-slides, but rather iterates over the data list of the target being progressivized.
                                 // to avoid creating a new slide to correspond to each of the target's data list, we create a computedField to refernce the target's data list.
                                 let dataField = Doc.LayoutFieldKey(tagDoc);
                                 if (Cast(tagDoc[dataField], listSpec(Doc), null)?.filter(d => d instanceof Doc) === undefined) dataField = dataField + '_annotations';
 
-                                if (DocCast(activeItem.presentationTargetDoc).annotationOn) activeItem.data = ComputedField.MakeFunction(`self.presentationTargetDoc.annotationOn["${dataField}"]`);
-                                else activeItem.data = ComputedField.MakeFunction(`self.presentationTargetDoc["${dataField}"]`);
+                                if (DocCast(activeItem.presentation_targetDoc).annotationOn) activeItem.data = ComputedField.MakeFunction(`self.presentation_targetDoc.annotationOn["${dataField}"]`);
+                                else activeItem.data = ComputedField.MakeFunction(`self.presentation_targetDoc["${dataField}"]`);
                             }}
-                            checked={Cast(activeItem.presIndexed, 'number', null) !== undefined ? true : false}
+                            checked={Cast(activeItem.presentation_indexed, 'number', null) !== undefined ? true : false}
                         />
                     </div>
                     <div className="ribbon-doubleButton" style={{ display: 'inline-flex' }}>
                         <div className="presBox-subheading">Progressivize First Bullet</div>
-                        <input className="presBox-checkbox" style={{ margin: 10 }} type="checkbox" onChange={() => (activeItem.presIndexedStart = activeItem.presIndexedStart ? 0 : 1)} checked={!NumCast(activeItem.presIndexedStart)} />
+                        <input
+                            className="presBox-checkbox"
+                            style={{ margin: 10 }}
+                            type="checkbox"
+                            onChange={() => (activeItem.presentation_indexedStart = activeItem.presentation_indexedStart ? 0 : 1)}
+                            checked={!NumCast(activeItem.presentation_indexedStart)}
+                        />
                     </div>
                     <div className="ribbon-doubleButton" style={{ display: 'inline-flex' }}>
                         <div className="presBox-subheading">Expand Current Bullet</div>
@@ -1598,18 +1609,21 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
     }
     @computed get transitionDropdown() {
         const activeItem = this.activeItem;
-        const presEffect = (effect: PresEffect) => (
-            <div className={`presBox-dropdownOption ${activeItem.presEffect === effect || (effect === PresEffect.None && !activeItem.presEffect) ? 'active' : ''}`} onPointerDown={StopEvent} onClick={() => this.updateEffect(effect, false)}>
+        const preseEffect = (effect: PresEffect) => (
+            <div
+                className={`presBox-dropdownOption ${activeItem.presentation_effect === effect || (effect === PresEffect.None && !activeItem.presentation_effect) ? 'active' : ''}`}
+                onPointerDown={StopEvent}
+                onClick={() => this.updateEffect(effect, false)}>
                 {effect}
             </div>
         );
         const presMovement = (movement: PresMovement) => (
-            <div className={`presBox-dropdownOption ${activeItem.presMovement === movement ? 'active' : ''}`} onPointerDown={StopEvent} onClick={() => this.updateMovement(movement)}>
+            <div className={`presBox-dropdownOption ${activeItem.presentation_movement === movement ? 'active' : ''}`} onPointerDown={StopEvent} onClick={() => this.updateMovement(movement)}>
                 {movement}
             </div>
         );
         const presDirection = (direction: PresEffectDirection, icon: string, gridColumn: number, gridRow: number, opts: object) => {
-            const color = activeItem.presEffectDirection === direction || (direction === PresEffectDirection.Center && !activeItem.presEffectDirection) ? Colors.LIGHT_BLUE : 'black';
+            const color = activeItem.presentation_effectDirection === direction || (direction === PresEffectDirection.Center && !activeItem.presentation_effectDirection) ? Colors.LIGHT_BLUE : 'black';
             return (
                 <Tooltip title={<div className="dash-tooltip">{direction}</div>}>
                     <div
@@ -1621,12 +1635,12 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
             );
         };
         if (activeItem && this.targetDoc) {
-            const transitionSpeed = activeItem.presTransition ? NumCast(activeItem.presTransition) / 1000 : 0.5;
+            const transitionSpeed = activeItem.presentation_transition ? NumCast(activeItem.presentation_transition) / 1000 : 0.5;
             const zoom = NumCast(activeItem.presZoom, 1) * 100;
-            const effect = activeItem.presEffect ? activeItem.presEffect : PresMovement.None;
+            const effect = activeItem.presentation_effect ? activeItem.presentation_effect : PresMovement.None;
             return (
                 <div
-                    className={`presBox-ribbon ${this._transitionTools && this.layoutDoc.presStatus === PresStatus.Edit ? 'active' : ''}`}
+                    className={`presBox-ribbon ${this._transitionTools && this.layoutDoc.presentation_status === PresStatus.Edit ? 'active' : ''}`}
                     onPointerDown={StopEvent}
                     onPointerUp={StopEvent}
                     onClick={action(e => {
@@ -1654,7 +1668,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                                 {presMovement(PresMovement.Jump)}
                             </div>
                         </div>
-                        <div className="ribbon-doubleButton" style={{ display: activeItem.presMovement === PresMovement.Zoom ? 'inline-flex' : 'none' }}>
+                        <div className="ribbon-doubleButton" style={{ display: activeItem.presentation_movement === PresMovement.Zoom ? 'inline-flex' : 'none' }}>
                             <div className="presBox-subheading">Zoom (% screen filled)</div>
                             <div className="ribbon-property">
                                 <input className="presBox-input" type="number" readOnly={true} value={zoom} onChange={e => this.updateZoom(e.target.value)} />%
@@ -1668,7 +1682,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                                 </div>
                             </div>
                         </div>
-                        {PresBox.inputter('0', '1', '100', zoom, activeItem.presMovement === PresMovement.Zoom, this.updateZoom)}
+                        {PresBox.inputter('0', '1', '100', zoom, activeItem.presentation_movement === PresMovement.Zoom, this.updateZoom)}
                         <div className="ribbon-doubleButton" style={{ display: 'inline-flex' }}>
                             <div className="presBox-subheading">Transition Time</div>
                             <div className="ribbon-property">
@@ -1698,7 +1712,13 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                         </div>
                         <div className="ribbon-doubleButton" style={{ display: 'inline-flex' }}>
                             <div className="presBox-subheading">Zoom Text Selections</div>
-                            <input className="presBox-checkbox" style={{ margin: 10 }} type="checkbox" onChange={() => (activeItem.presZoomText = !BoolCast(activeItem.presZoomText))} checked={BoolCast(activeItem.presZoomText)} />
+                            <input
+                                className="presBox-checkbox"
+                                style={{ margin: 10 }}
+                                type="checkbox"
+                                onChange={() => (activeItem.presentation_zoomText = !BoolCast(activeItem.presentation_zoomText))}
+                                checked={BoolCast(activeItem.presentation_zoomText)}
+                            />
                         </div>
                         <div
                             className="presBox-dropdown"
@@ -1710,17 +1730,17 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                             {effect?.toString()}
                             <FontAwesomeIcon className="presBox-dropdownIcon" style={{ gridColumn: 2, color: this._openEffectDropdown ? Colors.MEDIUM_BLUE : 'black' }} icon={'angle-down'} />
                             <div className={'presBox-dropdownOptions'} id={'presBoxMovementDropdown'} style={{ display: this._openEffectDropdown ? 'grid' : 'none' }} onPointerDown={e => e.stopPropagation()}>
-                                {presEffect(PresEffect.None)}
-                                {presEffect(PresEffect.Fade)}
-                                {presEffect(PresEffect.Flip)}
-                                {presEffect(PresEffect.Rotate)}
-                                {presEffect(PresEffect.Bounce)}
-                                {presEffect(PresEffect.Roll)}
+                                {preseEffect(PresEffect.None)}
+                                {preseEffect(PresEffect.Fade)}
+                                {preseEffect(PresEffect.Flip)}
+                                {preseEffect(PresEffect.Rotate)}
+                                {preseEffect(PresEffect.Bounce)}
+                                {preseEffect(PresEffect.Roll)}
                             </div>
                         </div>
                         <div className="ribbon-doubleButton" style={{ display: effect === PresEffectDirection.None ? 'none' : 'inline-flex' }}>
                             <div className="presBox-subheading">Effect direction</div>
-                            <div className="ribbon-property">{StrCast(this.activeItem.presEffectDirection)}</div>
+                            <div className="ribbon-property">{StrCast(this.activeItem.presentation_effectDirection)}</div>
                         </div>
                         <div className="effectDirection" style={{ display: effect === PresEffectDirection.None ? 'none' : 'grid', width: 40 }}>
                             {presDirection(PresEffectDirection.Left, 'angle-right', 1, 2, {})}
@@ -1760,10 +1780,10 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                                             style={{ textAlign: 'center', width: '100%', height: 15, fontSize: 10 }}
                                             type="number"
                                             readOnly={true}
-                                            value={NumCast(activeItem.presStartTime).toFixed(2)}
+                                            value={NumCast(activeItem.config_clipStart).toFixed(2)}
                                             onKeyDown={e => e.stopPropagation()}
                                             onChange={action((e: React.ChangeEvent<HTMLInputElement>) => {
-                                                activeItem.presStartTime = Number(e.target.value);
+                                                activeItem.config_clipStart = Number(e.target.value);
                                             })}
                                         />
                                     </div>
@@ -1773,7 +1793,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                                         Duration (s)
                                     </div>
                                     <div className="slider-number" style={{ backgroundColor: Colors.LIGHT_BLUE }}>
-                                        {Math.round((NumCast(activeItem.presEndTime) - NumCast(activeItem.presStartTime)) * 10) / 10}
+                                        {Math.round((NumCast(activeItem.config_clipEnd) - NumCast(activeItem.config_clipStart)) * 10) / 10}
                                     </div>
                                 </div>
                                 <div className="slider-block">
@@ -1787,9 +1807,9 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                                             style={{ textAlign: 'center', width: '100%', height: 15, fontSize: 10 }}
                                             type="number"
                                             readOnly={true}
-                                            value={NumCast(activeItem.presEndTime).toFixed(2)}
+                                            value={NumCast(activeItem.config_clipEnd).toFixed(2)}
                                             onChange={action((e: React.ChangeEvent<HTMLInputElement>) => {
-                                                activeItem.presEndTime = Number(e.target.value);
+                                                activeItem.config_clipEnd = Number(e.target.value);
                                             })}
                                         />
                                     </div>
@@ -1801,12 +1821,12 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                                     step="0.1"
                                     min={clipStart}
                                     max={clipEnd}
-                                    value={NumCast(activeItem.presEndTime)}
+                                    value={NumCast(activeItem.config_clipEnd)}
                                     style={{ gridColumn: 1, gridRow: 1 }}
                                     className={`toolbar-slider ${'end'}`}
                                     id="toolbar-slider"
                                     onPointerDown={e => {
-                                        this._batch = UndoManager.StartBatch('presEndTime');
+                                        this._batch = UndoManager.StartBatch('config_clipEnd');
                                         const endBlock = document.getElementById('endTime');
                                         if (endBlock) {
                                             endBlock.style.color = Colors.LIGHT_GRAY;
@@ -1824,7 +1844,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                                     }}
                                     onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
                                         e.stopPropagation();
-                                        activeItem.presEndTime = Number(e.target.value);
+                                        activeItem.config_clipEnd = Number(e.target.value);
                                     }}
                                 />
                                 <input
@@ -1832,12 +1852,12 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                                     step="0.1"
                                     min={clipStart}
                                     max={clipEnd}
-                                    value={NumCast(activeItem.presStartTime)}
+                                    value={NumCast(activeItem.config_clipStart)}
                                     style={{ gridColumn: 1, gridRow: 1 }}
                                     className={`toolbar-slider ${'start'}`}
                                     id="toolbar-slider"
                                     onPointerDown={e => {
-                                        this._batch = UndoManager.StartBatch('presStartTime');
+                                        this._batch = UndoManager.StartBatch('config_clipStart');
                                         const startBlock = document.getElementById('startTime');
                                         if (startBlock) {
                                             startBlock.style.color = Colors.LIGHT_GRAY;
@@ -1855,7 +1875,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                                     }}
                                     onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
                                         e.stopPropagation();
-                                        activeItem.presStartTime = Number(e.target.value);
+                                        activeItem.config_clipStart = Number(e.target.value);
                                     }}
                                 />
                             </div>
@@ -1916,7 +1936,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
         return (
             <div
                 className="presBox-toolbar-dropdown"
-                style={{ display: this._newDocumentTools && this.layoutDoc.presStatus === 'edit' ? 'inline-flex' : 'none' }}
+                style={{ display: this._newDocumentTools && this.layoutDoc.presentation_status === 'edit' ? 'inline-flex' : 'none' }}
                 onClick={e => e.stopPropagation()}
                 onPointerUp={e => e.stopPropagation()}
                 onPointerDown={e => e.stopPropagation()}>
@@ -2053,10 +2073,10 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
         if (doc) {
             const tabMap = CollectionDockingView.Instance?.tabMap;
             const tab = tabMap && Array.from(tabMap).find(tab => tab.DashDoc.type === DocumentType.COL)?.DashDoc;
-            const presCollection = DocumentManager.GetContextPath(this.activeItem).reverse().lastElement().presentationTargetDoc ?? tab;
+            const presCollection = DocumentManager.GetContextPath(this.activeItem).reverse().lastElement().presentation_targetDoc ?? tab;
             const data = Cast(presCollection?.data, listSpec(Doc));
-            const presData = Cast(this.rootDoc.data, listSpec(Doc));
-            if (data && presData) {
+            const config_data = Cast(this.rootDoc.data, listSpec(Doc));
+            if (data && config_data) {
                 data.push(doc);
                 TabDocView.PinDoc(doc, {});
                 this.gotoDocument(this.childDocs.length, this.activeItem);
@@ -2105,7 +2125,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                     className="dropdown-play-button"
                     onClick={undoBatch(
                         action(() => {
-                            this.layoutDoc.presStatus = 'manual';
+                            this.layoutDoc.presentation_status = 'manual';
                             this.initializePresState(this.itemIndex);
                             this.turnOffEdit(true);
                             this.gotoDocument(this.itemIndex, this.activeItem);
@@ -2181,7 +2201,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                 className={`presBox-buttons${Doc.IsInMyOverlay(this.rootDoc) ? ' inOverlay' : ''}`}
                 style={{ background: Doc.ActivePresentation === this.rootDoc ? Colors.LIGHT_BLUE : undefined, display: !this.rootDoc._chromeHidden ? 'none' : undefined }}>
                 {isMini ? null : (
-                    <select className="presBox-viewPicker" style={{ display: this.layoutDoc.presStatus === 'edit' ? 'block' : 'none' }} onPointerDown={e => e.stopPropagation()} onChange={this.viewChanged} value={mode}>
+                    <select className="presBox-viewPicker" style={{ display: this.layoutDoc.presentation_status === 'edit' ? 'block' : 'none' }} onPointerDown={e => e.stopPropagation()} onChange={this.viewChanged} value={mode}>
                         <option onPointerDown={StopEvent} value={CollectionViewType.Stacking}>
                             List
                         </option>
@@ -2196,12 +2216,12 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                     </select>
                 )}
                 <div className="presBox-presentPanel" style={{ opacity: this.childDocs.length ? 1 : 0.3 }}>
-                    <span className={`presBox-button ${this.layoutDoc.presStatus === PresStatus.Edit ? 'present' : ''}`}>
+                    <span className={`presBox-button ${this.layoutDoc.presentation_status === PresStatus.Edit ? 'present' : ''}`}>
                         <div
                             className="presBox-button-left"
                             onClick={undoBatch(() => {
                                 if (this.childDocs.length) {
-                                    this.layoutDoc.presStatus = 'manual';
+                                    this.layoutDoc.presentation_status = 'manual';
                                     this.initializePresState(this.itemIndex);
                                     this.gotoDocument(this.itemIndex, this.activeItem);
                                 }
@@ -2227,12 +2247,15 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
     }
 
     @computed get playButtons() {
-        const presEnd = !this.layoutDoc.presLoop && this.itemIndex === this.childDocs.length - 1 && (this.activeItem.presIndexed === undefined || NumCast(this.activeItem.presIndexed) === (this.progressivizedItems(this.activeItem)?.length ?? 0));
+        const presEnd =
+            !this.layoutDoc.presLoop &&
+            this.itemIndex === this.childDocs.length - 1 &&
+            (this.activeItem.presentation_indexed === undefined || NumCast(this.activeItem.presentation_indexed) === (this.progressivizedItems(this.activeItem)?.length ?? 0));
         const presStart: boolean = !this.layoutDoc.presLoop && this.itemIndex === 0;
         const inOverlay = Doc.IsInMyOverlay(this.rootDoc);
         // Case 1: There are still other frames and should go through all frames before going to next slide
         return (
-            <div className="presPanelOverlay" style={{ display: this.layoutDoc.presStatus !== 'edit' ? 'inline-flex' : 'none' }}>
+            <div className="presPanelOverlay" style={{ display: this.layoutDoc.presentation_status !== 'edit' ? 'inline-flex' : 'none' }}>
                 <Tooltip title={<div className="dash-tooltip">{'Loop'}</div>}>
                     <div
                         className="presPanel-button"
@@ -2255,7 +2278,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                                 this.back();
                                 if (this._presTimer) {
                                     clearTimeout(this._presTimer);
-                                    this.layoutDoc.presStatus = PresStatus.Manual;
+                                    this.layoutDoc.presentation_status = PresStatus.Manual;
                                 }
                                 e.stopPropagation();
                             },
@@ -2265,9 +2288,9 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                     }>
                     <FontAwesomeIcon icon={'arrow-left'} />
                 </div>
-                <Tooltip title={<div className="dash-tooltip">{this.layoutDoc.presStatus === PresStatus.Autoplay ? 'Pause' : 'Autoplay'}</div>}>
+                <Tooltip title={<div className="dash-tooltip">{this.layoutDoc.presentation_status === PresStatus.Autoplay ? 'Pause' : 'Autoplay'}</div>}>
                     <div className="presPanel-button" onPointerDown={e => setupMoveUpEvents(this, e, returnFalse, emptyFunction, () => this.startOrPause(true), false, false)}>
-                        <FontAwesomeIcon color={this.layoutDoc.presStatus === PresStatus.Autoplay ? 'red' : undefined} icon={this.layoutDoc.presStatus === PresStatus.Autoplay ? 'pause' : 'play'} />
+                        <FontAwesomeIcon color={this.layoutDoc.presentation_status === PresStatus.Autoplay ? 'red' : undefined} icon={this.layoutDoc.presentation_status === PresStatus.Autoplay ? 'pause' : 'play'} />
                     </div>
                 </Tooltip>
                 <div
@@ -2283,7 +2306,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                                 this.next();
                                 if (this._presTimer) {
                                     clearTimeout(this._presTimer);
-                                    this.layoutDoc.presStatus = PresStatus.Manual;
+                                    this.layoutDoc.presentation_status = PresStatus.Manual;
                                 }
                                 e.stopPropagation();
                             },
@@ -2316,7 +2339,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                 </Tooltip>
                 <div className="presPanel-button-text" onClick={() => this.gotoDocument(0, this.activeItem)} style={{ display: inOverlay || this.props.PanelWidth() > 250 ? 'inline-flex' : 'none' }}>
                     {inOverlay ? '' : 'Slide'} {this.itemIndex + 1}
-                    {this.activeItem?.presIndexed !== undefined ? `(${this.activeItem.presIndexed}/${this.progressivizedItems(this.activeItem)?.length})` : ''} / {this.childDocs.length}
+                    {this.activeItem?.presentation_indexed !== undefined ? `(${this.activeItem.presentation_indexed}/${this.progressivizedItems(this.activeItem)?.length})` : ''} / {this.childDocs.length}
                 </div>
                 <div className="presPanel-divider"></div>
                 {this.props.PanelWidth() > 250 ? (
@@ -2324,7 +2347,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                         className="presPanel-button-text"
                         onClick={undoBatch(
                             action(() => {
-                                this.layoutDoc.presStatus = PresStatus.Edit;
+                                this.layoutDoc.presentation_status = PresStatus.Edit;
                                 clearTimeout(this._presTimer);
                             })
                         )}>
@@ -2342,7 +2365,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
     @action
     startOrPause = (makeActive = true) => {
         makeActive && this.updateCurrentPresentation();
-        if (!this.layoutDoc.presStatus || this.layoutDoc.presStatus === PresStatus.Manual || this.layoutDoc.presStatus === PresStatus.Edit) this.startPresentation(this.itemIndex);
+        if (!this.layoutDoc.presentation_status || this.layoutDoc.presentation_status === PresStatus.Manual || this.layoutDoc.presentation_status === PresStatus.Edit) this.startPresentation(this.itemIndex);
         else this.pauseAutoPres();
     };
 
@@ -2351,7 +2374,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
         this.back();
         if (this._presTimer) {
             clearTimeout(this._presTimer);
-            this.layoutDoc.presStatus = PresStatus.Manual;
+            this.layoutDoc.presentation_status = PresStatus.Manual;
         }
     };
 
@@ -2360,19 +2383,19 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
         this.next();
         if (this._presTimer) {
             clearTimeout(this._presTimer);
-            this.layoutDoc.presStatus = PresStatus.Manual;
+            this.layoutDoc.presentation_status = PresStatus.Manual;
         }
     };
 
     @undoBatch
     @action
     exitClicked = () => {
-        this.layoutDoc.presStatus = this._exitTrail?.() ?? this.exitMinimize();
+        this.layoutDoc.presentation_status = this._exitTrail?.() ?? this.exitMinimize();
         clearTimeout(this._presTimer);
     };
 
     AddToMap = (treeViewDoc: Doc, index: number[]) => {
-        if (!treeViewDoc.presentationTargetDoc) return this.childDocs; // if treeViewDoc is not a pres elements, then it's a sub-bullet of a progressivized slide which isn't added to the linearized list of pres elements since it's not really a pres element.
+        if (!treeViewDoc.presentation_targetDoc) return this.childDocs; // if treeViewDoc is not a pres elements, then it's a sub-bullet of a progressivized slide which isn't added to the linearized list of pres elements since it's not really a pres element.
         var indexNum = 0;
         for (let i = 0; i < index.length; i++) {
             indexNum += index[i] * 10 ** -i;
@@ -2388,20 +2411,23 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
     };
 
     RemFromMap = (treeViewDoc: Doc, index: number[]) => {
-        if (!treeViewDoc.presentationTargetDoc) return this.childDocs; // if treeViewDoc is not a pres elements, then it's a sub-bullet of a progressivized slide which isn't added to the linearized list of pres elements since it's not really a pres element.
+        if (!treeViewDoc.presentation_targetDoc) return this.childDocs; // if treeViewDoc is not a pres elements, then it's a sub-bullet of a progressivized slide which isn't added to the linearized list of pres elements since it's not really a pres element.
         if (!this._unmounting && this.isTree) {
             this._treeViewMap.delete(treeViewDoc);
             this.dataDoc[this.presFieldKey] = new List<Doc>(this.sort(this._treeViewMap));
         }
     };
 
-    sort = (treeViewMap: Map<Doc, number>) => [...treeViewMap.entries()].sort((a: [Doc, number], b: [Doc, number]) => (a[1] > b[1] ? 1 : a[1] < b[1] ? -1 : 0)).map(kv => kv[0]);
+    sort = (treeView_Map: Map<Doc, number>) => [...treeView_Map.entries()].sort((a: [Doc, number], b: [Doc, number]) => (a[1] > b[1] ? 1 : a[1] < b[1] ? -1 : 0)).map(kv => kv[0]);
 
     render() {
         // needed to ensure that the childDocs are loaded for looking up fields
         this.childDocs.slice();
         const mode = StrCast(this.rootDoc._type_collection) as CollectionViewType;
-        const presEnd = !this.layoutDoc.presLoop && this.itemIndex === this.childDocs.length - 1 && (this.activeItem.presIndexed === undefined || NumCast(this.activeItem.presIndexed) === (this.progressivizedItems(this.activeItem)?.length ?? 0));
+        const presEnd =
+            !this.layoutDoc.presLoop &&
+            this.itemIndex === this.childDocs.length - 1 &&
+            (this.activeItem.presentation_indexed === undefined || NumCast(this.activeItem.presentation_indexed) === (this.progressivizedItems(this.activeItem)?.length ?? 0));
         const presStart = !this.layoutDoc.presLoop && this.itemIndex === 0;
         return this.props.addDocTab === returnFalse ? ( // bcz: hack!! - addDocTab === returnFalse only when this is being rendered by the OverlayView which means the doc is a mini player
             <div className="miniPres" onClick={e => e.stopPropagation()} onPointerEnter={action(e => (this._forceKeyEvents = true))}>
@@ -2420,9 +2446,9 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                     <div className="presPanel-button" style={{ opacity: presStart ? 0.4 : 1 }} onPointerDown={e => setupMoveUpEvents(this, e, returnFalse, returnFalse, this.prevClicked, false, false)}>
                         <FontAwesomeIcon icon={'arrow-left'} />
                     </div>
-                    <Tooltip title={<div className="dash-tooltip">{this.layoutDoc.presStatus === PresStatus.Autoplay ? 'Pause' : 'Autoplay'}</div>}>
+                    <Tooltip title={<div className="dash-tooltip">{this.layoutDoc.presentation_status === PresStatus.Autoplay ? 'Pause' : 'Autoplay'}</div>}>
                         <div className="presPanel-button" onPointerDown={e => setupMoveUpEvents(this, e, returnFalse, returnFalse, () => this.startOrPause(true), false, false)}>
-                            <FontAwesomeIcon icon={this.layoutDoc.presStatus === 'auto' ? 'pause' : 'play'} />
+                            <FontAwesomeIcon icon={this.layoutDoc.presentation_status === 'auto' ? 'pause' : 'play'} />
                         </div>
                     </Tooltip>
                     <div className="presPanel-button" style={{ opacity: presEnd ? 0.4 : 1 }} onPointerDown={e => setupMoveUpEvents(this, e, returnFalse, returnFalse, this.nextClicked, false, false)}>
@@ -2436,7 +2462,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                     </Tooltip>
                     <div className="presPanel-button-text">
                         Slide {this.itemIndex + 1}
-                        {this.activeItem?.presIndexed !== undefined ? `(${this.activeItem.presIndexed}/${this.progressivizedItems(this.activeItem)?.length})` : ''} / {this.childDocs.length}
+                        {this.activeItem?.presentation_indexed !== undefined ? `(${this.activeItem.presentation_indexed}/${this.progressivizedItems(this.activeItem)?.length})` : ''} / {this.childDocs.length}
                     </div>
                     <div className="presPanel-divider" />
                     <div className="presPanel-button-text" onPointerDown={e => setupMoveUpEvents(this, e, returnFalse, returnFalse, this.exitClicked, false, false)}>
@@ -2460,6 +2486,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                                 moveDocument={returnFalse}
                                 ignoreUnrendered={true}
                                 childDragAction="move"
+                                setContentView={emptyFunction}
                                 //childLayoutFitWidth={returnTrue}
                                 childOpacity={returnOne}
                                 childClickScript={PresBox.navigateToDocScript}
diff --git a/src/client/views/nodes/trails/PresElementBox.tsx b/src/client/views/nodes/trails/PresElementBox.tsx
index f31cf6147..aa514be3b 100644
--- a/src/client/views/nodes/trails/PresElementBox.tsx
+++ b/src/client/views/nodes/trails/PresElementBox.tsx
@@ -58,13 +58,13 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() {
         return this.props.DocumentView?.().props.docViewPath().lastElement()?.rootDoc;
     }
     @computed get targetDoc() {
-        return Cast(this.rootDoc.presentationTargetDoc, Doc, null) || this.rootDoc;
+        return Cast(this.rootDoc.presentation_targetDoc, Doc, null) || this.rootDoc;
     }
 
     componentDidMount() {
         this.layoutDoc.layout_hideLinkButton = true;
         this._heightDisposer = reaction(
-            () => ({ expand: this.rootDoc.presExpandInlineButton, height: this.collapsedHeight }),
+            () => ({ expand: this.rootDoc.presentation_expandInlineButton, height: this.collapsedHeight }),
             ({ expand, height }) => (this.layoutDoc._height = height + (expand ? this.expandViewHeight : 0)),
             { fireImmediately: true }
         );
@@ -79,7 +79,7 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() {
     ScreenToLocalListTransform = (xCord: number, yCord: number) => [xCord, yCord];
 
     @action
-    presExpandDocumentClick = () => (this.rootDoc.presExpandInlineButton = !this.rootDoc.presExpandInlineButton);
+    presExpandDocumentClick = () => (this.rootDoc.presentation_expandInlineButton = !this.rootDoc.presentation_expandInlineButton);
 
     embedHeight = (): number => this.collapsedHeight + this.expandViewHeight;
     // embedWidth = () => this.props.PanelWidth();
@@ -94,7 +94,7 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() {
      * presentation element.
      */
     @computed get renderEmbeddedInline() {
-        return !this.rootDoc.presExpandInlineButton || !this.targetDoc ? null : (
+        return !this.rootDoc.presentation_expandInlineButton || !this.targetDoc ? null : (
             <div className="presItem-embedded" style={{ height: this.embedHeight(), width: '50%' }}>
                 <DocumentView
                     Document={PresBox.targetRenderedDoc(this.rootDoc)}
@@ -158,9 +158,9 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() {
 
     @computed get transition() {
         let transitionInS: number;
-        if (this.rootDoc.presTransition) transitionInS = NumCast(this.rootDoc.presTransition) / 1000;
+        if (this.rootDoc.presentation_transition) transitionInS = NumCast(this.rootDoc.presentation_transition) / 1000;
         else transitionInS = 0.5;
-        return this.rootDoc.presMovement === PresMovement.Jump || this.rootDoc.presMovement === PresMovement.None ? null : 'M: ' + transitionInS + 's';
+        return this.rootDoc.presentation_movement === PresMovement.Jump || this.rootDoc.presentation_movement === PresMovement.None ? null : 'M: ' + transitionInS + 's';
     }
 
     private _itemRef: React.RefObject<HTMLDivElement> = React.createRef();
@@ -238,7 +238,7 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() {
 
     onPointerMove = (e: PointerEvent) => {
         const slide = this._itemRef.current!;
-        const dragIsPresItem = DragManager.docsBeingDragged.some(d => d.presentationTargetDoc);
+        const dragIsPresItem = DragManager.docsBeingDragged.some(d => d.presentation_targetDoc);
         if (slide && dragIsPresItem) {
             const rect = slide.getBoundingClientRect();
             const y = e.clientY - rect.top; //y position within the element.
@@ -296,12 +296,12 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() {
     @action
     updateCapturedContainerLayout = (presTargetDoc: Doc, activeItem: Doc) => {
         const targetDoc = DocCast(presTargetDoc.annotationOn) ?? presTargetDoc;
-        activeItem.presX = NumCast(targetDoc.x);
-        activeItem.presY = NumCast(targetDoc.y);
-        activeItem.presRotation = NumCast(targetDoc.rotation);
-        activeItem.presWidth = NumCast(targetDoc.width);
-        activeItem.presHeight = NumCast(targetDoc.height);
-        activeItem.presPinLayout = true;
+        activeItem.config_x = NumCast(targetDoc.x);
+        activeItem.config_y = NumCast(targetDoc.y);
+        activeItem.config_rotation = NumCast(targetDoc.rotation);
+        activeItem.config_width = NumCast(targetDoc.width);
+        activeItem.config_height = NumCast(targetDoc.height);
+        activeItem.config_pinLayout = true;
     };
     /**
      * Method called for updating the view of the currently selected document
@@ -421,7 +421,7 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() {
                 <div
                     className="slideButton"
                     onPointerDown={e => setupMoveUpEvents(this, e, returnFalse, emptyFunction, () => this.updateCapturedContainerLayout(targetDoc, activeItem), true)}
-                    style={{ opacity: activeItem.presPinLayout ? 1 : 0.5, fontWeight: 700, display: 'flex' }}>
+                    style={{ opacity: activeItem.config_pinLayout ? 1 : 0.5, fontWeight: 700, display: 'flex' }}>
                     L
                 </div>
             </Tooltip>
@@ -431,7 +431,7 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() {
                 <div
                     className="slideButton"
                     onPointerDown={e => setupMoveUpEvents(this, e, returnFalse, emptyFunction, () => this.updateCapturedViewContents(targetDoc, activeItem))}
-                    style={{ opacity: activeItem.presPinData || activeItem.presPinView ? 1 : 0.5, fontWeight: 700, display: 'flex' }}>
+                    style={{ opacity: activeItem.config_pinData || activeItem.config_pinView ? 1 : 0.5, fontWeight: 700, display: 'flex' }}>
                     C
                 </div>
             </Tooltip>
@@ -445,19 +445,19 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() {
         );
         if (this.indexInPres !== 0) {
             items.push(
-                <Tooltip key="arrow" title={<div className="dash-tooltip">{activeItem.groupWithUp ? 'Ungroup' : 'Group with up'}</div>}>
+                <Tooltip key="arrow" title={<div className="dash-tooltip">{activeItem.presentation_groupWithUp ? 'Ungroup' : 'Group with up'}</div>}>
                     <div
                         className="slideButton"
-                        onClick={() => (activeItem.groupWithUp = (NumCast(activeItem.groupWithUp) + 1) % 3)}
+                        onClick={() => (activeItem.presentation_groupWithUp = (NumCast(activeItem.presentation_groupWithUp) + 1) % 3)}
                         style={{
                             zIndex: 1000 - this.indexInPres,
                             fontWeight: 700,
-                            backgroundColor: activeItem.groupWithUp ? (presColorBool ? presBoxColor : Colors.MEDIUM_BLUE) : undefined,
-                            outline: NumCast(activeItem.groupWithUp) > 1 ? 'solid black 1px' : undefined,
-                            height: activeItem.groupWithUp ? 53 : 18,
-                            transform: activeItem.groupWithUp ? 'translate(0, -17px)' : undefined,
+                            backgroundColor: activeItem.presentation_groupWithUp ? (presColorBool ? presBoxColor : Colors.MEDIUM_BLUE) : undefined,
+                            outline: NumCast(activeItem.presentation_groupWithUp) > 1 ? 'solid black 1px' : undefined,
+                            height: activeItem.presentation_groupWithUp ? 53 : 18,
+                            transform: activeItem.presentation_groupWithUp ? 'translate(0, -17px)' : undefined,
                         }}>
-                        <div style={{ transform: activeItem.groupWithUp ? 'rotate(180deg) translate(0, -17.5px)' : 'rotate(0deg)' }}>
+                        <div style={{ transform: activeItem.presentation_groupWithUp ? 'rotate(180deg) translate(0, -17.5px)' : 'rotate(0deg)' }}>
                             <FontAwesomeIcon icon={'arrow-up'} onPointerDown={e => e.stopPropagation()} />
                         </div>
                     </div>
@@ -465,14 +465,14 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() {
             );
         }
         items.push(
-            <Tooltip key="eye" title={<div className="dash-tooltip">{this.rootDoc.presExpandInlineButton ? 'Minimize' : 'Expand'}</div>}>
+            <Tooltip key="eye" title={<div className="dash-tooltip">{this.rootDoc.presentation_expandInlineButton ? 'Minimize' : 'Expand'}</div>}>
                 <div
                     className="slideButton"
                     onClick={e => {
                         e.stopPropagation();
                         this.presExpandDocumentClick();
                     }}>
-                    <FontAwesomeIcon icon={this.rootDoc.presExpandInlineButton ? 'eye-slash' : 'eye'} onPointerDown={e => e.stopPropagation()} />
+                    <FontAwesomeIcon icon={this.rootDoc.presentation_expandInlineButton ? 'eye-slash' : 'eye'} onPointerDown={e => e.stopPropagation()} />
                 </div>
             </Tooltip>
         );
@@ -534,7 +534,7 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() {
                             style={{
                                 display: 'inline-flex',
                                 pointerEvents: isSelected ? undefined : 'none',
-                                width: `calc(100% ${this.rootDoc.presExpandInlineButton ? '- 50%' : ''} - ${this.presButtons.length * 22}px`,
+                                width: `calc(100% ${this.rootDoc.presentation_expandInlineButton ? '- 50%' : ''} - ${this.presButtons.length * 22}px`,
                                 cursor: isSelected ? 'text' : 'grab',
                             }}>
                             <div
diff --git a/src/client/views/pdf/Annotation.tsx b/src/client/views/pdf/Annotation.tsx
index db6b1f011..caa72c9dc 100644
--- a/src/client/views/pdf/Annotation.tsx
+++ b/src/client/views/pdf/Annotation.tsx
@@ -24,7 +24,7 @@ export class Annotation extends React.Component<IAnnotationProps> {
     render() {
         return (
             <div style={{ display: this.props.anno.textCopied && !Doc.isBrushedHighlightedDegree(this.props.anno) ? 'none' : undefined }}>
-                {DocListCast(this.props.anno.textInlineAnnotations).map(a => (
+                {DocListCast(this.props.anno.text_inlineAnnotations).map(a => (
                     <RegionAnnotation pointerEvents={this.props.pointerEvents} {...this.props} document={a} key={a[Id]} />
                 ))}
             </div>
@@ -61,7 +61,7 @@ class RegionAnnotation extends React.Component<IRegionAnnotationProps> {
     isTargetToggler = () => BoolCast(this.annoTextRegion.followLinkToggle);
     @undoBatch
     showTargetTrail = (anchor: Doc) => {
-        const trail = DocCast(anchor.presTrail);
+        const trail = DocCast(anchor.presentationTrail);
         if (trail) {
             Doc.ActivePresentation = trail;
             this.props.addDocTab(trail, OpenWhere.replaceRight);
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index 1319a236d..395fbd1ca 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -68,7 +68,7 @@ export class PDFViewer extends React.Component<IViewerProps> {
     private _styleRule: any; // stylesheet rule for making hyperlinks clickable
     private _retries = 0; // number of times tried to create the PDF viewer
     private _setPreviewCursor: undefined | ((x: number, y: number, drag: boolean, hide: boolean) => void);
-    private _setBrushViewer: undefined | ((view: { width: number; height: number; panX: number; panY: number }) => void);
+    private _setBrushViewer: undefined | ((view: { width: number; height: number; panX: number; panY: number }, transTime: number) => void);
     private _annotationLayer: React.RefObject<HTMLDivElement> = React.createRef();
     private _disposers: { [name: string]: IReactionDisposer } = {};
     private _viewer: React.RefObject<HTMLDivElement> = React.createRef();
@@ -95,7 +95,7 @@ export class PDFViewer extends React.Component<IViewerProps> {
         return DocUtils.FilterDocs(DocListCast(this.props.dataDoc[this.props.fieldKey + '_annotations']), this.props.childFilters(), this.props.childFiltersByRanges());
     }
     @computed get inlineTextAnnotations() {
-        return this.allAnnotations.filter(a => a.textInlineAnnotations);
+        return this.allAnnotations.filter(a => a.text_inlineAnnotations);
     }
 
     componentDidMount = async () => {
@@ -195,7 +195,7 @@ export class PDFViewer extends React.Component<IViewerProps> {
         return focusSpeed;
     };
     crop = (region: Doc | undefined, addCrop?: boolean) => this.props.crop(region, addCrop);
-    brushView = (view: { width: number; height: number; panX: number; panY: number }) => this._setBrushViewer?.(view);
+    brushView = (view: { width: number; height: number; panX: number; panY: number }, transTime: number) => this._setBrushViewer?.(view, transTime);
 
     @action
     setupPdfJsViewer = async () => {
@@ -470,7 +470,7 @@ export class PDFViewer extends React.Component<IViewerProps> {
     };
 
     setPreviewCursor = (func?: (x: number, y: number, drag: boolean, hide: boolean) => void) => (this._setPreviewCursor = func);
-    setBrushViewer = (func?: (view: { width: number; height: number; panX: number; panY: number }) => void) => (this._setBrushViewer = func);
+    setBrushViewer = (func?: (view: { width: number; height: number; panX: number; panY: number }, transTime: number) => void) => (this._setBrushViewer = func);
 
     @action
     onZoomWheel = (e: React.WheelEvent) => {
diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts
index eb52cff88..d3912b8a0 100644
--- a/src/fields/Doc.ts
+++ b/src/fields/Doc.ts
@@ -1363,9 +1363,9 @@ export namespace Doc {
             UnhighlightWatchers.push(watcher);
         } else watcher();
     }
-    export function linkFollowHighlight(destDoc: Doc | Doc[], dataAndDisplayDocs = true, presEffect?: Doc) {
+    export function linkFollowHighlight(destDoc: Doc | Doc[], dataAndDisplayDocs = true, presentation_effect?: Doc) {
         linkFollowUnhighlight();
-        (destDoc instanceof Doc ? [destDoc] : destDoc).forEach(doc => Doc.HighlightDoc(doc, dataAndDisplayDocs, presEffect));
+        (destDoc instanceof Doc ? [destDoc] : destDoc).forEach(doc => Doc.HighlightDoc(doc, dataAndDisplayDocs, presentation_effect));
         document.removeEventListener('pointerdown', linkFollowUnhighlight);
         document.addEventListener('pointerdown', linkFollowUnhighlight);
         if (UnhighlightTimer) clearTimeout(UnhighlightTimer);
@@ -1380,11 +1380,11 @@ export namespace Doc {
         if (!doc || GetEffectiveAcl(doc) === AclPrivate || GetEffectiveAcl(Doc.GetProto(doc)) === AclPrivate || doc.opacity === 0) return false;
         return doc[Highlight] || Doc.GetProto(doc)[Highlight];
     }
-    export function HighlightDoc(doc: Doc, dataAndDisplayDocs = true, presEffect?: Doc) {
+    export function HighlightDoc(doc: Doc, dataAndDisplayDocs = true, presentation_effect?: Doc) {
         runInAction(() => {
             highlightedDocs.add(doc);
             doc[Highlight] = true;
-            doc[Animation] = presEffect;
+            doc[Animation] = presentation_effect;
             if (dataAndDisplayDocs) {
                 highlightedDocs.add(Doc.GetProto(doc));
                 Doc.GetProto(doc)[Highlight] = true;
diff --git a/src/fields/documentSchemas.ts b/src/fields/documentSchemas.ts
index 76b287be7..e33a17416 100644
--- a/src/fields/documentSchemas.ts
+++ b/src/fields/documentSchemas.ts
@@ -72,11 +72,11 @@ export const documentSchema = createSchema({
     stroke_endMarker: 'string',
     stroke_dash: 'string',
     textTransform: 'string',
-    treeViewOpen: 'boolean', //  flag denoting whether the documents sub-tree (contents) is visible or hidden
-    treeViewExpandedView: 'string', // name of field whose contents are being displayed as the document's subtree
-    treeViewExpandedViewLock: 'boolean', // whether the expanded view can be changed
-    treeViewOpenIsTransient: 'boolean', // ignores the treeViewOpen flag (for allowing a view to not be slaved to other views of the document)
-    treeViewType: 'string', // whether tree view is an outline, file syste or (default) hierarchy. For outline, clicks edit document titles immediately since double-click opening is turned off
+    treeView_Open: 'boolean', //  flag denoting whether the documents sub-tree (contents) is visible or hidden
+    treeView_ExpandedView: 'string', // name of field whose contents are being displayed as the document's subtree
+    treeView_ExpandedViewLock: 'boolean', // whether the expanded view can be changed
+    treeView_OpenIsTransient: 'boolean', // ignores the treeView_Open flag (for allowing a view to not be slaved to other views of the document)
+    treeView_Type: 'string', // whether tree view is an outline, file syste or (default) hierarchy. For outline, clicks edit document titles immediately since double-click opening is turned off
 
     // interaction and linking properties
     ignoreClick: 'boolean', // whether documents ignores input clicks (but does not ignore manipulation and other events)
-- 
cgit v1.2.3-70-g09d2


From bcada17befd639516862163831b9adb823791a93 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Thu, 17 Aug 2023 15:50:47 -0400
Subject: changed default color picker

---
 package-lock.json                                  | 97 ++++++++++++++++++++--
 package.json                                       |  2 +-
 src/client/views/nodes/FontIconBox/FontIconBox.tsx |  1 +
 src/fields/DocSymbols.ts                           |  2 +-
 4 files changed, 94 insertions(+), 8 deletions(-)

(limited to 'src/client/views/nodes/FontIconBox/FontIconBox.tsx')

diff --git a/package-lock.json b/package-lock.json
index eb2a0bd68..e6985cf65 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -6507,9 +6507,9 @@
             }
         },
         "browndash-components": {
-            "version": "0.0.96",
-            "resolved": "https://registry.npmjs.org/browndash-components/-/browndash-components-0.0.96.tgz",
-            "integrity": "sha512-HX05U7oIwnwZuQDPBgdASLm5LPE8pF7l8L2bIdS7YOmS4HisesXGU8GZeOBc+wqHWKMSYCMRe9gFhRvJK+FaPA==",
+            "version": "0.0.97",
+            "resolved": "https://registry.npmjs.org/browndash-components/-/browndash-components-0.0.97.tgz",
+            "integrity": "sha512-UO8NQrOJoAq+UQGR8TXCRzr6jX9qSnEot9FHP7zdwlKH1sGntbQpyM5BXdwfkyXo+oh1qstTGkyR4s20CY7Yrw==",
             "requires": {
                 "@emotion/react": "^11.11.1",
                 "@emotion/styled": "^11.11.0",
@@ -7063,12 +7063,97 @@
                                         "strip-ansi": "^7.0.1"
                                     }
                                 },
+                                "string-width-cjs": {
+                                    "version": "npm:string-width@4.2.3",
+                                    "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+                                    "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+                                    "requires": {
+                                        "emoji-regex": "^8.0.0",
+                                        "is-fullwidth-code-point": "^3.0.0",
+                                        "strip-ansi": "^6.0.1"
+                                    },
+                                    "dependencies": {
+                                        "ansi-regex": {
+                                            "version": "5.0.1",
+                                            "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+                                            "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="
+                                        },
+                                        "emoji-regex": {
+                                            "version": "8.0.0",
+                                            "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+                                            "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
+                                        },
+                                        "strip-ansi": {
+                                            "version": "6.0.1",
+                                            "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+                                            "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+                                            "requires": {
+                                                "ansi-regex": "^5.0.1"
+                                            }
+                                        }
+                                    }
+                                },
                                 "strip-ansi": {
                                     "version": "7.1.0",
                                     "bundled": true,
                                     "requires": {
                                         "ansi-regex": "^6.0.1"
                                     }
+                                },
+                                "strip-ansi-cjs": {
+                                    "version": "npm:strip-ansi@6.0.1",
+                                    "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+                                    "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+                                    "requires": {
+                                        "ansi-regex": "^5.0.1"
+                                    },
+                                    "dependencies": {
+                                        "ansi-regex": {
+                                            "version": "5.0.1",
+                                            "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+                                            "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="
+                                        }
+                                    }
+                                },
+                                "wrap-ansi-cjs": {
+                                    "version": "npm:wrap-ansi@7.0.0",
+                                    "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+                                    "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+                                    "requires": {
+                                        "ansi-styles": "^4.0.0",
+                                        "string-width": "^4.1.0",
+                                        "strip-ansi": "^6.0.0"
+                                    },
+                                    "dependencies": {
+                                        "ansi-regex": {
+                                            "version": "5.0.1",
+                                            "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+                                            "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="
+                                        },
+                                        "emoji-regex": {
+                                            "version": "8.0.0",
+                                            "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+                                            "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
+                                        },
+                                        "string-width": {
+                                            "version": "4.2.3",
+                                            "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+                                            "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+                                            "requires": {
+                                                "emoji-regex": "^8.0.0",
+                                                "is-fullwidth-code-point": "^3.0.0",
+                                                "strip-ansi": "^6.0.1"
+                                            }
+                                        },
+                                        "strip-ansi": {
+                                            "version": "6.0.1",
+                                            "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+                                            "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+                                            "requires": {
+                                                "ansi-regex": "^5.0.1"
+                                            }
+                                        }
+                                    }
                                 }
                             }
                         },
@@ -8573,7 +8658,7 @@
                             }
                         },
                         "string-width-cjs": {
-                            "version": "npm:string-width@4.2.3",
+                            "version": "npm:string-width-cjs@4.2.3",
                             "bundled": true,
                             "requires": {
                                 "emoji-regex": "^8.0.0",
@@ -8596,7 +8681,7 @@
                             }
                         },
                         "strip-ansi-cjs": {
-                            "version": "npm:strip-ansi@6.0.1",
+                            "version": "npm:strip-ansi-cjs@6.0.1",
                             "bundled": true,
                             "requires": {
                                 "ansi-regex": "^5.0.1"
@@ -8755,7 +8840,7 @@
                             }
                         },
                         "wrap-ansi-cjs": {
-                            "version": "npm:wrap-ansi@7.0.0",
+                            "version": "npm:wrap-ansi-cjs@7.0.0",
                             "bundled": true,
                             "requires": {
                                 "ansi-styles": "^4.0.0",
diff --git a/package.json b/package.json
index bcd3ce037..ea4e6a5e6 100644
--- a/package.json
+++ b/package.json
@@ -178,7 +178,7 @@
         "body-parser": "^1.19.2",
         "bootstrap": "^4.6.1",
         "brotli": "^1.3.3",
-        "browndash-components": "^0.0.96",
+        "browndash-components": "^0.0.97",
         "browser-assert": "^1.2.1",
         "bson": "^4.6.1",
         "canvas": "^2.9.3",
diff --git a/src/client/views/nodes/FontIconBox/FontIconBox.tsx b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
index bf3c79cf9..5ff5f7bfa 100644
--- a/src/client/views/nodes/FontIconBox/FontIconBox.tsx
+++ b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
@@ -287,6 +287,7 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
                     this.colorBatch?.end();
                     this.colorBatch = undefined;
                 }}
+                defaultPickerType="Classic"
                 selectedColor={curColor}
                 type={Type.PRIM}
                 color={color}
diff --git a/src/fields/DocSymbols.ts b/src/fields/DocSymbols.ts
index ac13fa27a..088903082 100644
--- a/src/fields/DocSymbols.ts
+++ b/src/fields/DocSymbols.ts
@@ -24,4 +24,4 @@ export const Initializing = Symbol('DocInitializing');
 export const ForceServerWrite = Symbol('DocForceServerWrite');
 export const CachedUpdates = Symbol('DocCachedUpdates');
 
-export const DashVersion = 'v0.5.5';
+export const DashVersion = 'v0.5.6';
-- 
cgit v1.2.3-70-g09d2


From d3ecace5f03233e5d5ab2354c3f482418287ca9a Mon Sep 17 00:00:00 2001
From: Sophie Zhang <sophie_zhang@brown.edu>
Date: Thu, 17 Aug 2023 16:14:53 -0400
Subject: broken version

---
 package-lock.json                                  |  97 +++++++++++++++--
 src/client/util/CurrentUserUtils.ts                |   2 +
 src/client/views/MainView.tsx                      |   2 +-
 .../collectionFreeForm/CollectionFreeFormView.tsx  |   1 +
 src/client/views/global/globalScripts.ts           |   8 +-
 src/client/views/nodes/FontIconBox/FontIconBox.tsx |  28 +++++
 src/client/views/nodes/ImageBox.tsx                |   6 +-
 .../views/nodes/formattedText/FormattedTextBox.tsx |  76 +++++++-------
 .../views/nodes/generativeFill/GenerativeFill.tsx  | 115 +++++++++++++--------
 .../nodes/generativeFill/GenerativeFillButtons.tsx |   6 +-
 src/client/views/pdf/AnchorMenu.tsx                |   1 +
 src/client/views/pdf/GPTPopup/GPTPopup.scss        |   2 +
 src/client/views/pdf/GPTPopup/GPTPopup.tsx         |  99 +++++++++---------
 src/client/views/pdf/PDFViewer.tsx                 |   4 -
 14 files changed, 301 insertions(+), 146 deletions(-)

(limited to 'src/client/views/nodes/FontIconBox/FontIconBox.tsx')

diff --git a/package-lock.json b/package-lock.json
index 658e783f9..20d582e5b 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -6507,9 +6507,9 @@
             }
         },
         "browndash-components": {
-            "version": "0.0.92",
-            "resolved": "https://registry.npmjs.org/browndash-components/-/browndash-components-0.0.92.tgz",
-            "integrity": "sha512-eE/6WQNZiLnaXUKyoaMm0PDYjExUsFJ9VTAIIxROpYPosIBKWNZ743xaOfmehib5us9hEXJb0CvUFJQb8rzDVw==",
+            "version": "0.0.93",
+            "resolved": "https://registry.npmjs.org/browndash-components/-/browndash-components-0.0.93.tgz",
+            "integrity": "sha512-JL9Hi7Nq+zHZtjLCQSuGhID0Hd7X6sARutyJqbECfsLWACsIC/JfeEQZdUeH5CqO+R7pJKeoWM82AIkWGtN2Xw==",
             "requires": {
                 "@emotion/react": "^11.11.1",
                 "@emotion/styled": "^11.11.0",
@@ -7063,12 +7063,97 @@
                                         "strip-ansi": "^7.0.1"
                                     }
                                 },
+                                "string-width-cjs": {
+                                    "version": "npm:string-width@4.2.3",
+                                    "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+                                    "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+                                    "requires": {
+                                        "emoji-regex": "^8.0.0",
+                                        "is-fullwidth-code-point": "^3.0.0",
+                                        "strip-ansi": "^6.0.1"
+                                    },
+                                    "dependencies": {
+                                        "ansi-regex": {
+                                            "version": "5.0.1",
+                                            "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+                                            "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="
+                                        },
+                                        "emoji-regex": {
+                                            "version": "8.0.0",
+                                            "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+                                            "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
+                                        },
+                                        "strip-ansi": {
+                                            "version": "6.0.1",
+                                            "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+                                            "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+                                            "requires": {
+                                                "ansi-regex": "^5.0.1"
+                                            }
+                                        }
+                                    }
+                                },
                                 "strip-ansi": {
                                     "version": "7.1.0",
                                     "bundled": true,
                                     "requires": {
                                         "ansi-regex": "^6.0.1"
                                     }
+                                },
+                                "strip-ansi-cjs": {
+                                    "version": "npm:strip-ansi@6.0.1",
+                                    "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+                                    "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+                                    "requires": {
+                                        "ansi-regex": "^5.0.1"
+                                    },
+                                    "dependencies": {
+                                        "ansi-regex": {
+                                            "version": "5.0.1",
+                                            "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+                                            "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="
+                                        }
+                                    }
+                                },
+                                "wrap-ansi-cjs": {
+                                    "version": "npm:wrap-ansi@7.0.0",
+                                    "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+                                    "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+                                    "requires": {
+                                        "ansi-styles": "^4.0.0",
+                                        "string-width": "^4.1.0",
+                                        "strip-ansi": "^6.0.0"
+                                    },
+                                    "dependencies": {
+                                        "ansi-regex": {
+                                            "version": "5.0.1",
+                                            "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+                                            "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="
+                                        },
+                                        "emoji-regex": {
+                                            "version": "8.0.0",
+                                            "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+                                            "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
+                                        },
+                                        "string-width": {
+                                            "version": "4.2.3",
+                                            "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+                                            "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+                                            "requires": {
+                                                "emoji-regex": "^8.0.0",
+                                                "is-fullwidth-code-point": "^3.0.0",
+                                                "strip-ansi": "^6.0.1"
+                                            }
+                                        },
+                                        "strip-ansi": {
+                                            "version": "6.0.1",
+                                            "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+                                            "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+                                            "requires": {
+                                                "ansi-regex": "^5.0.1"
+                                            }
+                                        }
+                                    }
                                 }
                             }
                         },
@@ -8573,7 +8658,7 @@
                             }
                         },
                         "string-width-cjs": {
-                            "version": "npm:string-width@4.2.3",
+                            "version": "npm:string-width-cjs@4.2.3",
                             "bundled": true,
                             "requires": {
                                 "emoji-regex": "^8.0.0",
@@ -8596,7 +8681,7 @@
                             }
                         },
                         "strip-ansi-cjs": {
-                            "version": "npm:strip-ansi@6.0.1",
+                            "version": "npm:strip-ansi-cjs@6.0.1",
                             "bundled": true,
                             "requires": {
                                 "ansi-regex": "^5.0.1"
@@ -8755,7 +8840,7 @@
                             }
                         },
                         "wrap-ansi-cjs": {
-                            "version": "npm:wrap-ansi@7.0.0",
+                            "version": "npm:wrap-ansi-cjs@7.0.0",
                             "bundled": true,
                             "requires": {
                                 "ansi-styles": "^4.0.0",
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index c9a5175bb..6592ecffc 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -633,6 +633,8 @@ export class CurrentUserUtils {
             { title: "Snap", icon: "th",                    toolTip: "Show Snap Lines",     btnType: ButtonType.ToggleButton, ignoreClick: true, expertMode: false, toolType:"snaplines",  funcs: {}, scripts: { onClick: '{ return showFreeform(self.toolType, _readOnly_);}'}}, // Only when floating document is selected in freeform
             { title: "Grid",          icon: "border-all",   toolTip: "Show Grid",           btnType: ButtonType.ToggleButton, ignoreClick: true, expertMode: false, toolType:"grid",       funcs: {}, scripts: { onClick: '{ return showFreeform(self.toolType, _readOnly_);}'}}, // Only when floating document is selected in freeform
             { title: "View All",   icon: "object-group", toolTip: "Fit all Docs to View",   btnType: ButtonType.ToggleButton, ignoreClick: true, expertMode: false, toolType:"viewAll",    funcs: {}, scripts: { onClick: '{ return showFreeform(self.toolType, _readOnly_);}'}}, // Only when floating document is selected in freeform
+            // want the same style as toggle button, but don't want it to act as an actual toggle, so set disableToggle to true,
+            { title: "Fit All",   icon: "arrows-left-right", toolTip: "Fit all Docs to View (persistent)", btnType: ButtonType.IconClickButton, ignoreClick: false, expertMode: false, toolType:"viewAllPersist",    funcs: {}, scripts: { onClick: '{ return showFreeform(self.toolType, _readOnly_);}'}}, // Only when floating document is selected in freeform
             { title: "Clusters",      icon: "braille",      toolTip: "Show Doc Clusters",   btnType: ButtonType.ToggleButton, ignoreClick: true, expertMode: false, toolType:"clusters",   funcs: {}, scripts: { onClick: '{ return showFreeform(self.toolType, _readOnly_);}'}}, // Only when floating document is selected in freeform
             { title: "Cards",         icon: "brain",        toolTip: "Flashcards",          btnType: ButtonType.ToggleButton, ignoreClick: true, expertMode: false, toolType:"flashcards", funcs: {}, scripts: { onClick: '{ return showFreeform(self.toolType, _readOnly_);}'}}, // Only when floating document is selected in freeform
             { title: "Arrange",icon:"arrow-down-short-wide",toolTip:"Toggle Auto Arrange",  btnType: ButtonType.ToggleButton, ignoreClick: true, expertMode: false, toolType:"arrange",    funcs: {hidden: 'IsNoviceMode()'}, scripts: { onClick: '{ return showFreeform(self.toolType, _readOnly_);}'}}, // Only when floating document is selected in freeform
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 60eb64caa..8fba9b886 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -80,7 +80,6 @@ export class MainView extends React.Component {
     @observable public imageEditorSource: string = '';
     @action public setImageEditorSource = (source: string) => (this.imageEditorSource = source);
     @observable public imageRootDoc: Doc | undefined;
-    @action public setImageRootDoc = (doc: Doc) => (this.imageRootDoc = doc);
     @observable public addDoc: ((doc: Doc | Doc[], annotationKey?: string) => boolean) | undefined;
 
     @observable public LastButton: Opt<Doc>;
@@ -350,6 +349,7 @@ export class MainView extends React.Component {
                 fa.faMousePointer,
                 fa.faMusic,
                 fa.faObjectGroup,
+                fa.faArrowsLeftRight,
                 fa.faPause,
                 fa.faPen,
                 fa.faPenNib,
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 29122cb91..f353dfab7 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -1599,6 +1599,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
                     () => this.rootDoc.fitContentOnce,
                     fitContentOnce => {
                         if (fitContentOnce) this.fitContentOnce();
+                        this.rootDoc.fitContentOnce = false;
                     },
                     { fireImmediately: true, name: 'fitContent' }
                 );
diff --git a/src/client/views/global/globalScripts.ts b/src/client/views/global/globalScripts.ts
index 256377758..38bf1042d 100644
--- a/src/client/views/global/globalScripts.ts
+++ b/src/client/views/global/globalScripts.ts
@@ -85,10 +85,10 @@ ScriptingGlobals.add(function toggleOverlay(checkResult?: boolean) {
     selected ? selected.props.CollectionFreeFormDocumentView?.().float() : console.log('[FontIconBox.tsx] toggleOverlay failed');
 });
 
-ScriptingGlobals.add(function showFreeform(attr: 'flashcards' | 'grid' | 'snaplines' | 'clusters' | 'arrange' | 'viewAll', checkResult?: boolean) {
+ScriptingGlobals.add(function showFreeform(attr: 'flashcards' | 'grid' | 'snaplines' | 'clusters' | 'arrange' | 'viewAll' | 'viewAllPersist', 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([
+    const map: Map<'flashcards' | 'grid' | 'snaplines' | 'clusters' | 'arrange'| 'viewAll' | 'viewAllPersist', { waitForRender?: boolean, checkResult: (doc:Doc) => any; setDoc: (doc:Doc) => void;}> = new Map([
         ['grid', {
             checkResult: (doc:Doc) => BoolCast(doc._freeform_backgroundGrid, false),
             setDoc: (doc:Doc) => doc._freeform_backgroundGrid = !doc._freeform_backgroundGrid,
@@ -101,6 +101,10 @@ ScriptingGlobals.add(function showFreeform(attr: 'flashcards' | 'grid' | 'snapli
             checkResult: (doc:Doc) => BoolCast(doc._freeform_fitContentsToBox, false),
             setDoc: (doc:Doc) => doc._freeform_fitContentsToBox = !doc._freeform_fitContentsToBox,
         }],
+        ['viewAllPersist', {
+            checkResult: (doc:Doc) => false,
+            setDoc: (doc:Doc) => doc.fitContentOnce = true
+        }],
         ['clusters', {
             waitForRender: true, // flags that undo batch should terminate after a re-render giving the script the chance to fire
             checkResult: (doc:Doc) => BoolCast(doc._freeform_useClusters, false),
diff --git a/src/client/views/nodes/FontIconBox/FontIconBox.tsx b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
index 91eac675f..90ec212fc 100644
--- a/src/client/views/nodes/FontIconBox/FontIconBox.tsx
+++ b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
@@ -29,6 +29,7 @@ export enum ButtonType {
     DropdownList = 'dropdownList',
     DropdownButton = 'dropdownBtn',
     ClickButton = 'clickBtn',
+    IconClickButton = 'iconClickBtn',
     ToggleButton = 'toggleBtn',
     ColorButton = 'colorBtn',
     ToolButton = 'toolBtn',
@@ -346,6 +347,32 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
         );
     }
 
+    @computed get iconClickButton() {
+        // Determine the type of toggle button
+        const buttonText: string = StrCast(this.rootDoc.buttonText);
+        const tooltip: string = StrCast(this.rootDoc.toolTip);
+
+        const script = ScriptCast(this.rootDoc.onClick);
+        const toggleStatus = script ? script.script.run({ this: this.layoutDoc, self: this.rootDoc, value: undefined, _readOnly_: true }).result : false;
+        // Colors
+        const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color);
+        const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor);
+
+        return (
+            <Toggle
+                tooltip={`${tooltip}`}
+                toggleType={ToggleType.BUTTON}
+                type={Type.PRIM}
+                toggleStatus={toggleStatus}
+                text={buttonText}
+                color={color}
+                icon={this.Icon(color)!}
+                label={this.label}
+                onPointerDown={() => script.script.run({ this: this.layoutDoc, self: this.rootDoc, value: !toggleStatus, _readOnly_: false })}
+            />
+        );
+    }
+
     /**
      * Default
      */
@@ -393,6 +420,7 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
             case ButtonType.DropdownButton:     return this.dropdownButton;
             case ButtonType.MultiToggleButton:  return this.multiToggleButton;
             case ButtonType.ToggleButton:       return this.toggleButton;
+            case ButtonType.IconClickButton: return this.iconClickButton;
             case ButtonType.ClickButton:
             case ButtonType.ToolButton: return <IconButton {...btnProps} size={Size.LARGE} color={color} />;
             case ButtonType.TextButton: return <Button     {...btnProps} text={StrCast(this.rootDoc.buttonText)}/>;
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx
index 4ce359f3f..352e0fbdc 100644
--- a/src/client/views/nodes/ImageBox.tsx
+++ b/src/client/views/nodes/ImageBox.tsx
@@ -252,8 +252,8 @@ export class ImageBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
             funcs.push({
                 description: 'Open Image Editor',
                 event: action(() => {
-                    MainView.Instance.setImageEditorOpen(true);
-                    MainView.Instance.setImageEditorSource(this.choosePath(field.url));
+                    MainView.Instance.imageEditorOpen = true;
+                    MainView.Instance.imageEditorSource = this.choosePath(field.url);
                     MainView.Instance.addDoc = this.props.addDocument;
                     MainView.Instance.imageRootDoc = this.rootDoc;
                 }),
@@ -306,7 +306,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
     choosePath(url: URL) {
         const lower = url.href.toLowerCase();
         if (url.protocol === 'data') return url.href;
-        if (url.href.indexOf(window.location.origin) === -1 && url.href.indexOf("dashblobstore") === -1) return Utils.CorsProxy(url.href);
+        if (url.href.indexOf(window.location.origin) === -1 && url.href.indexOf('dashblobstore') === -1) return Utils.CorsProxy(url.href);
         if (!/\.(png|jpg|jpeg|gif|webp)$/.test(lower)) return `/assets/unknown-file-icon-hi.png`;
 
         const ext = extname(url.href);
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index 332f0f467..5acc45d02 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -946,44 +946,46 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
         console.log('Generate image from text: ', (this.dataDoc.text as RichTextField)?.Text);
         GPTPopup.Instance?.setTextAnchor(this.getAnchor(false));
         GPTPopup.Instance?.setImgTargetDoc(this.rootDoc);
-        GPTPopup.Instance.setImgUrls([]);
-        GPTPopup.Instance.setMode(GPTPopupMode.IMAGE);
-        GPTPopup.Instance.setVisible(true);
+        // GPTPopup.Instance.setImgUrls([]);
+        // GPTPopup.Instance.setMode(GPTPopupMode.IMAGE);
+        // GPTPopup.Instance.setVisible(true);
         GPTPopup.Instance.addToCollection = this.props.addDocument;
-        GPTPopup.Instance.setLoading(true);
-
-        try {
-            // make this support multiple images
-            let image_urls = await gptImageCall((this.dataDoc.text as RichTextField)?.Text);
-            console.log(image_urls);
-            if (image_urls) {
-                const [result] = await Networking.PostToServer('/uploadRemoteImage', { sources: [image_urls[0]] });
-                const source = Utils.prepend(result.accessPaths.agnostic.client);
-                GPTPopup.Instance.setImgUrls([source]);
-
-                // const newDoc = Docs.Create.ImageDocument(source, {
-                //     x: NumCast(this.rootDoc.x) + NumCast(this.layoutDoc._width) + 10,
-                //     y: NumCast(this.rootDoc.y),
-                //     _height: 200,
-                //     _width: 200,
-                //     data_nativeWidth: result.nativeWidth,
-                //     data_nativeHeight: result.nativeHeight,
-                // });
-                // if (Doc.IsInMyOverlay(this.rootDoc)) {
-                //     newDoc.overlayX = this.rootDoc.x;
-                //     newDoc.overlayY = NumCast(this.rootDoc.y) + NumCast(this.rootDoc._height);
-                //     Doc.AddToMyOverlay(newDoc);
-                // } else {
-                //     this.props.addDocument?.(newDoc);
-                // }
-                // // Create link between prompt and image
-                // DocUtils.MakeLink(this.rootDoc, newDoc, { link_relationship: 'Image Prompt' });
-            }
-        } catch (err) {
-            console.log(err);
-            return '';
-        }
-        GPTPopup.Instance.setLoading(false);
+        // GPTPopup.Instance.setLoading(true);
+        GPTPopup.Instance.setImgDesc((this.dataDoc.text as RichTextField)?.Text);
+        GPTPopup.Instance.generateImage();
+
+        // try {
+        //     // make this support multiple images
+        //     let image_urls = await gptImageCall((this.dataDoc.text as RichTextField)?.Text);
+        //     console.log(image_urls);
+        //     if (image_urls) {
+        //         const [result] = await Networking.PostToServer('/uploadRemoteImage', { sources: [image_urls[0]] });
+        //         const source = Utils.prepend(result.accessPaths.agnostic.client);
+        //         GPTPopup.Instance.setImgUrls([source]);
+
+        //         // const newDoc = Docs.Create.ImageDocument(source, {
+        //         //     x: NumCast(this.rootDoc.x) + NumCast(this.layoutDoc._width) + 10,
+        //         //     y: NumCast(this.rootDoc.y),
+        //         //     _height: 200,
+        //         //     _width: 200,
+        //         //     data_nativeWidth: result.nativeWidth,
+        //         //     data_nativeHeight: result.nativeHeight,
+        //         // });
+        //         // if (Doc.IsInMyOverlay(this.rootDoc)) {
+        //         //     newDoc.overlayX = this.rootDoc.x;
+        //         //     newDoc.overlayY = NumCast(this.rootDoc.y) + NumCast(this.rootDoc._height);
+        //         //     Doc.AddToMyOverlay(newDoc);
+        //         // } else {
+        //         //     this.props.addDocument?.(newDoc);
+        //         // }
+        //         // // Create link between prompt and image
+        //         // DocUtils.MakeLink(this.rootDoc, newDoc, { link_relationship: 'Image Prompt' });
+        //     }
+        // } catch (err) {
+        //     console.log(err);
+        //     return '';
+        // }
+        // GPTPopup.Instance.setLoading(false);
     };
 
     breakupDictation = () => {
diff --git a/src/client/views/nodes/generativeFill/GenerativeFill.tsx b/src/client/views/nodes/generativeFill/GenerativeFill.tsx
index f8f9fe077..99068d647 100644
--- a/src/client/views/nodes/generativeFill/GenerativeFill.tsx
+++ b/src/client/views/nodes/generativeFill/GenerativeFill.tsx
@@ -3,7 +3,7 @@ import React = require('react');
 import { useEffect, useRef, useState } from 'react';
 import { APISuccess, ImageUtility } from './generativeFillUtils/ImageHandler';
 import { BrushHandler } from './generativeFillUtils/BrushHandler';
-import { Box, IconButton, Slider, TextField } from '@mui/material';
+import { Box, Checkbox, FormControlLabel, IconButton, Slider, TextField } from '@mui/material';
 import { CursorData, Point } from './generativeFillUtils/generativeFillInterfaces';
 import { activeColor, canvasSize, eraserColor, freeformRenderSize, newCollectionSize, offsetDistanceY, offsetX } from './generativeFillUtils/generativeFillConstants';
 import { PointerHandler } from './generativeFillUtils/PointerHandler';
@@ -19,6 +19,7 @@ import { Cast, DocCast, NumCast } from '../../../../fields/Types';
 import { CollectionDockingView } from '../../collections/CollectionDockingView';
 import { OpenWhere, OpenWhereMod } from '../DocumentView';
 import { Oval } from 'react-loader-spinner';
+import { CheckBox } from '../../search/CheckBox';
 
 /**
  * For images not 1024x1024 fill in the rest in solid black, or a
@@ -72,6 +73,7 @@ const GenerativeFill = ({ imageEditorOpen, imageEditorSource, imageRootDoc, addD
     const [input, setInput] = useState('');
     const [loading, setLoading] = useState(false);
     const [saveLoading, setSaveLoading] = useState(false);
+    const [isNewCollection, setIsNewCollection] = useState(false);
     // the current image in the main canvas
     const currImg = useRef<HTMLImageElement | null>(null);
     // the unedited version of each generation (parent)
@@ -81,9 +83,6 @@ const GenerativeFill = ({ imageEditorOpen, imageEditorSource, imageRootDoc, addD
     // stores redo stack
     const redoStack = useRef<string[]>([]);
 
-    // early stage properly, likely will get rid of
-    const freeformPosition = useRef<number[]>([0, 0]);
-
     // which urls were already saved to canvas
     const savedSrcs = useRef<Set<string>>(new Set());
 
@@ -91,7 +90,6 @@ const GenerativeFill = ({ imageEditorOpen, imageEditorSource, imageRootDoc, addD
     const newCollectionRef = useRef<Doc | null>(null);
     const parentDoc = useRef<Doc | null>(null);
     const childrenDocs = useRef<Doc[]>([]);
-    const addToExistingCollection = useRef<boolean>(false);
 
     // Undo and Redo
     const handleUndo = () => {
@@ -111,10 +109,13 @@ const GenerativeFill = ({ imageEditorOpen, imageEditorSource, imageRootDoc, addD
     };
 
     const handleRedo = () => {
-        // TODO: handle undo as well
+        const ctx = ImageUtility.getCanvasContext(canvasRef);
+        if (!ctx || !currImg.current || !canvasRef.current) return;
+
         const target = redoStack.current[redoStack.current.length - 1];
         if (!target) {
         } else {
+            undoStack.current = [...undoStack.current, canvasRef.current?.toDataURL()];
             const img = new Image();
             img.src = target;
             ImageUtility.drawImgToCanvas(img, canvasRef);
@@ -188,7 +189,6 @@ const GenerativeFill = ({ imageEditorOpen, imageEditorSource, imageRootDoc, addD
         ImageUtility.drawImgToCanvas(img, canvasRef);
         currImg.current = img;
         originalImg.current = img;
-        freeformPosition.current = [0, 0];
 
         return () => {
             console.log('cleanup');
@@ -197,7 +197,6 @@ const GenerativeFill = ({ imageEditorOpen, imageEditorSource, imageRootDoc, addD
             childrenDocs.current = [];
             currImg.current = null;
             originalImg.current = null;
-            freeformPosition.current = [0, 0];
             undoStack.current = [];
             redoStack.current = [];
         };
@@ -266,24 +265,25 @@ const GenerativeFill = ({ imageEditorOpen, imageEditorSource, imageRootDoc, addD
 
             // create first image
             if (!newCollectionRef.current) {
-                if (addToExistingCollection.current) {
+                if (!isNewCollection) {
+                    // newcollection should stay null
+                } else {
+                    if (!(originalImg.current && imageRootDoc)) return;
+                    // create new collection and add it to the view
+                    newCollectionRef.current = Docs.Create.FreeformDocument([], {
+                        x: NumCast(imageRootDoc.x) + NumCast(imageRootDoc._width) + offsetX,
+                        y: NumCast(imageRootDoc.y),
+                        _width: newCollectionSize,
+                        _height: newCollectionSize,
+                        title: 'Image edit collection',
+                    });
+                    DocUtils.MakeLink(imageRootDoc, newCollectionRef.current, { link_relationship: 'Image Edit Version History', link_displayLine: false });
+                    // add the doc to the main freeform
+                    addDoc?.(newCollectionRef.current);
+                    await createNewImgDoc(originalImg.current, true);
                 }
-                if (!(originalImg.current && imageRootDoc)) return;
-                console.log('creating first image');
-                // create new collection and add it to the view
-                newCollectionRef.current = Docs.Create.FreeformDocument([], {
-                    x: NumCast(imageRootDoc.x) + NumCast(imageRootDoc._width) + offsetX,
-                    y: NumCast(imageRootDoc.y),
-                    _width: newCollectionSize,
-                    _height: newCollectionSize,
-                    title: 'Image edit collection',
-                });
-                DocUtils.MakeLink(imageRootDoc, newCollectionRef.current, { link_relationship: 'Image Edit Version History', link_displayLine: false });
-                // add the doc to the main freeform
-                // addDoc?.(newCollectionRef.current);
-                await createNewImgDoc(originalImg.current, true);
             } else {
-                parentDoc.current = childrenDocs.current[childrenDocs.current.length - 1];
+                // parentDoc.current = childrenDocs.current[childrenDocs.current.length - 1];
                 childrenDocs.current = [];
             }
 
@@ -292,12 +292,24 @@ const GenerativeFill = ({ imageEditorOpen, imageEditorSource, imageRootDoc, addD
             const { urls } = res as APISuccess;
             const image = new Image();
             image.src = urls[0];
+
+            // need to crop images agh
+            // save to dash
+
+            // const imageRes = await Promise.all(
+            //     urls.map(async url => {
+            //         const newImg = new Image();
+            //         newImg.src = url;
+            //         await onSave(newImg);
+            //     })
+            // );
+
+            // map each url to [url, imgDoc]
             setEdits(urls);
+
             ImageUtility.drawImgToCanvas(image, canvasRef);
             currImg.current = image;
-            onSave();
-            freeformPosition.current[0] += 1;
-            freeformPosition.current[1] = 0;
+            // onSave(currImg.current);
         } catch (err) {
             console.log(err);
         }
@@ -324,7 +336,7 @@ const GenerativeFill = ({ imageEditorOpen, imageEditorSource, imageRootDoc, addD
 
     // creates a new image document and returns its reference
     const createNewImgDoc = async (img: HTMLImageElement, firstDoc: boolean): Promise<Doc | undefined> => {
-        if (!newCollectionRef.current || !imageRootDoc) return;
+        if (!imageRootDoc) return;
         const src = img.src;
         const [result] = await Networking.PostToServer('/uploadRemoteImage', { sources: [src] });
         const source = Utils.prepend(result.accessPaths.agnostic.client);
@@ -332,7 +344,6 @@ const GenerativeFill = ({ imageEditorOpen, imageEditorSource, imageRootDoc, addD
         if (firstDoc) {
             const x = 0;
             const initialY = 0;
-            console.log('first doc');
 
             const newImg = Docs.Create.ImageDocument(source, {
                 x: x,
@@ -343,16 +354,19 @@ const GenerativeFill = ({ imageEditorOpen, imageEditorSource, imageRootDoc, addD
                 data_nativeHeight: result.nativeHeight,
             });
 
-            Doc.AddDocToList(newCollectionRef.current, undefined, newImg);
+            if (isNewCollection && newCollectionRef.current) {
+                Doc.AddDocToList(newCollectionRef.current, undefined, newImg);
+            } else {
+                addDoc?.(newImg);
+            }
+
             parentDoc.current = newImg;
             return newImg;
         } else {
             if (!parentDoc.current) return;
             const x = NumCast(parentDoc.current.x) + freeformRenderSize + offsetX;
             // dummy position
-            console.log('creating child elements');
             const initialY = 0;
-
             const newImg = Docs.Create.ImageDocument(source, {
                 x: x,
                 y: initialY,
@@ -363,21 +377,26 @@ const GenerativeFill = ({ imageEditorOpen, imageEditorSource, imageRootDoc, addD
             });
 
             childrenDocs.current.push(newImg);
+
+            if (isNewCollection && newCollectionRef.current) {
+                Doc.AddDocToList(newCollectionRef.current, undefined, newImg);
+            } else {
+                addDoc?.(newImg);
+            }
+
             DocUtils.MakeLink(parentDoc.current, newImg, { link_relationship: 'Image Edit', link_displayLine: true });
             adjustImgPositions();
-
-            Doc.AddDocToList(newCollectionRef.current, undefined, newImg);
             return newImg;
         }
     };
 
     // need to maybe call on every img click, not just when the save btn is clicked
-    const onSave = async () => {
+    const onSave = async (img: HTMLImageElement) => {
         setSaveLoading(true);
-        if (!currImg.current || !originalImg.current || !imageRootDoc) return;
+        // if (!currImg.current || !originalImg.current || !imageRootDoc) return;
         try {
             console.log('creating another image');
-            await createNewImgDoc(currImg.current, false);
+            await createNewImgDoc(img, false);
         } catch (err) {
             console.log(err);
         }
@@ -387,7 +406,7 @@ const GenerativeFill = ({ imageEditorOpen, imageEditorSource, imageRootDoc, addD
     const handleViewClose = () => {
         if (newCollectionRef.current) {
             newCollectionRef.current.fitContentOnce = true;
-            CollectionDockingView.AddSplit(newCollectionRef.current, OpenWhereMod.right);
+            // CollectionDockingView.AddSplit(newCollectionRef.current, OpenWhereMod.right);
         }
         MainView.Instance.setImageEditorOpen(false);
         MainView.Instance.setImageEditorSource('');
@@ -399,7 +418,20 @@ const GenerativeFill = ({ imageEditorOpen, imageEditorSource, imageRootDoc, addD
             <div className="generativeFillControls">
                 <h1>AI Image Editor</h1>
                 <div style={{ display: 'flex', alignItems: 'center', gap: '1.5rem' }}>
-                    <Buttons canvasRef={canvasRef} currImg={currImg} getEdit={getEdit} loading={loading} onSave={onSave} onReset={handleReset} />
+                    <FormControlLabel
+                        control={
+                            <Checkbox
+                                checked={isNewCollection}
+                                onChange={e => {
+                                    setIsNewCollection(prev => !prev);
+                                }}
+                            />
+                        }
+                        label={'Create New Collection'}
+                        labelPlacement="end"
+                        sx={{ whiteSpace: 'nowrap' }}
+                    />
+                    <Buttons canvasRef={canvasRef} currImg={currImg} getEdit={getEdit} loading={loading} onReset={handleReset} />
                     <IconButton onClick={handleViewClose}>
                         <BsX color={activeColor} />
                     </IconButton>
@@ -491,13 +523,14 @@ const GenerativeFill = ({ imageEditorOpen, imageEditorSource, imageRootDoc, addD
                             height={100}
                             src={edit}
                             onClick={async () => {
-                                // if (savedSrcs.current.has(edit)) return;
                                 const img = new Image();
                                 img.src = edit;
                                 ImageUtility.drawImgToCanvas(img, canvasRef);
                                 currImg.current = img;
                                 savedSrcs.current.add(edit);
-                                await onSave();
+                                undoStack.current = [];
+                                redoStack.current = [];
+                                await onSave(img);
                             }}
                         />
                     ))}
diff --git a/src/client/views/nodes/generativeFill/GenerativeFillButtons.tsx b/src/client/views/nodes/generativeFill/GenerativeFillButtons.tsx
index 53c6cec84..b4d56b408 100644
--- a/src/client/views/nodes/generativeFill/GenerativeFillButtons.tsx
+++ b/src/client/views/nodes/generativeFill/GenerativeFillButtons.tsx
@@ -11,14 +11,10 @@ interface ButtonContainerProps {
     currImg: React.MutableRefObject<HTMLImageElement | null>;
     getEdit: () => Promise<void>;
     loading: boolean;
-    onSave: () => Promise<void>;
     onReset: () => void;
 }
 
-const Buttons = ({ canvasRef, currImg, loading, getEdit, onSave, onReset }: ButtonContainerProps) => {
-    const handleSave = () => {
-        onSave();
-    };
+const Buttons = ({ canvasRef, currImg, loading, getEdit, onReset }: ButtonContainerProps) => {
 
     return (
         <div className="generativeFillBtnContainer">
diff --git a/src/client/views/pdf/AnchorMenu.tsx b/src/client/views/pdf/AnchorMenu.tsx
index 7404650d6..1be8fe6ab 100644
--- a/src/client/views/pdf/AnchorMenu.tsx
+++ b/src/client/views/pdf/AnchorMenu.tsx
@@ -130,6 +130,7 @@ export class AnchorMenu extends AntimodeMenu<AntimodeMenuProps> {
      * @param e pointer down event
      */
     gptSummarize = async (e: React.PointerEvent) => {
+        // move this logic to gptpopup, need to implement generate again
         GPTPopup.Instance.setVisible(true);
         this.setHighlightRange(undefined);
         GPTPopup.Instance.setMode(GPTPopupMode.SUMMARY);
diff --git a/src/client/views/pdf/GPTPopup/GPTPopup.scss b/src/client/views/pdf/GPTPopup/GPTPopup.scss
index 478b7d4ba..5d966395c 100644
--- a/src/client/views/pdf/GPTPopup/GPTPopup.scss
+++ b/src/client/views/pdf/GPTPopup/GPTPopup.scss
@@ -123,9 +123,11 @@ $highlightedText: #82e0ff;
         cursor: pointer;
 
         .img-container {
+            pointer-events: none;
             position: relative;
 
             img {
+                pointer-events: all;
                 position: relative;
             }
         }
diff --git a/src/client/views/pdf/GPTPopup/GPTPopup.tsx b/src/client/views/pdf/GPTPopup/GPTPopup.tsx
index fc6fc1af8..943c38d42 100644
--- a/src/client/views/pdf/GPTPopup/GPTPopup.tsx
+++ b/src/client/views/pdf/GPTPopup/GPTPopup.tsx
@@ -10,6 +10,11 @@ import { DocUtils, Docs } from '../../../documents/Documents';
 import { Button, IconButton, Type } from 'browndash-components';
 import { NumCast, StrCast } from '../../../../fields/Types';
 import { CgClose } from 'react-icons/cg';
+import { AnchorMenu } from '../AnchorMenu';
+import { gptAPICall, gptImageCall } from '../../../apis/gpt/GPT';
+import { RichTextField } from '../../../../fields/RichTextField';
+import { Networking } from '../../../Network';
+import { Utils } from '../../../../Utils';
 
 export enum GPTPopupMode {
     SUMMARY,
@@ -43,10 +48,17 @@ export class GPTPopup extends React.Component<GPTPopupProps> {
     };
 
     @observable
-    public imageUrls: string[] = [];
+    public imgDesc: string = '';
     @action
-    public setImgUrls = (imgs: string[]) => {
-        this.imageUrls = imgs;
+    public setImgDesc = (text: string) => {
+        this.imgDesc = text;
+    };
+
+    @observable
+    public imgUrls: string[][] = [];
+    @action
+    public setImgUrls = (imgs: string[][]) => {
+        this.imgUrls = imgs;
     };
 
     @observable
@@ -102,6 +114,30 @@ export class GPTPopup extends React.Component<GPTPopupProps> {
     public addDoc: (doc: Doc | Doc[], sidebarKey?: string | undefined) => boolean = () => false;
     public addToCollection: ((doc: Doc | Doc[], annotationKey?: string | undefined) => boolean) | undefined;
 
+    generateImage = async () => {
+        if (this.imgDesc === '') return;
+        this.setImgUrls([]);
+        this.setMode(GPTPopupMode.IMAGE);
+        this.setVisible(true);
+        this.setLoading(true);
+
+        try {
+            // make this support multiple images
+            let image_urls = await gptImageCall(this.imgDesc);
+            console.log(image_urls);
+            if (image_urls && image_urls[0]) {
+                const [result] = await Networking.PostToServer('/uploadRemoteImage', { sources: [image_urls[0]] });
+                const source = Utils.prepend(result.accessPaths.agnostic.client);
+                console.log('Source', source);
+                this.setImgUrls([[image_urls[0], source]]);
+            }
+        } catch (err) {
+            console.log(err);
+            return '';
+        }
+        GPTPopup.Instance.setLoading(false);
+    };
+
     /**
      * Transfers the summarization text to a sidebar annotation text document.
      */
@@ -113,8 +149,9 @@ export class GPTPopup extends React.Component<GPTPopupProps> {
             _layout_autoHeight: true,
         });
         this.addDoc(newDoc, this.sidebarId);
-        if (this.targetAnchor) {
-            DocUtils.MakeLink(newDoc, this.targetAnchor, {
+        const anchor = AnchorMenu.Instance?.GetAnchor(undefined, false);
+        if (anchor) {
+            DocUtils.MakeLink(newDoc, anchor, {
                 link_relationship: 'GPT Summary',
             });
         }
@@ -163,17 +200,22 @@ export class GPTPopup extends React.Component<GPTPopupProps> {
             <div style={{ display: 'flex', flexDirection: 'column', gap: '1rem' }}>
                 {this.heading('GENERATED IMAGE')}
                 <div className="image-content-wrapper">
-                    {this.imageUrls.map(rawSrc => (
+                    {this.imgUrls.map(rawSrc => (
                         <div className="img-wrapper">
                             <div className="img-container">
-                                <img key={rawSrc} src={this.getPreviewUrl(rawSrc)} width={150} height={150} alt="dalle generation" />
+                                <img key={rawSrc[0]} src={rawSrc[0]} width={150} height={150} alt="dalle generation" />
                             </div>
                             <div className="btn-container">
-                                <Button text="Save Image" onClick={() => this.transferToImage(rawSrc)} color={StrCast(Doc.UserDoc().userColor)} type={Type.TERT} />
+                                <Button text="Save Image" onClick={() => this.transferToImage(rawSrc[1])} color={StrCast(Doc.UserDoc().userColor)} type={Type.TERT} />
                             </div>
                         </div>
                     ))}
                 </div>
+                {!this.loading && (
+                    <>
+                        <IconButton tooltip="Generate Again" onClick={this.generateImage} icon={<FontAwesomeIcon icon="redo-alt" size="lg" />} color={StrCast(Doc.UserDoc().userVariantColor)} />
+                    </>
+                )}
             </div>
         );
     };
@@ -227,43 +269,6 @@ export class GPTPopup extends React.Component<GPTPopupProps> {
         </>
     );
 
-    editBox = () => {
-        const hr = this.highlightRange;
-        return (
-            <>
-                <div>
-                    {this.heading('TEXT EDIT SUGGESTIONS')}
-                    <div className="content-wrapper">
-                        {hr && (
-                            <div>
-                                {this.text.slice(0, hr[0])} <span className="highlighted-text">{this.text.slice(hr[0], hr[1])}</span> {this.text.slice(hr[1])}
-                            </div>
-                        )}
-                    </div>
-                </div>
-                {hr && !this.loading && (
-                    <>
-                        <div className="btns-wrapper">
-                            <>
-                                <button className="icon-btn" onPointerDown={this.callEditApi}>
-                                    <FontAwesomeIcon icon="redo-alt" size="lg" />
-                                </button>
-                                <button
-                                    className="text-btn"
-                                    onClick={e => {
-                                        this.replaceText(this.text);
-                                    }}>
-                                    Replace Text
-                                </button>
-                            </>
-                        </div>
-                        {this.aiWarning()}
-                    </>
-                )}
-            </>
-        );
-    };
-
     aiWarning = () =>
         this.done ? (
             <div className="ai-warning">
@@ -277,14 +282,14 @@ export class GPTPopup extends React.Component<GPTPopupProps> {
     heading = (headingText: string) => (
         <div className="summary-heading">
             <label className="summary-text">{headingText}</label>
-            {this.loading ? <ReactLoading type="spin" color="#bcbcbc" width={14} height={14} /> : <IconButton color={StrCast(Doc.UserDoc().userColor)} tooltip="close" icon={<CgClose size="16px" />} onClick={() => this.setVisible(false)} />}
+            {this.loading ? <ReactLoading type="spin" color="#bcbcbc" width={14} height={14} /> : <IconButton color={StrCast(Doc.UserDoc().userVariantColor)} tooltip="close" icon={<CgClose size="16px" />} onClick={() => this.setVisible(false)} />}
         </div>
     );
 
     render() {
         return (
             <div className="summary-box" style={{ display: this.visible ? 'flex' : 'none' }}>
-                {this.mode === GPTPopupMode.SUMMARY ? this.summaryBox() : this.mode === GPTPopupMode.IMAGE ? this.imageBox() : this.editBox()}
+                {this.mode === GPTPopupMode.SUMMARY ? this.summaryBox() : this.mode === GPTPopupMode.IMAGE ? this.imageBox() : <></>}
             </div>
         );
     }
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index c9fee4813..1319a236d 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -424,10 +424,6 @@ export class PDFViewer extends React.Component<IViewerProps> {
 
         // Changing which document to add the annotation to (the currently selected PDF)
         GPTPopup.Instance.setSidebarId('data_sidebar');
-        const anchor = this._getAnchor(undefined, false);
-        if (anchor) {
-            GPTPopup.Instance.setTargetAnchor(anchor);
-        }
         GPTPopup.Instance.addDoc = this.props.sidebarAddDoc;
     };
 
-- 
cgit v1.2.3-70-g09d2


From bdabb0eb1aeac9ea9d4f1fa40889b8d30937c1f0 Mon Sep 17 00:00:00 2001
From: monoguitari <113245090+monoguitari@users.noreply.github.com>
Date: Sat, 19 Aug 2023 03:22:16 -0400
Subject: Toggling icon for mic and added webcapturedoc to dropdown

---
 src/client/util/CurrentUserUtils.ts                |  8 +++-
 src/client/views/UndoStack.tsx                     |  4 +-
 src/client/views/nodes/FontIconBox/FontIconBox.tsx |  4 +-
 .../views/nodes/RecordingBox/RecordingBox.tsx      | 47 ++++++++++++++++++++--
 .../views/nodes/RecordingBox/RecordingView.tsx     |  3 +-
 src/client/views/nodes/trails/PresElementBox.tsx   |  2 +-
 6 files changed, 56 insertions(+), 12 deletions(-)

(limited to 'src/client/views/nodes/FontIconBox/FontIconBox.tsx')

diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 25c8f511b..54828867e 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -714,7 +714,9 @@ export class CurrentUserUtils {
             { title: "View",    icon: "View",          toolTip: "View tools",           subMenu: CurrentUserUtils.viewTools(),   expertMode: false, toolType:CollectionViewType.Freeform, funcs: {hidden: `!SelectionManager_selectedDocType(self.toolType, self.expertMode)`, linearView_IsOpen: `SelectionManager_selectedDocType(self.toolType, self.expertMode)`} }, // Always available
             { title: "Web",     icon: "Web",           toolTip: "Web functions",        subMenu: CurrentUserUtils.webTools(),    expertMode: false, toolType:DocumentType.WEB,            funcs: {hidden: `!SelectionManager_selectedDocType(self.toolType, self.expertMode)`, linearView_IsOpen: `SelectionManager_selectedDocType(self.toolType, self.expertMode)`} }, // Only when Web is selected
             { title: "Schema",  icon: "Schema",linearBtnWidth:58,toolTip: "Schema functions",subMenu: CurrentUserUtils.schemaTools(), expertMode: false, toolType:CollectionViewType.Schema,   funcs: {hidden: `!SelectionManager_selectedDocType(self.toolType, self.expertMode)`, linearView_IsOpen: `SelectionManager_selectedDocType(self.toolType, self.expertMode)`} }, // Only when Schema is selected
-            { title: "Audio",   icon: "microphone",    toolTip: "Dictate",              btnType: ButtonType.ToggleButton,        expertMode: false,                                                                                                          ignoreClick: true,             scripts: { onClick:  'return toggleRecording(_readOnly_)'}, funcs: { }}
+            { title: "Audio",   icon: 'microphone',    toolTip: "Dictate",              btnType: ButtonType.ToggleButton,        expertMode: false,                                       funcs: {hidden: `getIsRecording()`},                                                                  ignoreClick: true,             scripts: { onClick:  'return toggleRecording(_readOnly_)'},},
+            { title: "StopRec", icon: "stop",          toolTip: "Stop",                 btnType: ButtonType.ToggleButton,        expertMode: false,                                       funcs: {hidden: `!getIsRecording()`},                                                                  ignoreClick: true,             scripts: { onClick: `return toggleRecording(_readOnly_)`}},
+            { title: "Dropdown",                       toolTip: "Workspace Recordings", btnType: ButtonType.DropdownList,        expertMode: false,                                       funcs: {btnList: `getWorkspaceRecordings()`},                                                         ignoreClick: true,             scripts: { script: `toggleRecPlayback(value)`}, },
         ];
     }
 
@@ -737,6 +739,8 @@ export class CurrentUserUtils {
     static setupContextMenuBtn(params:Button, menuDoc:Doc):Doc {
         const menuBtnDoc = DocListCast(menuDoc?.data).find(doc => doc.title === params.title);
         const subMenu = params.subMenu;
+        Doc.UserDoc().workspaceRecordings = new List<Doc>;
+        Doc.UserDoc().isRecording = false;
         if (!subMenu) { // button does not have a sub menu
             return this.setupContextMenuButton(params, menuBtnDoc);
         }  
@@ -999,4 +1003,4 @@ ScriptingGlobals.add(function createNewPresentation() { return MainView.Instance
 ScriptingGlobals.add(function openPresentation(pres:Doc) { return MainView.Instance.openPresentation(pres); }, "creates a new presentation when called");
 ScriptingGlobals.add(function createNewFolder() { return MainView.Instance.createNewFolder(); }, "creates a new folder in myFiles when called");
 ScriptingGlobals.add(function importDocument() { return CurrentUserUtils.importDocument(); }, "imports files from device directly into the import sidebar");
-ScriptingGlobals.add(function setInkToolDefaults() { Doc.ActiveTool = InkTool.None; });
\ No newline at end of file
+ScriptingGlobals.add(function setInkToolDefaults() { Doc.ActiveTool = InkTool.None; });
diff --git a/src/client/views/UndoStack.tsx b/src/client/views/UndoStack.tsx
index a551e5332..813cdd050 100644
--- a/src/client/views/UndoStack.tsx
+++ b/src/client/views/UndoStack.tsx
@@ -37,7 +37,7 @@ export class UndoStack extends React.Component<UndoStackProps> {
                             }}>
                             {UndoManager.undoStackNames.map((name, i) => (
                                 <div className="undoStack-resultContainer" key={i}>
-                                    <div className="undoStack-commandString">{name.replace(/[^\.]*\./, '')}</div>
+                                    <div className="undoStack-commandString">{StrCast(name).replace(/[^\.]*\./, '')}</div>
                                 </div>
                             ))}
                             {Array.from(UndoManager.redoStackNames)
@@ -45,7 +45,7 @@ export class UndoStack extends React.Component<UndoStackProps> {
                                 .map((name, i) => (
                                     <div className="undoStack-resultContainer" key={i}>
                                         <div className="undoStack-commandString" style={{ fontWeight: 'bold', color: 'red' }}>
-                                            {name.replace(/[^\.]*\./, '')}
+                                            {StrCast(name).replace(/[^\.]*\./, '')}
                                         </div>
                                     </div>
                                 ))}
diff --git a/src/client/views/nodes/FontIconBox/FontIconBox.tsx b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
index 5ff5f7bfa..41ad90155 100644
--- a/src/client/views/nodes/FontIconBox/FontIconBox.tsx
+++ b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
@@ -6,7 +6,7 @@ import { observer } from 'mobx-react';
 import * as React from 'react';
 import { Doc, DocListCast, StrListCast } from '../../../../fields/Doc';
 import { ScriptField } from '../../../../fields/ScriptField';
-import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from '../../../../fields/Types';
+import { BoolCast, Cast, DocCast, NumCast, ScriptCast, StrCast } from '../../../../fields/Types';
 import { CollectionViewType, DocumentType } from '../../../documents/DocumentTypes';
 import { SelectionManager } from '../../../util/SelectionManager';
 import { undoable, UndoManager } from '../../../util/UndoManager';
@@ -242,7 +242,7 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
         const list: IListItemProps[] = this.buttonList
             .filter(value => !Doc.noviceMode || !noviceList.length || noviceList.includes(value))
             .map(value => ({
-                text: value.charAt(0).toUpperCase() + value.slice(1),
+                text: value === "string" ? value.charAt(0).toUpperCase() + value.slice(1) : StrCast(DocCast(value)?.title),
                 val: value,
                 style: getStyle(value),
                 onClick: undoable(() => script.script.run({ this: this.layoutDoc, self: this.rootDoc, value }), value),
diff --git a/src/client/views/nodes/RecordingBox/RecordingBox.tsx b/src/client/views/nodes/RecordingBox/RecordingBox.tsx
index 8fa2861b6..3237ce6cd 100644
--- a/src/client/views/nodes/RecordingBox/RecordingBox.tsx
+++ b/src/client/views/nodes/RecordingBox/RecordingBox.tsx
@@ -15,6 +15,8 @@ import { BoolCast, DocCast } from '../../../../fields/Types';
 import { ScriptingGlobals } from '../../../util/ScriptingGlobals';
 import { DocumentManager } from '../../../util/DocumentManager';
 import { Docs } from '../../../documents/Documents';
+import { CollectionFreeFormView } from '../../collections/collectionFreeForm/CollectionFreeFormView';
+import { CurrentUserUtils } from '../../../util/CurrentUserUtils';
 
 @observer
 export class RecordingBox extends ViewBoxBaseComponent<FieldViewProps>() {
@@ -82,27 +84,64 @@ export class RecordingBox extends ViewBoxBaseComponent<FieldViewProps>() {
     static screengrabber: RecordingBox | undefined;
 }
 ScriptingGlobals.add(function toggleRecording(_readOnly_: boolean) {
+    console.log(_readOnly_)
+    console.log(RecordingBox.screengrabber)
     if (_readOnly_) return RecordingBox.screengrabber ? true : false;
     if (RecordingBox.screengrabber) {
+        //if recordingbox is true; when we press the stop button. changed vals temporarily to see if changes happening
+        console.log('grabbing screen!')
         RecordingBox.screengrabber.Pause?.();
         setTimeout(() => {
             RecordingBox.screengrabber?.Finish?.();
-            RecordingBox.screengrabber!.rootDoc.overlayX = 100;
+            RecordingBox.screengrabber!.rootDoc.overlayX = 400; //was 100
             RecordingBox.screengrabber!.rootDoc.overlayY = 100;
+            console.log(RecordingBox.screengrabber?.rootDoc)
             RecordingBox.screengrabber = undefined;
         }, 100);
+        Doc.UserDoc().isRecording = false;
+        // console.log(RecordingBox.screengrabber.dataDoc);
+        // Doc.AddDocToList(Doc.UserDoc(), "workspaceRecordings", RecordingBox.screengrabber.dataDoc);
+        Doc.AddDocToList(Doc.UserDoc(), "workspaceRecordings", RecordingBox.screengrabber.rootDoc);
+        // console.log(RecordingBox.screengrabber.rootDoc)
+        // console.log(RecordingBox.screengrabber.dataDoc.data?.valueOf);
     } else {
+        //when we first press mic
         const screengrabber = Docs.Create.WebCamDocument('', {
             _width: 384,
             _height: 216,
         });
-        screengrabber.overlayX = -400;
-        screengrabber.overlayY = 0;
+        // Doc.UserDoc().currentScreenGrab = screengrabber;
+        screengrabber.overlayX = 100; //was -400
+        screengrabber.overlayY = 100; //was 0
         screengrabber[Doc.LayoutFieldKey(screengrabber) + '_trackScreen'] = true;
-        Doc.AddToMyOverlay(screengrabber);
+        Doc.AddToMyOverlay(screengrabber);  //just adds doc to overlay
         DocumentManager.Instance.AddViewRenderedCb(screengrabber, docView => {
             RecordingBox.screengrabber = docView.ComponentView as RecordingBox;
             RecordingBox.screengrabber.Record?.();
         });
+        // Doc.AddDocToList(Doc.UserDoc(), "workspaceRecordings", screengrabber);
+        Doc.UserDoc().isRecording = true;
+        
     }
 }, 'toggle recording');
+ScriptingGlobals.add(function toggleRecPlayback(value: Doc) {
+    console.log(value)
+    const screenvid = Docs.Create.VideoDocument('', {_width: 384, _height: 216});
+    
+    let ffView = Array.from(DocumentManager.Instance.DocumentViews).find(view => view.ComponentView instanceof CollectionFreeFormView);
+    (ffView?.ComponentView as CollectionFreeFormView).props.addDocument?.(value); 
+
+});
+
+ScriptingGlobals.add(function getCurrRecording() {
+    console.log(RecordingBox.screengrabber);
+});
+ScriptingGlobals.add(function getWorkspaceRecordings() {
+    return Doc.UserDoc().workspaceRecordings
+});
+ScriptingGlobals.add(function getIsRecording() {
+    return Doc.UserDoc().isRecording;
+})
+
+
+
diff --git a/src/client/views/nodes/RecordingBox/RecordingView.tsx b/src/client/views/nodes/RecordingBox/RecordingView.tsx
index 0e386b093..8c0f5efef 100644
--- a/src/client/views/nodes/RecordingBox/RecordingView.tsx
+++ b/src/client/views/nodes/RecordingBox/RecordingView.tsx
@@ -163,8 +163,9 @@ export function RecordingView(props: IRecordingViewProps) {
     // if this is called, then we're done recording all the segments
     const finish = () => {
         // call stop on the video recorder if active
+        console.log(videoRecorder.current?.state);
         videoRecorder.current?.state !== 'inactive' && videoRecorder.current?.stop();
-
+        console.log("this it")
         // end the streams (audio/video) to remove recording icon
         const stream = videoElementRef.current!.srcObject;
         stream instanceof MediaStream && stream.getTracks().forEach(track => track.stop());
diff --git a/src/client/views/nodes/trails/PresElementBox.tsx b/src/client/views/nodes/trails/PresElementBox.tsx
index aa514be3b..5de51dbe9 100644
--- a/src/client/views/nodes/trails/PresElementBox.tsx
+++ b/src/client/views/nodes/trails/PresElementBox.tsx
@@ -365,7 +365,7 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() {
 
     @undoBatch
     @action
-    startRecording = (e: React.MouseEvent, activeItem: Doc) => {
+    startRecording =    (e: React.MouseEvent, activeItem: Doc) => {
         e.stopPropagation();
         if (PresElementBox.videoIsRecorded(activeItem)) {
             // if we already have an existing recording
-- 
cgit v1.2.3-70-g09d2


From 2466587655888d5894159b942f09661ab73ebe66 Mon Sep 17 00:00:00 2001
From: monoguitari <113245090+monoguitari@users.noreply.github.com>
Date: Sat, 19 Aug 2023 08:33:14 -0400
Subject: Revert "Toggling icon for mic and added webcapturedoc to dropdown"

This reverts commit bdabb0eb1aeac9ea9d4f1fa40889b8d30937c1f0.
---
 src/client/util/CurrentUserUtils.ts                |  8 +---
 src/client/views/UndoStack.tsx                     |  4 +-
 src/client/views/nodes/FontIconBox/FontIconBox.tsx |  4 +-
 .../views/nodes/RecordingBox/RecordingBox.tsx      | 47 ++--------------------
 .../views/nodes/RecordingBox/RecordingView.tsx     |  3 +-
 src/client/views/nodes/trails/PresElementBox.tsx   |  2 +-
 6 files changed, 12 insertions(+), 56 deletions(-)

(limited to 'src/client/views/nodes/FontIconBox/FontIconBox.tsx')

diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 54828867e..25c8f511b 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -714,9 +714,7 @@ export class CurrentUserUtils {
             { title: "View",    icon: "View",          toolTip: "View tools",           subMenu: CurrentUserUtils.viewTools(),   expertMode: false, toolType:CollectionViewType.Freeform, funcs: {hidden: `!SelectionManager_selectedDocType(self.toolType, self.expertMode)`, linearView_IsOpen: `SelectionManager_selectedDocType(self.toolType, self.expertMode)`} }, // Always available
             { title: "Web",     icon: "Web",           toolTip: "Web functions",        subMenu: CurrentUserUtils.webTools(),    expertMode: false, toolType:DocumentType.WEB,            funcs: {hidden: `!SelectionManager_selectedDocType(self.toolType, self.expertMode)`, linearView_IsOpen: `SelectionManager_selectedDocType(self.toolType, self.expertMode)`} }, // Only when Web is selected
             { title: "Schema",  icon: "Schema",linearBtnWidth:58,toolTip: "Schema functions",subMenu: CurrentUserUtils.schemaTools(), expertMode: false, toolType:CollectionViewType.Schema,   funcs: {hidden: `!SelectionManager_selectedDocType(self.toolType, self.expertMode)`, linearView_IsOpen: `SelectionManager_selectedDocType(self.toolType, self.expertMode)`} }, // Only when Schema is selected
-            { title: "Audio",   icon: 'microphone',    toolTip: "Dictate",              btnType: ButtonType.ToggleButton,        expertMode: false,                                       funcs: {hidden: `getIsRecording()`},                                                                  ignoreClick: true,             scripts: { onClick:  'return toggleRecording(_readOnly_)'},},
-            { title: "StopRec", icon: "stop",          toolTip: "Stop",                 btnType: ButtonType.ToggleButton,        expertMode: false,                                       funcs: {hidden: `!getIsRecording()`},                                                                  ignoreClick: true,             scripts: { onClick: `return toggleRecording(_readOnly_)`}},
-            { title: "Dropdown",                       toolTip: "Workspace Recordings", btnType: ButtonType.DropdownList,        expertMode: false,                                       funcs: {btnList: `getWorkspaceRecordings()`},                                                         ignoreClick: true,             scripts: { script: `toggleRecPlayback(value)`}, },
+            { title: "Audio",   icon: "microphone",    toolTip: "Dictate",              btnType: ButtonType.ToggleButton,        expertMode: false,                                                                                                          ignoreClick: true,             scripts: { onClick:  'return toggleRecording(_readOnly_)'}, funcs: { }}
         ];
     }
 
@@ -739,8 +737,6 @@ export class CurrentUserUtils {
     static setupContextMenuBtn(params:Button, menuDoc:Doc):Doc {
         const menuBtnDoc = DocListCast(menuDoc?.data).find(doc => doc.title === params.title);
         const subMenu = params.subMenu;
-        Doc.UserDoc().workspaceRecordings = new List<Doc>;
-        Doc.UserDoc().isRecording = false;
         if (!subMenu) { // button does not have a sub menu
             return this.setupContextMenuButton(params, menuBtnDoc);
         }  
@@ -1003,4 +999,4 @@ ScriptingGlobals.add(function createNewPresentation() { return MainView.Instance
 ScriptingGlobals.add(function openPresentation(pres:Doc) { return MainView.Instance.openPresentation(pres); }, "creates a new presentation when called");
 ScriptingGlobals.add(function createNewFolder() { return MainView.Instance.createNewFolder(); }, "creates a new folder in myFiles when called");
 ScriptingGlobals.add(function importDocument() { return CurrentUserUtils.importDocument(); }, "imports files from device directly into the import sidebar");
-ScriptingGlobals.add(function setInkToolDefaults() { Doc.ActiveTool = InkTool.None; });
+ScriptingGlobals.add(function setInkToolDefaults() { Doc.ActiveTool = InkTool.None; });
\ No newline at end of file
diff --git a/src/client/views/UndoStack.tsx b/src/client/views/UndoStack.tsx
index 813cdd050..a551e5332 100644
--- a/src/client/views/UndoStack.tsx
+++ b/src/client/views/UndoStack.tsx
@@ -37,7 +37,7 @@ export class UndoStack extends React.Component<UndoStackProps> {
                             }}>
                             {UndoManager.undoStackNames.map((name, i) => (
                                 <div className="undoStack-resultContainer" key={i}>
-                                    <div className="undoStack-commandString">{StrCast(name).replace(/[^\.]*\./, '')}</div>
+                                    <div className="undoStack-commandString">{name.replace(/[^\.]*\./, '')}</div>
                                 </div>
                             ))}
                             {Array.from(UndoManager.redoStackNames)
@@ -45,7 +45,7 @@ export class UndoStack extends React.Component<UndoStackProps> {
                                 .map((name, i) => (
                                     <div className="undoStack-resultContainer" key={i}>
                                         <div className="undoStack-commandString" style={{ fontWeight: 'bold', color: 'red' }}>
-                                            {StrCast(name).replace(/[^\.]*\./, '')}
+                                            {name.replace(/[^\.]*\./, '')}
                                         </div>
                                     </div>
                                 ))}
diff --git a/src/client/views/nodes/FontIconBox/FontIconBox.tsx b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
index 41ad90155..5ff5f7bfa 100644
--- a/src/client/views/nodes/FontIconBox/FontIconBox.tsx
+++ b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
@@ -6,7 +6,7 @@ import { observer } from 'mobx-react';
 import * as React from 'react';
 import { Doc, DocListCast, StrListCast } from '../../../../fields/Doc';
 import { ScriptField } from '../../../../fields/ScriptField';
-import { BoolCast, Cast, DocCast, NumCast, ScriptCast, StrCast } from '../../../../fields/Types';
+import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from '../../../../fields/Types';
 import { CollectionViewType, DocumentType } from '../../../documents/DocumentTypes';
 import { SelectionManager } from '../../../util/SelectionManager';
 import { undoable, UndoManager } from '../../../util/UndoManager';
@@ -242,7 +242,7 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
         const list: IListItemProps[] = this.buttonList
             .filter(value => !Doc.noviceMode || !noviceList.length || noviceList.includes(value))
             .map(value => ({
-                text: value === "string" ? value.charAt(0).toUpperCase() + value.slice(1) : StrCast(DocCast(value)?.title),
+                text: value.charAt(0).toUpperCase() + value.slice(1),
                 val: value,
                 style: getStyle(value),
                 onClick: undoable(() => script.script.run({ this: this.layoutDoc, self: this.rootDoc, value }), value),
diff --git a/src/client/views/nodes/RecordingBox/RecordingBox.tsx b/src/client/views/nodes/RecordingBox/RecordingBox.tsx
index 3237ce6cd..8fa2861b6 100644
--- a/src/client/views/nodes/RecordingBox/RecordingBox.tsx
+++ b/src/client/views/nodes/RecordingBox/RecordingBox.tsx
@@ -15,8 +15,6 @@ import { BoolCast, DocCast } from '../../../../fields/Types';
 import { ScriptingGlobals } from '../../../util/ScriptingGlobals';
 import { DocumentManager } from '../../../util/DocumentManager';
 import { Docs } from '../../../documents/Documents';
-import { CollectionFreeFormView } from '../../collections/collectionFreeForm/CollectionFreeFormView';
-import { CurrentUserUtils } from '../../../util/CurrentUserUtils';
 
 @observer
 export class RecordingBox extends ViewBoxBaseComponent<FieldViewProps>() {
@@ -84,64 +82,27 @@ export class RecordingBox extends ViewBoxBaseComponent<FieldViewProps>() {
     static screengrabber: RecordingBox | undefined;
 }
 ScriptingGlobals.add(function toggleRecording(_readOnly_: boolean) {
-    console.log(_readOnly_)
-    console.log(RecordingBox.screengrabber)
     if (_readOnly_) return RecordingBox.screengrabber ? true : false;
     if (RecordingBox.screengrabber) {
-        //if recordingbox is true; when we press the stop button. changed vals temporarily to see if changes happening
-        console.log('grabbing screen!')
         RecordingBox.screengrabber.Pause?.();
         setTimeout(() => {
             RecordingBox.screengrabber?.Finish?.();
-            RecordingBox.screengrabber!.rootDoc.overlayX = 400; //was 100
+            RecordingBox.screengrabber!.rootDoc.overlayX = 100;
             RecordingBox.screengrabber!.rootDoc.overlayY = 100;
-            console.log(RecordingBox.screengrabber?.rootDoc)
             RecordingBox.screengrabber = undefined;
         }, 100);
-        Doc.UserDoc().isRecording = false;
-        // console.log(RecordingBox.screengrabber.dataDoc);
-        // Doc.AddDocToList(Doc.UserDoc(), "workspaceRecordings", RecordingBox.screengrabber.dataDoc);
-        Doc.AddDocToList(Doc.UserDoc(), "workspaceRecordings", RecordingBox.screengrabber.rootDoc);
-        // console.log(RecordingBox.screengrabber.rootDoc)
-        // console.log(RecordingBox.screengrabber.dataDoc.data?.valueOf);
     } else {
-        //when we first press mic
         const screengrabber = Docs.Create.WebCamDocument('', {
             _width: 384,
             _height: 216,
         });
-        // Doc.UserDoc().currentScreenGrab = screengrabber;
-        screengrabber.overlayX = 100; //was -400
-        screengrabber.overlayY = 100; //was 0
+        screengrabber.overlayX = -400;
+        screengrabber.overlayY = 0;
         screengrabber[Doc.LayoutFieldKey(screengrabber) + '_trackScreen'] = true;
-        Doc.AddToMyOverlay(screengrabber);  //just adds doc to overlay
+        Doc.AddToMyOverlay(screengrabber);
         DocumentManager.Instance.AddViewRenderedCb(screengrabber, docView => {
             RecordingBox.screengrabber = docView.ComponentView as RecordingBox;
             RecordingBox.screengrabber.Record?.();
         });
-        // Doc.AddDocToList(Doc.UserDoc(), "workspaceRecordings", screengrabber);
-        Doc.UserDoc().isRecording = true;
-        
     }
 }, 'toggle recording');
-ScriptingGlobals.add(function toggleRecPlayback(value: Doc) {
-    console.log(value)
-    const screenvid = Docs.Create.VideoDocument('', {_width: 384, _height: 216});
-    
-    let ffView = Array.from(DocumentManager.Instance.DocumentViews).find(view => view.ComponentView instanceof CollectionFreeFormView);
-    (ffView?.ComponentView as CollectionFreeFormView).props.addDocument?.(value); 
-
-});
-
-ScriptingGlobals.add(function getCurrRecording() {
-    console.log(RecordingBox.screengrabber);
-});
-ScriptingGlobals.add(function getWorkspaceRecordings() {
-    return Doc.UserDoc().workspaceRecordings
-});
-ScriptingGlobals.add(function getIsRecording() {
-    return Doc.UserDoc().isRecording;
-})
-
-
-
diff --git a/src/client/views/nodes/RecordingBox/RecordingView.tsx b/src/client/views/nodes/RecordingBox/RecordingView.tsx
index 8c0f5efef..0e386b093 100644
--- a/src/client/views/nodes/RecordingBox/RecordingView.tsx
+++ b/src/client/views/nodes/RecordingBox/RecordingView.tsx
@@ -163,9 +163,8 @@ export function RecordingView(props: IRecordingViewProps) {
     // if this is called, then we're done recording all the segments
     const finish = () => {
         // call stop on the video recorder if active
-        console.log(videoRecorder.current?.state);
         videoRecorder.current?.state !== 'inactive' && videoRecorder.current?.stop();
-        console.log("this it")
+
         // end the streams (audio/video) to remove recording icon
         const stream = videoElementRef.current!.srcObject;
         stream instanceof MediaStream && stream.getTracks().forEach(track => track.stop());
diff --git a/src/client/views/nodes/trails/PresElementBox.tsx b/src/client/views/nodes/trails/PresElementBox.tsx
index 5de51dbe9..aa514be3b 100644
--- a/src/client/views/nodes/trails/PresElementBox.tsx
+++ b/src/client/views/nodes/trails/PresElementBox.tsx
@@ -365,7 +365,7 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() {
 
     @undoBatch
     @action
-    startRecording =    (e: React.MouseEvent, activeItem: Doc) => {
+    startRecording = (e: React.MouseEvent, activeItem: Doc) => {
         e.stopPropagation();
         if (PresElementBox.videoIsRecorded(activeItem)) {
             // if we already have an existing recording
-- 
cgit v1.2.3-70-g09d2


From 5e8cc0a6a7f8dfc0c33fbdfa8879de88f057233e Mon Sep 17 00:00:00 2001
From: monoguitari <113245090+monoguitari@users.noreply.github.com>
Date: Sat, 19 Aug 2023 08:39:45 -0400
Subject: Revert "Revert "Toggling icon for mic and added webcapturedoc to
 dropdown""

This reverts commit 2466587655888d5894159b942f09661ab73ebe66.
---
 src/client/util/CurrentUserUtils.ts                |  8 +++-
 src/client/views/UndoStack.tsx                     |  4 +-
 src/client/views/nodes/FontIconBox/FontIconBox.tsx |  4 +-
 .../views/nodes/RecordingBox/RecordingBox.tsx      | 47 ++++++++++++++++++++--
 .../views/nodes/RecordingBox/RecordingView.tsx     |  3 +-
 src/client/views/nodes/trails/PresElementBox.tsx   |  2 +-
 6 files changed, 56 insertions(+), 12 deletions(-)

(limited to 'src/client/views/nodes/FontIconBox/FontIconBox.tsx')

diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 25c8f511b..54828867e 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -714,7 +714,9 @@ export class CurrentUserUtils {
             { title: "View",    icon: "View",          toolTip: "View tools",           subMenu: CurrentUserUtils.viewTools(),   expertMode: false, toolType:CollectionViewType.Freeform, funcs: {hidden: `!SelectionManager_selectedDocType(self.toolType, self.expertMode)`, linearView_IsOpen: `SelectionManager_selectedDocType(self.toolType, self.expertMode)`} }, // Always available
             { title: "Web",     icon: "Web",           toolTip: "Web functions",        subMenu: CurrentUserUtils.webTools(),    expertMode: false, toolType:DocumentType.WEB,            funcs: {hidden: `!SelectionManager_selectedDocType(self.toolType, self.expertMode)`, linearView_IsOpen: `SelectionManager_selectedDocType(self.toolType, self.expertMode)`} }, // Only when Web is selected
             { title: "Schema",  icon: "Schema",linearBtnWidth:58,toolTip: "Schema functions",subMenu: CurrentUserUtils.schemaTools(), expertMode: false, toolType:CollectionViewType.Schema,   funcs: {hidden: `!SelectionManager_selectedDocType(self.toolType, self.expertMode)`, linearView_IsOpen: `SelectionManager_selectedDocType(self.toolType, self.expertMode)`} }, // Only when Schema is selected
-            { title: "Audio",   icon: "microphone",    toolTip: "Dictate",              btnType: ButtonType.ToggleButton,        expertMode: false,                                                                                                          ignoreClick: true,             scripts: { onClick:  'return toggleRecording(_readOnly_)'}, funcs: { }}
+            { title: "Audio",   icon: 'microphone',    toolTip: "Dictate",              btnType: ButtonType.ToggleButton,        expertMode: false,                                       funcs: {hidden: `getIsRecording()`},                                                                  ignoreClick: true,             scripts: { onClick:  'return toggleRecording(_readOnly_)'},},
+            { title: "StopRec", icon: "stop",          toolTip: "Stop",                 btnType: ButtonType.ToggleButton,        expertMode: false,                                       funcs: {hidden: `!getIsRecording()`},                                                                  ignoreClick: true,             scripts: { onClick: `return toggleRecording(_readOnly_)`}},
+            { title: "Dropdown",                       toolTip: "Workspace Recordings", btnType: ButtonType.DropdownList,        expertMode: false,                                       funcs: {btnList: `getWorkspaceRecordings()`},                                                         ignoreClick: true,             scripts: { script: `toggleRecPlayback(value)`}, },
         ];
     }
 
@@ -737,6 +739,8 @@ export class CurrentUserUtils {
     static setupContextMenuBtn(params:Button, menuDoc:Doc):Doc {
         const menuBtnDoc = DocListCast(menuDoc?.data).find(doc => doc.title === params.title);
         const subMenu = params.subMenu;
+        Doc.UserDoc().workspaceRecordings = new List<Doc>;
+        Doc.UserDoc().isRecording = false;
         if (!subMenu) { // button does not have a sub menu
             return this.setupContextMenuButton(params, menuBtnDoc);
         }  
@@ -999,4 +1003,4 @@ ScriptingGlobals.add(function createNewPresentation() { return MainView.Instance
 ScriptingGlobals.add(function openPresentation(pres:Doc) { return MainView.Instance.openPresentation(pres); }, "creates a new presentation when called");
 ScriptingGlobals.add(function createNewFolder() { return MainView.Instance.createNewFolder(); }, "creates a new folder in myFiles when called");
 ScriptingGlobals.add(function importDocument() { return CurrentUserUtils.importDocument(); }, "imports files from device directly into the import sidebar");
-ScriptingGlobals.add(function setInkToolDefaults() { Doc.ActiveTool = InkTool.None; });
\ No newline at end of file
+ScriptingGlobals.add(function setInkToolDefaults() { Doc.ActiveTool = InkTool.None; });
diff --git a/src/client/views/UndoStack.tsx b/src/client/views/UndoStack.tsx
index a551e5332..813cdd050 100644
--- a/src/client/views/UndoStack.tsx
+++ b/src/client/views/UndoStack.tsx
@@ -37,7 +37,7 @@ export class UndoStack extends React.Component<UndoStackProps> {
                             }}>
                             {UndoManager.undoStackNames.map((name, i) => (
                                 <div className="undoStack-resultContainer" key={i}>
-                                    <div className="undoStack-commandString">{name.replace(/[^\.]*\./, '')}</div>
+                                    <div className="undoStack-commandString">{StrCast(name).replace(/[^\.]*\./, '')}</div>
                                 </div>
                             ))}
                             {Array.from(UndoManager.redoStackNames)
@@ -45,7 +45,7 @@ export class UndoStack extends React.Component<UndoStackProps> {
                                 .map((name, i) => (
                                     <div className="undoStack-resultContainer" key={i}>
                                         <div className="undoStack-commandString" style={{ fontWeight: 'bold', color: 'red' }}>
-                                            {name.replace(/[^\.]*\./, '')}
+                                            {StrCast(name).replace(/[^\.]*\./, '')}
                                         </div>
                                     </div>
                                 ))}
diff --git a/src/client/views/nodes/FontIconBox/FontIconBox.tsx b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
index 5ff5f7bfa..41ad90155 100644
--- a/src/client/views/nodes/FontIconBox/FontIconBox.tsx
+++ b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
@@ -6,7 +6,7 @@ import { observer } from 'mobx-react';
 import * as React from 'react';
 import { Doc, DocListCast, StrListCast } from '../../../../fields/Doc';
 import { ScriptField } from '../../../../fields/ScriptField';
-import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from '../../../../fields/Types';
+import { BoolCast, Cast, DocCast, NumCast, ScriptCast, StrCast } from '../../../../fields/Types';
 import { CollectionViewType, DocumentType } from '../../../documents/DocumentTypes';
 import { SelectionManager } from '../../../util/SelectionManager';
 import { undoable, UndoManager } from '../../../util/UndoManager';
@@ -242,7 +242,7 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
         const list: IListItemProps[] = this.buttonList
             .filter(value => !Doc.noviceMode || !noviceList.length || noviceList.includes(value))
             .map(value => ({
-                text: value.charAt(0).toUpperCase() + value.slice(1),
+                text: value === "string" ? value.charAt(0).toUpperCase() + value.slice(1) : StrCast(DocCast(value)?.title),
                 val: value,
                 style: getStyle(value),
                 onClick: undoable(() => script.script.run({ this: this.layoutDoc, self: this.rootDoc, value }), value),
diff --git a/src/client/views/nodes/RecordingBox/RecordingBox.tsx b/src/client/views/nodes/RecordingBox/RecordingBox.tsx
index 8fa2861b6..3237ce6cd 100644
--- a/src/client/views/nodes/RecordingBox/RecordingBox.tsx
+++ b/src/client/views/nodes/RecordingBox/RecordingBox.tsx
@@ -15,6 +15,8 @@ import { BoolCast, DocCast } from '../../../../fields/Types';
 import { ScriptingGlobals } from '../../../util/ScriptingGlobals';
 import { DocumentManager } from '../../../util/DocumentManager';
 import { Docs } from '../../../documents/Documents';
+import { CollectionFreeFormView } from '../../collections/collectionFreeForm/CollectionFreeFormView';
+import { CurrentUserUtils } from '../../../util/CurrentUserUtils';
 
 @observer
 export class RecordingBox extends ViewBoxBaseComponent<FieldViewProps>() {
@@ -82,27 +84,64 @@ export class RecordingBox extends ViewBoxBaseComponent<FieldViewProps>() {
     static screengrabber: RecordingBox | undefined;
 }
 ScriptingGlobals.add(function toggleRecording(_readOnly_: boolean) {
+    console.log(_readOnly_)
+    console.log(RecordingBox.screengrabber)
     if (_readOnly_) return RecordingBox.screengrabber ? true : false;
     if (RecordingBox.screengrabber) {
+        //if recordingbox is true; when we press the stop button. changed vals temporarily to see if changes happening
+        console.log('grabbing screen!')
         RecordingBox.screengrabber.Pause?.();
         setTimeout(() => {
             RecordingBox.screengrabber?.Finish?.();
-            RecordingBox.screengrabber!.rootDoc.overlayX = 100;
+            RecordingBox.screengrabber!.rootDoc.overlayX = 400; //was 100
             RecordingBox.screengrabber!.rootDoc.overlayY = 100;
+            console.log(RecordingBox.screengrabber?.rootDoc)
             RecordingBox.screengrabber = undefined;
         }, 100);
+        Doc.UserDoc().isRecording = false;
+        // console.log(RecordingBox.screengrabber.dataDoc);
+        // Doc.AddDocToList(Doc.UserDoc(), "workspaceRecordings", RecordingBox.screengrabber.dataDoc);
+        Doc.AddDocToList(Doc.UserDoc(), "workspaceRecordings", RecordingBox.screengrabber.rootDoc);
+        // console.log(RecordingBox.screengrabber.rootDoc)
+        // console.log(RecordingBox.screengrabber.dataDoc.data?.valueOf);
     } else {
+        //when we first press mic
         const screengrabber = Docs.Create.WebCamDocument('', {
             _width: 384,
             _height: 216,
         });
-        screengrabber.overlayX = -400;
-        screengrabber.overlayY = 0;
+        // Doc.UserDoc().currentScreenGrab = screengrabber;
+        screengrabber.overlayX = 100; //was -400
+        screengrabber.overlayY = 100; //was 0
         screengrabber[Doc.LayoutFieldKey(screengrabber) + '_trackScreen'] = true;
-        Doc.AddToMyOverlay(screengrabber);
+        Doc.AddToMyOverlay(screengrabber);  //just adds doc to overlay
         DocumentManager.Instance.AddViewRenderedCb(screengrabber, docView => {
             RecordingBox.screengrabber = docView.ComponentView as RecordingBox;
             RecordingBox.screengrabber.Record?.();
         });
+        // Doc.AddDocToList(Doc.UserDoc(), "workspaceRecordings", screengrabber);
+        Doc.UserDoc().isRecording = true;
+        
     }
 }, 'toggle recording');
+ScriptingGlobals.add(function toggleRecPlayback(value: Doc) {
+    console.log(value)
+    const screenvid = Docs.Create.VideoDocument('', {_width: 384, _height: 216});
+    
+    let ffView = Array.from(DocumentManager.Instance.DocumentViews).find(view => view.ComponentView instanceof CollectionFreeFormView);
+    (ffView?.ComponentView as CollectionFreeFormView).props.addDocument?.(value); 
+
+});
+
+ScriptingGlobals.add(function getCurrRecording() {
+    console.log(RecordingBox.screengrabber);
+});
+ScriptingGlobals.add(function getWorkspaceRecordings() {
+    return Doc.UserDoc().workspaceRecordings
+});
+ScriptingGlobals.add(function getIsRecording() {
+    return Doc.UserDoc().isRecording;
+})
+
+
+
diff --git a/src/client/views/nodes/RecordingBox/RecordingView.tsx b/src/client/views/nodes/RecordingBox/RecordingView.tsx
index 0e386b093..8c0f5efef 100644
--- a/src/client/views/nodes/RecordingBox/RecordingView.tsx
+++ b/src/client/views/nodes/RecordingBox/RecordingView.tsx
@@ -163,8 +163,9 @@ export function RecordingView(props: IRecordingViewProps) {
     // if this is called, then we're done recording all the segments
     const finish = () => {
         // call stop on the video recorder if active
+        console.log(videoRecorder.current?.state);
         videoRecorder.current?.state !== 'inactive' && videoRecorder.current?.stop();
-
+        console.log("this it")
         // end the streams (audio/video) to remove recording icon
         const stream = videoElementRef.current!.srcObject;
         stream instanceof MediaStream && stream.getTracks().forEach(track => track.stop());
diff --git a/src/client/views/nodes/trails/PresElementBox.tsx b/src/client/views/nodes/trails/PresElementBox.tsx
index aa514be3b..5de51dbe9 100644
--- a/src/client/views/nodes/trails/PresElementBox.tsx
+++ b/src/client/views/nodes/trails/PresElementBox.tsx
@@ -365,7 +365,7 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() {
 
     @undoBatch
     @action
-    startRecording = (e: React.MouseEvent, activeItem: Doc) => {
+    startRecording =    (e: React.MouseEvent, activeItem: Doc) => {
         e.stopPropagation();
         if (PresElementBox.videoIsRecorded(activeItem)) {
             // if we already have an existing recording
-- 
cgit v1.2.3-70-g09d2


From 40a39db25646b513c25554a2abdf35ef977500a8 Mon Sep 17 00:00:00 2001
From: monoguitari <113245090+monoguitari@users.noreply.github.com>
Date: Sat, 19 Aug 2023 08:52:33 -0400
Subject: Revert "Revert "Revert "Toggling icon for mic and added webcapturedoc
 to dropdown"""

This reverts commit 5e8cc0a6a7f8dfc0c33fbdfa8879de88f057233e.
---
 src/client/util/CurrentUserUtils.ts                |  8 +---
 src/client/views/UndoStack.tsx                     |  4 +-
 src/client/views/nodes/FontIconBox/FontIconBox.tsx |  4 +-
 .../views/nodes/RecordingBox/RecordingBox.tsx      | 47 ++--------------------
 .../views/nodes/RecordingBox/RecordingView.tsx     |  3 +-
 src/client/views/nodes/trails/PresElementBox.tsx   |  2 +-
 6 files changed, 12 insertions(+), 56 deletions(-)

(limited to 'src/client/views/nodes/FontIconBox/FontIconBox.tsx')

diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 54828867e..25c8f511b 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -714,9 +714,7 @@ export class CurrentUserUtils {
             { title: "View",    icon: "View",          toolTip: "View tools",           subMenu: CurrentUserUtils.viewTools(),   expertMode: false, toolType:CollectionViewType.Freeform, funcs: {hidden: `!SelectionManager_selectedDocType(self.toolType, self.expertMode)`, linearView_IsOpen: `SelectionManager_selectedDocType(self.toolType, self.expertMode)`} }, // Always available
             { title: "Web",     icon: "Web",           toolTip: "Web functions",        subMenu: CurrentUserUtils.webTools(),    expertMode: false, toolType:DocumentType.WEB,            funcs: {hidden: `!SelectionManager_selectedDocType(self.toolType, self.expertMode)`, linearView_IsOpen: `SelectionManager_selectedDocType(self.toolType, self.expertMode)`} }, // Only when Web is selected
             { title: "Schema",  icon: "Schema",linearBtnWidth:58,toolTip: "Schema functions",subMenu: CurrentUserUtils.schemaTools(), expertMode: false, toolType:CollectionViewType.Schema,   funcs: {hidden: `!SelectionManager_selectedDocType(self.toolType, self.expertMode)`, linearView_IsOpen: `SelectionManager_selectedDocType(self.toolType, self.expertMode)`} }, // Only when Schema is selected
-            { title: "Audio",   icon: 'microphone',    toolTip: "Dictate",              btnType: ButtonType.ToggleButton,        expertMode: false,                                       funcs: {hidden: `getIsRecording()`},                                                                  ignoreClick: true,             scripts: { onClick:  'return toggleRecording(_readOnly_)'},},
-            { title: "StopRec", icon: "stop",          toolTip: "Stop",                 btnType: ButtonType.ToggleButton,        expertMode: false,                                       funcs: {hidden: `!getIsRecording()`},                                                                  ignoreClick: true,             scripts: { onClick: `return toggleRecording(_readOnly_)`}},
-            { title: "Dropdown",                       toolTip: "Workspace Recordings", btnType: ButtonType.DropdownList,        expertMode: false,                                       funcs: {btnList: `getWorkspaceRecordings()`},                                                         ignoreClick: true,             scripts: { script: `toggleRecPlayback(value)`}, },
+            { title: "Audio",   icon: "microphone",    toolTip: "Dictate",              btnType: ButtonType.ToggleButton,        expertMode: false,                                                                                                          ignoreClick: true,             scripts: { onClick:  'return toggleRecording(_readOnly_)'}, funcs: { }}
         ];
     }
 
@@ -739,8 +737,6 @@ export class CurrentUserUtils {
     static setupContextMenuBtn(params:Button, menuDoc:Doc):Doc {
         const menuBtnDoc = DocListCast(menuDoc?.data).find(doc => doc.title === params.title);
         const subMenu = params.subMenu;
-        Doc.UserDoc().workspaceRecordings = new List<Doc>;
-        Doc.UserDoc().isRecording = false;
         if (!subMenu) { // button does not have a sub menu
             return this.setupContextMenuButton(params, menuBtnDoc);
         }  
@@ -1003,4 +999,4 @@ ScriptingGlobals.add(function createNewPresentation() { return MainView.Instance
 ScriptingGlobals.add(function openPresentation(pres:Doc) { return MainView.Instance.openPresentation(pres); }, "creates a new presentation when called");
 ScriptingGlobals.add(function createNewFolder() { return MainView.Instance.createNewFolder(); }, "creates a new folder in myFiles when called");
 ScriptingGlobals.add(function importDocument() { return CurrentUserUtils.importDocument(); }, "imports files from device directly into the import sidebar");
-ScriptingGlobals.add(function setInkToolDefaults() { Doc.ActiveTool = InkTool.None; });
+ScriptingGlobals.add(function setInkToolDefaults() { Doc.ActiveTool = InkTool.None; });
\ No newline at end of file
diff --git a/src/client/views/UndoStack.tsx b/src/client/views/UndoStack.tsx
index 813cdd050..a551e5332 100644
--- a/src/client/views/UndoStack.tsx
+++ b/src/client/views/UndoStack.tsx
@@ -37,7 +37,7 @@ export class UndoStack extends React.Component<UndoStackProps> {
                             }}>
                             {UndoManager.undoStackNames.map((name, i) => (
                                 <div className="undoStack-resultContainer" key={i}>
-                                    <div className="undoStack-commandString">{StrCast(name).replace(/[^\.]*\./, '')}</div>
+                                    <div className="undoStack-commandString">{name.replace(/[^\.]*\./, '')}</div>
                                 </div>
                             ))}
                             {Array.from(UndoManager.redoStackNames)
@@ -45,7 +45,7 @@ export class UndoStack extends React.Component<UndoStackProps> {
                                 .map((name, i) => (
                                     <div className="undoStack-resultContainer" key={i}>
                                         <div className="undoStack-commandString" style={{ fontWeight: 'bold', color: 'red' }}>
-                                            {StrCast(name).replace(/[^\.]*\./, '')}
+                                            {name.replace(/[^\.]*\./, '')}
                                         </div>
                                     </div>
                                 ))}
diff --git a/src/client/views/nodes/FontIconBox/FontIconBox.tsx b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
index 41ad90155..5ff5f7bfa 100644
--- a/src/client/views/nodes/FontIconBox/FontIconBox.tsx
+++ b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
@@ -6,7 +6,7 @@ import { observer } from 'mobx-react';
 import * as React from 'react';
 import { Doc, DocListCast, StrListCast } from '../../../../fields/Doc';
 import { ScriptField } from '../../../../fields/ScriptField';
-import { BoolCast, Cast, DocCast, NumCast, ScriptCast, StrCast } from '../../../../fields/Types';
+import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from '../../../../fields/Types';
 import { CollectionViewType, DocumentType } from '../../../documents/DocumentTypes';
 import { SelectionManager } from '../../../util/SelectionManager';
 import { undoable, UndoManager } from '../../../util/UndoManager';
@@ -242,7 +242,7 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
         const list: IListItemProps[] = this.buttonList
             .filter(value => !Doc.noviceMode || !noviceList.length || noviceList.includes(value))
             .map(value => ({
-                text: value === "string" ? value.charAt(0).toUpperCase() + value.slice(1) : StrCast(DocCast(value)?.title),
+                text: value.charAt(0).toUpperCase() + value.slice(1),
                 val: value,
                 style: getStyle(value),
                 onClick: undoable(() => script.script.run({ this: this.layoutDoc, self: this.rootDoc, value }), value),
diff --git a/src/client/views/nodes/RecordingBox/RecordingBox.tsx b/src/client/views/nodes/RecordingBox/RecordingBox.tsx
index 3237ce6cd..8fa2861b6 100644
--- a/src/client/views/nodes/RecordingBox/RecordingBox.tsx
+++ b/src/client/views/nodes/RecordingBox/RecordingBox.tsx
@@ -15,8 +15,6 @@ import { BoolCast, DocCast } from '../../../../fields/Types';
 import { ScriptingGlobals } from '../../../util/ScriptingGlobals';
 import { DocumentManager } from '../../../util/DocumentManager';
 import { Docs } from '../../../documents/Documents';
-import { CollectionFreeFormView } from '../../collections/collectionFreeForm/CollectionFreeFormView';
-import { CurrentUserUtils } from '../../../util/CurrentUserUtils';
 
 @observer
 export class RecordingBox extends ViewBoxBaseComponent<FieldViewProps>() {
@@ -84,64 +82,27 @@ export class RecordingBox extends ViewBoxBaseComponent<FieldViewProps>() {
     static screengrabber: RecordingBox | undefined;
 }
 ScriptingGlobals.add(function toggleRecording(_readOnly_: boolean) {
-    console.log(_readOnly_)
-    console.log(RecordingBox.screengrabber)
     if (_readOnly_) return RecordingBox.screengrabber ? true : false;
     if (RecordingBox.screengrabber) {
-        //if recordingbox is true; when we press the stop button. changed vals temporarily to see if changes happening
-        console.log('grabbing screen!')
         RecordingBox.screengrabber.Pause?.();
         setTimeout(() => {
             RecordingBox.screengrabber?.Finish?.();
-            RecordingBox.screengrabber!.rootDoc.overlayX = 400; //was 100
+            RecordingBox.screengrabber!.rootDoc.overlayX = 100;
             RecordingBox.screengrabber!.rootDoc.overlayY = 100;
-            console.log(RecordingBox.screengrabber?.rootDoc)
             RecordingBox.screengrabber = undefined;
         }, 100);
-        Doc.UserDoc().isRecording = false;
-        // console.log(RecordingBox.screengrabber.dataDoc);
-        // Doc.AddDocToList(Doc.UserDoc(), "workspaceRecordings", RecordingBox.screengrabber.dataDoc);
-        Doc.AddDocToList(Doc.UserDoc(), "workspaceRecordings", RecordingBox.screengrabber.rootDoc);
-        // console.log(RecordingBox.screengrabber.rootDoc)
-        // console.log(RecordingBox.screengrabber.dataDoc.data?.valueOf);
     } else {
-        //when we first press mic
         const screengrabber = Docs.Create.WebCamDocument('', {
             _width: 384,
             _height: 216,
         });
-        // Doc.UserDoc().currentScreenGrab = screengrabber;
-        screengrabber.overlayX = 100; //was -400
-        screengrabber.overlayY = 100; //was 0
+        screengrabber.overlayX = -400;
+        screengrabber.overlayY = 0;
         screengrabber[Doc.LayoutFieldKey(screengrabber) + '_trackScreen'] = true;
-        Doc.AddToMyOverlay(screengrabber);  //just adds doc to overlay
+        Doc.AddToMyOverlay(screengrabber);
         DocumentManager.Instance.AddViewRenderedCb(screengrabber, docView => {
             RecordingBox.screengrabber = docView.ComponentView as RecordingBox;
             RecordingBox.screengrabber.Record?.();
         });
-        // Doc.AddDocToList(Doc.UserDoc(), "workspaceRecordings", screengrabber);
-        Doc.UserDoc().isRecording = true;
-        
     }
 }, 'toggle recording');
-ScriptingGlobals.add(function toggleRecPlayback(value: Doc) {
-    console.log(value)
-    const screenvid = Docs.Create.VideoDocument('', {_width: 384, _height: 216});
-    
-    let ffView = Array.from(DocumentManager.Instance.DocumentViews).find(view => view.ComponentView instanceof CollectionFreeFormView);
-    (ffView?.ComponentView as CollectionFreeFormView).props.addDocument?.(value); 
-
-});
-
-ScriptingGlobals.add(function getCurrRecording() {
-    console.log(RecordingBox.screengrabber);
-});
-ScriptingGlobals.add(function getWorkspaceRecordings() {
-    return Doc.UserDoc().workspaceRecordings
-});
-ScriptingGlobals.add(function getIsRecording() {
-    return Doc.UserDoc().isRecording;
-})
-
-
-
diff --git a/src/client/views/nodes/RecordingBox/RecordingView.tsx b/src/client/views/nodes/RecordingBox/RecordingView.tsx
index 8c0f5efef..0e386b093 100644
--- a/src/client/views/nodes/RecordingBox/RecordingView.tsx
+++ b/src/client/views/nodes/RecordingBox/RecordingView.tsx
@@ -163,9 +163,8 @@ export function RecordingView(props: IRecordingViewProps) {
     // if this is called, then we're done recording all the segments
     const finish = () => {
         // call stop on the video recorder if active
-        console.log(videoRecorder.current?.state);
         videoRecorder.current?.state !== 'inactive' && videoRecorder.current?.stop();
-        console.log("this it")
+
         // end the streams (audio/video) to remove recording icon
         const stream = videoElementRef.current!.srcObject;
         stream instanceof MediaStream && stream.getTracks().forEach(track => track.stop());
diff --git a/src/client/views/nodes/trails/PresElementBox.tsx b/src/client/views/nodes/trails/PresElementBox.tsx
index 5de51dbe9..aa514be3b 100644
--- a/src/client/views/nodes/trails/PresElementBox.tsx
+++ b/src/client/views/nodes/trails/PresElementBox.tsx
@@ -365,7 +365,7 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() {
 
     @undoBatch
     @action
-    startRecording =    (e: React.MouseEvent, activeItem: Doc) => {
+    startRecording = (e: React.MouseEvent, activeItem: Doc) => {
         e.stopPropagation();
         if (PresElementBox.videoIsRecorded(activeItem)) {
             // if we already have an existing recording
-- 
cgit v1.2.3-70-g09d2


From ec6a5f5d5684ca66cd21bb8fef91c86852dd126f Mon Sep 17 00:00:00 2001
From: monoguitari <113245090+monoguitari@users.noreply.github.com>
Date: Sat, 19 Aug 2023 08:53:11 -0400
Subject: Revert "Revert "Revert "Revert "Toggling icon for mic and added
 webcapturedoc to dropdown""""

This reverts commit 40a39db25646b513c25554a2abdf35ef977500a8.
---
 src/client/util/CurrentUserUtils.ts                |  8 +++-
 src/client/views/UndoStack.tsx                     |  4 +-
 src/client/views/nodes/FontIconBox/FontIconBox.tsx |  4 +-
 .../views/nodes/RecordingBox/RecordingBox.tsx      | 47 ++++++++++++++++++++--
 .../views/nodes/RecordingBox/RecordingView.tsx     |  3 +-
 src/client/views/nodes/trails/PresElementBox.tsx   |  2 +-
 6 files changed, 56 insertions(+), 12 deletions(-)

(limited to 'src/client/views/nodes/FontIconBox/FontIconBox.tsx')

diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 25c8f511b..54828867e 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -714,7 +714,9 @@ export class CurrentUserUtils {
             { title: "View",    icon: "View",          toolTip: "View tools",           subMenu: CurrentUserUtils.viewTools(),   expertMode: false, toolType:CollectionViewType.Freeform, funcs: {hidden: `!SelectionManager_selectedDocType(self.toolType, self.expertMode)`, linearView_IsOpen: `SelectionManager_selectedDocType(self.toolType, self.expertMode)`} }, // Always available
             { title: "Web",     icon: "Web",           toolTip: "Web functions",        subMenu: CurrentUserUtils.webTools(),    expertMode: false, toolType:DocumentType.WEB,            funcs: {hidden: `!SelectionManager_selectedDocType(self.toolType, self.expertMode)`, linearView_IsOpen: `SelectionManager_selectedDocType(self.toolType, self.expertMode)`} }, // Only when Web is selected
             { title: "Schema",  icon: "Schema",linearBtnWidth:58,toolTip: "Schema functions",subMenu: CurrentUserUtils.schemaTools(), expertMode: false, toolType:CollectionViewType.Schema,   funcs: {hidden: `!SelectionManager_selectedDocType(self.toolType, self.expertMode)`, linearView_IsOpen: `SelectionManager_selectedDocType(self.toolType, self.expertMode)`} }, // Only when Schema is selected
-            { title: "Audio",   icon: "microphone",    toolTip: "Dictate",              btnType: ButtonType.ToggleButton,        expertMode: false,                                                                                                          ignoreClick: true,             scripts: { onClick:  'return toggleRecording(_readOnly_)'}, funcs: { }}
+            { title: "Audio",   icon: 'microphone',    toolTip: "Dictate",              btnType: ButtonType.ToggleButton,        expertMode: false,                                       funcs: {hidden: `getIsRecording()`},                                                                  ignoreClick: true,             scripts: { onClick:  'return toggleRecording(_readOnly_)'},},
+            { title: "StopRec", icon: "stop",          toolTip: "Stop",                 btnType: ButtonType.ToggleButton,        expertMode: false,                                       funcs: {hidden: `!getIsRecording()`},                                                                  ignoreClick: true,             scripts: { onClick: `return toggleRecording(_readOnly_)`}},
+            { title: "Dropdown",                       toolTip: "Workspace Recordings", btnType: ButtonType.DropdownList,        expertMode: false,                                       funcs: {btnList: `getWorkspaceRecordings()`},                                                         ignoreClick: true,             scripts: { script: `toggleRecPlayback(value)`}, },
         ];
     }
 
@@ -737,6 +739,8 @@ export class CurrentUserUtils {
     static setupContextMenuBtn(params:Button, menuDoc:Doc):Doc {
         const menuBtnDoc = DocListCast(menuDoc?.data).find(doc => doc.title === params.title);
         const subMenu = params.subMenu;
+        Doc.UserDoc().workspaceRecordings = new List<Doc>;
+        Doc.UserDoc().isRecording = false;
         if (!subMenu) { // button does not have a sub menu
             return this.setupContextMenuButton(params, menuBtnDoc);
         }  
@@ -999,4 +1003,4 @@ ScriptingGlobals.add(function createNewPresentation() { return MainView.Instance
 ScriptingGlobals.add(function openPresentation(pres:Doc) { return MainView.Instance.openPresentation(pres); }, "creates a new presentation when called");
 ScriptingGlobals.add(function createNewFolder() { return MainView.Instance.createNewFolder(); }, "creates a new folder in myFiles when called");
 ScriptingGlobals.add(function importDocument() { return CurrentUserUtils.importDocument(); }, "imports files from device directly into the import sidebar");
-ScriptingGlobals.add(function setInkToolDefaults() { Doc.ActiveTool = InkTool.None; });
\ No newline at end of file
+ScriptingGlobals.add(function setInkToolDefaults() { Doc.ActiveTool = InkTool.None; });
diff --git a/src/client/views/UndoStack.tsx b/src/client/views/UndoStack.tsx
index a551e5332..813cdd050 100644
--- a/src/client/views/UndoStack.tsx
+++ b/src/client/views/UndoStack.tsx
@@ -37,7 +37,7 @@ export class UndoStack extends React.Component<UndoStackProps> {
                             }}>
                             {UndoManager.undoStackNames.map((name, i) => (
                                 <div className="undoStack-resultContainer" key={i}>
-                                    <div className="undoStack-commandString">{name.replace(/[^\.]*\./, '')}</div>
+                                    <div className="undoStack-commandString">{StrCast(name).replace(/[^\.]*\./, '')}</div>
                                 </div>
                             ))}
                             {Array.from(UndoManager.redoStackNames)
@@ -45,7 +45,7 @@ export class UndoStack extends React.Component<UndoStackProps> {
                                 .map((name, i) => (
                                     <div className="undoStack-resultContainer" key={i}>
                                         <div className="undoStack-commandString" style={{ fontWeight: 'bold', color: 'red' }}>
-                                            {name.replace(/[^\.]*\./, '')}
+                                            {StrCast(name).replace(/[^\.]*\./, '')}
                                         </div>
                                     </div>
                                 ))}
diff --git a/src/client/views/nodes/FontIconBox/FontIconBox.tsx b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
index 5ff5f7bfa..41ad90155 100644
--- a/src/client/views/nodes/FontIconBox/FontIconBox.tsx
+++ b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
@@ -6,7 +6,7 @@ import { observer } from 'mobx-react';
 import * as React from 'react';
 import { Doc, DocListCast, StrListCast } from '../../../../fields/Doc';
 import { ScriptField } from '../../../../fields/ScriptField';
-import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from '../../../../fields/Types';
+import { BoolCast, Cast, DocCast, NumCast, ScriptCast, StrCast } from '../../../../fields/Types';
 import { CollectionViewType, DocumentType } from '../../../documents/DocumentTypes';
 import { SelectionManager } from '../../../util/SelectionManager';
 import { undoable, UndoManager } from '../../../util/UndoManager';
@@ -242,7 +242,7 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
         const list: IListItemProps[] = this.buttonList
             .filter(value => !Doc.noviceMode || !noviceList.length || noviceList.includes(value))
             .map(value => ({
-                text: value.charAt(0).toUpperCase() + value.slice(1),
+                text: value === "string" ? value.charAt(0).toUpperCase() + value.slice(1) : StrCast(DocCast(value)?.title),
                 val: value,
                 style: getStyle(value),
                 onClick: undoable(() => script.script.run({ this: this.layoutDoc, self: this.rootDoc, value }), value),
diff --git a/src/client/views/nodes/RecordingBox/RecordingBox.tsx b/src/client/views/nodes/RecordingBox/RecordingBox.tsx
index 8fa2861b6..3237ce6cd 100644
--- a/src/client/views/nodes/RecordingBox/RecordingBox.tsx
+++ b/src/client/views/nodes/RecordingBox/RecordingBox.tsx
@@ -15,6 +15,8 @@ import { BoolCast, DocCast } from '../../../../fields/Types';
 import { ScriptingGlobals } from '../../../util/ScriptingGlobals';
 import { DocumentManager } from '../../../util/DocumentManager';
 import { Docs } from '../../../documents/Documents';
+import { CollectionFreeFormView } from '../../collections/collectionFreeForm/CollectionFreeFormView';
+import { CurrentUserUtils } from '../../../util/CurrentUserUtils';
 
 @observer
 export class RecordingBox extends ViewBoxBaseComponent<FieldViewProps>() {
@@ -82,27 +84,64 @@ export class RecordingBox extends ViewBoxBaseComponent<FieldViewProps>() {
     static screengrabber: RecordingBox | undefined;
 }
 ScriptingGlobals.add(function toggleRecording(_readOnly_: boolean) {
+    console.log(_readOnly_)
+    console.log(RecordingBox.screengrabber)
     if (_readOnly_) return RecordingBox.screengrabber ? true : false;
     if (RecordingBox.screengrabber) {
+        //if recordingbox is true; when we press the stop button. changed vals temporarily to see if changes happening
+        console.log('grabbing screen!')
         RecordingBox.screengrabber.Pause?.();
         setTimeout(() => {
             RecordingBox.screengrabber?.Finish?.();
-            RecordingBox.screengrabber!.rootDoc.overlayX = 100;
+            RecordingBox.screengrabber!.rootDoc.overlayX = 400; //was 100
             RecordingBox.screengrabber!.rootDoc.overlayY = 100;
+            console.log(RecordingBox.screengrabber?.rootDoc)
             RecordingBox.screengrabber = undefined;
         }, 100);
+        Doc.UserDoc().isRecording = false;
+        // console.log(RecordingBox.screengrabber.dataDoc);
+        // Doc.AddDocToList(Doc.UserDoc(), "workspaceRecordings", RecordingBox.screengrabber.dataDoc);
+        Doc.AddDocToList(Doc.UserDoc(), "workspaceRecordings", RecordingBox.screengrabber.rootDoc);
+        // console.log(RecordingBox.screengrabber.rootDoc)
+        // console.log(RecordingBox.screengrabber.dataDoc.data?.valueOf);
     } else {
+        //when we first press mic
         const screengrabber = Docs.Create.WebCamDocument('', {
             _width: 384,
             _height: 216,
         });
-        screengrabber.overlayX = -400;
-        screengrabber.overlayY = 0;
+        // Doc.UserDoc().currentScreenGrab = screengrabber;
+        screengrabber.overlayX = 100; //was -400
+        screengrabber.overlayY = 100; //was 0
         screengrabber[Doc.LayoutFieldKey(screengrabber) + '_trackScreen'] = true;
-        Doc.AddToMyOverlay(screengrabber);
+        Doc.AddToMyOverlay(screengrabber);  //just adds doc to overlay
         DocumentManager.Instance.AddViewRenderedCb(screengrabber, docView => {
             RecordingBox.screengrabber = docView.ComponentView as RecordingBox;
             RecordingBox.screengrabber.Record?.();
         });
+        // Doc.AddDocToList(Doc.UserDoc(), "workspaceRecordings", screengrabber);
+        Doc.UserDoc().isRecording = true;
+        
     }
 }, 'toggle recording');
+ScriptingGlobals.add(function toggleRecPlayback(value: Doc) {
+    console.log(value)
+    const screenvid = Docs.Create.VideoDocument('', {_width: 384, _height: 216});
+    
+    let ffView = Array.from(DocumentManager.Instance.DocumentViews).find(view => view.ComponentView instanceof CollectionFreeFormView);
+    (ffView?.ComponentView as CollectionFreeFormView).props.addDocument?.(value); 
+
+});
+
+ScriptingGlobals.add(function getCurrRecording() {
+    console.log(RecordingBox.screengrabber);
+});
+ScriptingGlobals.add(function getWorkspaceRecordings() {
+    return Doc.UserDoc().workspaceRecordings
+});
+ScriptingGlobals.add(function getIsRecording() {
+    return Doc.UserDoc().isRecording;
+})
+
+
+
diff --git a/src/client/views/nodes/RecordingBox/RecordingView.tsx b/src/client/views/nodes/RecordingBox/RecordingView.tsx
index 0e386b093..8c0f5efef 100644
--- a/src/client/views/nodes/RecordingBox/RecordingView.tsx
+++ b/src/client/views/nodes/RecordingBox/RecordingView.tsx
@@ -163,8 +163,9 @@ export function RecordingView(props: IRecordingViewProps) {
     // if this is called, then we're done recording all the segments
     const finish = () => {
         // call stop on the video recorder if active
+        console.log(videoRecorder.current?.state);
         videoRecorder.current?.state !== 'inactive' && videoRecorder.current?.stop();
-
+        console.log("this it")
         // end the streams (audio/video) to remove recording icon
         const stream = videoElementRef.current!.srcObject;
         stream instanceof MediaStream && stream.getTracks().forEach(track => track.stop());
diff --git a/src/client/views/nodes/trails/PresElementBox.tsx b/src/client/views/nodes/trails/PresElementBox.tsx
index aa514be3b..5de51dbe9 100644
--- a/src/client/views/nodes/trails/PresElementBox.tsx
+++ b/src/client/views/nodes/trails/PresElementBox.tsx
@@ -365,7 +365,7 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() {
 
     @undoBatch
     @action
-    startRecording = (e: React.MouseEvent, activeItem: Doc) => {
+    startRecording =    (e: React.MouseEvent, activeItem: Doc) => {
         e.stopPropagation();
         if (PresElementBox.videoIsRecorded(activeItem)) {
             // if we already have an existing recording
-- 
cgit v1.2.3-70-g09d2


From 63c2c903d4d92aaeb0d024f02d8142d7c8ad7a5f Mon Sep 17 00:00:00 2001
From: geireann <geireann.lindfield@gmail.com>
Date: Tue, 22 Aug 2023 15:32:06 -0400
Subject: tweaks

---
 .../views/collections/collectionFreeForm/CollectionFreeFormView.tsx     | 2 +-
 src/client/views/nodes/FontIconBox/FontIconBox.tsx                      | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

(limited to 'src/client/views/nodes/FontIconBox/FontIconBox.tsx')

diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 91a78c2af..f5cc1eb53 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -1600,7 +1600,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
                     () => this.rootDoc.fitContentOnce,
                     fitContentOnce => {
                         if (fitContentOnce) this.fitContentOnce();
-                        this.rootDoc.fitContentOnce = false;
+                        this.rootDoc.fitContentOnce = undefined;
                     },
                     { fireImmediately: true, name: 'fitContent' }
                 );
diff --git a/src/client/views/nodes/FontIconBox/FontIconBox.tsx b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
index 0e230e19b..a2cf3bc25 100644
--- a/src/client/views/nodes/FontIconBox/FontIconBox.tsx
+++ b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
@@ -426,7 +426,7 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
             case ButtonType.DropdownButton:     return this.dropdownButton;
             case ButtonType.MultiToggleButton:  return this.multiToggleButton;
             case ButtonType.ToggleButton:       return this.toggleButton;
-            case ButtonType.IconClickButton: return this.iconClickButton;
+            case ButtonType.IconClickButton:    return this.iconClickButton;
             case ButtonType.ClickButton:
             case ButtonType.ToolButton: return <IconButton {...btnProps} size={Size.LARGE} color={color} />;
             case ButtonType.TextButton: return <Button     {...btnProps} text={StrCast(this.rootDoc.buttonText)}/>;
-- 
cgit v1.2.3-70-g09d2


From 9a9ee6058941dc89eb5719ef4fdd66a4743698fd Mon Sep 17 00:00:00 2001
From: geireann <geireann.lindfield@gmail.com>
Date: Thu, 24 Aug 2023 10:37:07 -0400
Subject: removed iconClickButton and reverted fit All menu item

---
 src/client/util/CurrentUserUtils.ts                | 14 ++++----
 src/client/views/nodes/FontIconBox/FontIconBox.tsx | 37 +++-------------------
 2 files changed, 11 insertions(+), 40 deletions(-)

(limited to 'src/client/views/nodes/FontIconBox/FontIconBox.tsx')

diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 9322cda4b..62b99d752 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -629,14 +629,14 @@ export class CurrentUserUtils {
     }
     static viewTools(): Button[] {
         return [
-            { title: "Snap", icon: "th",                    toolTip: "Show Snap Lines",     btnType: ButtonType.ToggleButton, ignoreClick: true, expertMode: false, toolType:"snaplines",  funcs: {}, scripts: { onClick: '{ return showFreeform(self.toolType, _readOnly_);}'}}, // Only when floating document is selected in freeform
-            { title: "Grid",          icon: "border-all",   toolTip: "Show Grid",           btnType: ButtonType.ToggleButton, ignoreClick: true, expertMode: false, toolType:"grid",       funcs: {}, scripts: { onClick: '{ return showFreeform(self.toolType, _readOnly_);}'}}, // Only when floating document is selected in freeform
-            { title: "View All",   icon: "object-group", toolTip: "Fit all Docs to View",   btnType: ButtonType.ToggleButton, ignoreClick: true, expertMode: false, toolType:"viewAll",    funcs: {}, scripts: { onClick: '{ return showFreeform(self.toolType, _readOnly_);}'}}, // Only when floating document is selected in freeform
+            { title: "Snap",      icon: "th",                  toolTip: "Show Snap Lines",     btnType: ButtonType.ToggleButton, ignoreClick: true, expertMode: false, toolType:"snaplines",  funcs: {}, scripts: { onClick: '{ return showFreeform(self.toolType, _readOnly_);}'}}, // Only when floating document is selected in freeform
+            { title: "Grid",      icon: "border-all",          toolTip: "Show Grid",           btnType: ButtonType.ToggleButton, ignoreClick: true, expertMode: false, toolType:"grid",       funcs: {}, scripts: { onClick: '{ return showFreeform(self.toolType, _readOnly_);}'}}, // Only when floating document is selected in freeform
+            { title: "View All",  icon: "object-group",        toolTip: "Fit all Docs to View",btnType: ButtonType.ToggleButton, ignoreClick: true, expertMode: false, toolType:"viewAll",    funcs: {}, scripts: { onClick: '{ return showFreeform(self.toolType, _readOnly_);}'}}, // Only when floating document is selected in freeform
             // want the same style as toggle button, but don't want it to act as an actual toggle, so set disableToggle to true,
-            { title: "Fit All",   icon: "arrows-left-right", toolTip: "Fit all Docs to View (persistent)", btnType: ButtonType.IconClickButton, ignoreClick: false, expertMode: false, toolType:"viewAllPersist",    funcs: {}, scripts: { onClick: '{ return showFreeform(self.toolType, _readOnly_);}'}}, // Only when floating document is selected in freeform
-            { title: "Clusters",      icon: "braille",      toolTip: "Show Doc Clusters",   btnType: ButtonType.ToggleButton, ignoreClick: true, expertMode: false, toolType:"clusters",   funcs: {}, scripts: { onClick: '{ return showFreeform(self.toolType, _readOnly_);}'}}, // Only when floating document is selected in freeform
-            { title: "Cards",         icon: "brain",        toolTip: "Flashcards",          btnType: ButtonType.ToggleButton, ignoreClick: true, expertMode: false, toolType:"flashcards", funcs: {}, scripts: { onClick: '{ return showFreeform(self.toolType, _readOnly_);}'}}, // Only when floating document is selected in freeform
-            { title: "Arrange",icon:"arrow-down-short-wide",toolTip:"Toggle Auto Arrange",  btnType: ButtonType.ToggleButton, ignoreClick: true, expertMode: false, toolType:"arrange",    funcs: {hidden: 'IsNoviceMode()'}, scripts: { onClick: '{ return showFreeform(self.toolType, _readOnly_);}'}}, // Only when floating document is selected in freeform
+            { title: "Fit All",   icon: "arrows-left-right",   toolTip: "Fit all Docs to View (persistent)", btnType: ButtonType.ClickButton, ignoreClick: false, expertMode: false, toolType:"viewAllPersist",    funcs: {}, scripts: { onClick: '{ return showFreeform(self.toolType, _readOnly_);}'}}, // Only when floating document is selected in freeform
+            { title: "Clusters",  icon: "braille",             toolTip: "Show Doc Clusters",   btnType: ButtonType.ToggleButton, ignoreClick: true, expertMode: false, toolType:"clusters",   funcs: {}, scripts: { onClick: '{ return showFreeform(self.toolType, _readOnly_);}'}}, // Only when floating document is selected in freeform
+            { title: "Cards",     icon: "brain",               toolTip: "Flashcards",          btnType: ButtonType.ToggleButton, ignoreClick: true, expertMode: false, toolType:"flashcards", funcs: {}, scripts: { onClick: '{ return showFreeform(self.toolType, _readOnly_);}'}}, // Only when floating document is selected in freeform
+            { title: "Arrange",   icon:"arrow-down-short-wide",toolTip:"Toggle Auto Arrange",  btnType: ButtonType.ToggleButton, ignoreClick: true, expertMode: false, toolType:"arrange",    funcs: {hidden: 'IsNoviceMode()'}, scripts: { onClick: '{ return showFreeform(self.toolType, _readOnly_);}'}}, // Only when floating document is selected in freeform
         ]
     }
     static textTools():Button[] {
diff --git a/src/client/views/nodes/FontIconBox/FontIconBox.tsx b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
index a2cf3bc25..47dac651d 100644
--- a/src/client/views/nodes/FontIconBox/FontIconBox.tsx
+++ b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
@@ -1,12 +1,13 @@
 import { IconProp } from '@fortawesome/fontawesome-svg-core';
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { Button, MultiToggle, ColorPicker, Dropdown, DropdownType, EditableText, IconButton, IListItemProps, NumberDropdown, NumberDropdownType, Popup, Size, Toggle, ToggleType, Type } from 'browndash-components';
+import { Button, ColorPicker, Dropdown, DropdownType, EditableText, IconButton, IListItemProps, MultiToggle, NumberDropdown, NumberDropdownType, Popup, Size, Toggle, ToggleType, Type } from 'browndash-components';
 import { action, computed, observable } from 'mobx';
 import { observer } from 'mobx-react';
 import * as React from 'react';
 import { Doc, DocListCast, StrListCast } from '../../../../fields/Doc';
 import { ScriptField } from '../../../../fields/ScriptField';
 import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from '../../../../fields/Types';
+import { Utils } from '../../../../Utils';
 import { CollectionViewType, DocumentType } from '../../../documents/DocumentTypes';
 import { SelectionManager } from '../../../util/SelectionManager';
 import { undoable, UndoManager } from '../../../util/UndoManager';
@@ -14,14 +15,12 @@ import { ContextMenu } from '../../ContextMenu';
 import { DocComponent } from '../../DocComponent';
 import { EditableView } from '../../EditableView';
 import { Colors } from '../../global/globalEnums';
+import { SelectedDocView } from '../../selectedDoc';
 import { StyleProp } from '../../StyleProvider';
-import { FieldView, FieldViewProps } from '../FieldView';
 import { OpenWhere } from '../DocumentView';
+import { FieldView, FieldViewProps } from '../FieldView';
 import { RichTextMenu } from '../formattedText/RichTextMenu';
 import './FontIconBox.scss';
-import { SelectedDocView } from '../../selectedDoc';
-import { Utils } from '../../../../Utils';
-import { FaAlignCenter, FaAlignJustify, FaAlignLeft, FaAlignRight } from 'react-icons/fa';
 
 export enum ButtonType {
     TextButton = 'textBtn',
@@ -29,7 +28,6 @@ export enum ButtonType {
     DropdownList = 'dropdownList',
     DropdownButton = 'dropdownBtn',
     ClickButton = 'clickBtn',
-    IconClickButton = 'iconClickBtn',
     ToggleButton = 'toggleBtn',
     ColorButton = 'colorBtn',
     ToolButton = 'toolBtn',
@@ -353,32 +351,6 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
         );
     }
 
-    @computed get iconClickButton() {
-        // Determine the type of toggle button
-        const buttonText: string = StrCast(this.rootDoc.buttonText);
-        const tooltip: string = StrCast(this.rootDoc.toolTip);
-
-        const script = ScriptCast(this.rootDoc.onClick);
-        const toggleStatus = script ? script.script.run({ this: this.layoutDoc, self: this.rootDoc, value: undefined, _readOnly_: true }).result : false;
-        // Colors
-        const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color);
-        const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor);
-
-        return (
-            <Toggle
-                tooltip={`${tooltip}`}
-                toggleType={ToggleType.BUTTON}
-                type={Type.PRIM}
-                toggleStatus={toggleStatus}
-                text={buttonText}
-                color={color}
-                icon={this.Icon(color)!}
-                label={this.label}
-                onPointerDown={() => script.script.run({ this: this.layoutDoc, self: this.rootDoc, value: !toggleStatus, _readOnly_: false })}
-            />
-        );
-    }
-
     /**
      * Default
      */
@@ -426,7 +398,6 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
             case ButtonType.DropdownButton:     return this.dropdownButton;
             case ButtonType.MultiToggleButton:  return this.multiToggleButton;
             case ButtonType.ToggleButton:       return this.toggleButton;
-            case ButtonType.IconClickButton:    return this.iconClickButton;
             case ButtonType.ClickButton:
             case ButtonType.ToolButton: return <IconButton {...btnProps} size={Size.LARGE} color={color} />;
             case ButtonType.TextButton: return <Button     {...btnProps} text={StrCast(this.rootDoc.buttonText)}/>;
-- 
cgit v1.2.3-70-g09d2


From c1fb1fd8d347604882a80ec006d04b8bfed495bd Mon Sep 17 00:00:00 2001
From: Sophie Zhang <sophie_zhang@brown.edu>
Date: Fri, 25 Aug 2023 14:25:55 -0400
Subject: changed pres icon to svg

---
 deploy/assets/presTrailsSvg.svg                    | 58 +++++++++++++++
 src/client/views/nodes/FontIconBox/FontIconBox.tsx |  4 +-
 src/client/views/nodes/FontIconBox/TrailsIcon.tsx  | 83 ++++++++++++++++++++++
 3 files changed, 143 insertions(+), 2 deletions(-)
 create mode 100644 deploy/assets/presTrailsSvg.svg
 create mode 100644 src/client/views/nodes/FontIconBox/TrailsIcon.tsx

(limited to 'src/client/views/nodes/FontIconBox/FontIconBox.tsx')

diff --git a/deploy/assets/presTrailsSvg.svg b/deploy/assets/presTrailsSvg.svg
new file mode 100644
index 000000000..238e9979f
--- /dev/null
+++ b/deploy/assets/presTrailsSvg.svg
@@ -0,0 +1,58 @@
+<?xml version="1.0" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+ "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
+ width="1080.000000pt" height="1080.000000pt" viewBox="0 0 1080.000000 1080.000000"
+ preserveAspectRatio="xMidYMid meet">
+
+<g transform="translate(0.000000,1080.000000) scale(0.100000,-0.100000)"
+fill="#000000" stroke="none">
+<path d="M665 9253 c-74 -10 -157 -38 -240 -81 -74 -37 -107 -63 -186 -141
+-104 -104 -156 -191 -201 -334 l-23 -72 0 -3215 c0 -3072 1 -3218 18 -3280 10
+-36 39 -108 64 -160 40 -82 59 -107 142 -190 81 -81 111 -103 191 -143 52 -26
+122 -55 155 -65 57 -16 322 -17 4775 -20 3250 -2 4736 1 4784 8 256 39 486
+220 588 462 63 148 59 -96 56 3413 -3 3049 -4 3203 -21 3260 -78 260 -285 467
+-542 542 -57 17 -308 18 -4795 19 -2604 1 -4748 -1 -4765 -3z m9187 -787 c65
+-19 114 -60 143 -120 l25 -51 0 -2898 c0 -2582 -2 -2901 -15 -2934 -24 -57
+-62 -101 -108 -126 l-42 -22 -4435 -3 c-3954 -2 -4440 0 -4481 13 -26 9 -63
+33 -87 56 -79 79 -72 -205 -72 3012 0 2156 3 2889 12 2918 20 70 91 136 168
+160 14 4 2010 8 4436 8 3710 1 4418 -1 4456 -13z"/>
+<path d="M7692 7839 c-46 -14 -109 -80 -122 -128 -7 -27 -9 -472 -8 -1443 l3
+-1403 24 -38 c13 -21 42 -50 64 -65 l41 -27 816 0 816 0 41 27 c22 15 51 44
+64 65 l24 38 0 1425 0 1425 -24 38 c-13 21 -42 50 -64 65 l-41 27 -800 2
+c-488 1 -814 -2 -834 -8z"/>
+<path d="M1982 7699 c-46 -14 -109 -80 -122 -128 -7 -27 -10 -308 -8 -893 l3
+-853 24 -38 c13 -21 42 -50 64 -65 l41 -27 1386 0 1386 0 41 27 c22 15 51 44
+64 65 l24 38 0 876 0 875 -27 41 c-15 22 -44 51 -65 64 l-38 24 -1370 2 c-847
+1 -1383 -2 -1403 -8z"/>
+<path d="M6413 7093 c-13 -2 -23 -9 -23 -15 0 -24 21 -307 26 -343 l5 -40 182
+-1 c200 -1 307 -15 484 -65 57 -16 107 -29 112 -29 5 0 36 75 69 168 33 92 63
+175 67 184 6 14 -10 22 -92 48 -126 39 -308 76 -447 89 -106 11 -337 13 -383
+4z"/>
+<path d="M5840 7033 c-63 -8 -238 -29 -388 -47 -150 -18 -274 -35 -276 -37 -2
+-2 8 -89 23 -194 22 -163 29 -190 44 -193 10 -2 91 6 180 17 89 12 258 32 376
+46 118 14 216 27 218 28 7 8 -43 391 -52 392 -5 1 -62 -4 -125 -12z"/>
+<path d="M4762 4789 c-46 -14 -109 -80 -122 -128 -7 -27 -10 -323 -8 -943 l3
+-903 24 -38 c13 -21 42 -50 64 -65 l41 -27 926 0 926 0 41 27 c22 15 51 44 64
+65 l24 38 0 926 0 925 -27 41 c-15 22 -44 51 -65 64 l-38 24 -910 2 c-557 1
+-923 -2 -943 -8z"/>
+<path d="M8487 4297 c-26 -215 -161 -474 -307 -585 -27 -20 -49 -40 -49 -44
+-1 -3 49 -79 110 -167 l110 -161 44 31 c176 126 333 350 418 594 30 86 77 282
+77 320 0 8 -57 19 -167 34 -93 13 -182 25 -199 28 -31 5 -31 5 -37 -50z"/>
+<path d="M3965 4233 c-106 -9 -348 -36 -415 -47 -55 -8 -75 -15 -74 -26 1 -20
+56 -374 59 -377 1 -2 46 4 101 12 159 24 409 45 526 45 l108 0 0 200 0 200
+-132 -2 c-73 -1 -151 -3 -173 -5z"/>
+<path d="M3020 4079 c-85 -23 -292 -94 -368 -125 -97 -40 -298 -140 -305 -151
+-5 -7 172 -315 192 -336 4 -4 41 10 82 32 103 55 272 123 414 165 66 20 125
+38 132 41 11 4 -4 70 -78 348 -10 39 -14 41 -69 26z"/>
+<path d="M6955 3538 c-21 -91 -74 -362 -72 -364 7 -7 260 -44 367 -54 146 -13
+359 -13 475 0 49 6 90 12 91 13 2 1 -12 90 -29 197 -26 155 -36 194 -47 192
+-8 -2 -85 -6 -170 -9 -160 -6 -357 7 -505 33 -103 18 -104 18 -110 -8z"/>
+<path d="M1993 3513 c-52 -67 -71 -106 -98 -198 -35 -122 -44 -284 -21 -415 9
+-51 18 -96 21 -98 4 -5 360 79 375 88 7 4 7 24 0 60 -21 109 -7 244 31 307
+l20 31 -146 131 c-80 72 -147 131 -149 131 -2 0 -17 -17 -33 -37z"/>
+<path d="M2210 2519 c-91 -50 -166 -92 -168 -94 -2 -1 11 -26 28 -54 l32 -51
+244 0 c134 0 244 2 244 5 0 3 -23 33 -51 67 -28 35 -72 98 -97 140 -26 43 -51
+77 -57 77 -5 0 -84 -41 -175 -90z"/>
+</g>
+</svg>
diff --git a/src/client/views/nodes/FontIconBox/FontIconBox.tsx b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
index 47dac651d..225df555b 100644
--- a/src/client/views/nodes/FontIconBox/FontIconBox.tsx
+++ b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
@@ -21,6 +21,7 @@ import { OpenWhere } from '../DocumentView';
 import { FieldView, FieldViewProps } from '../FieldView';
 import { RichTextMenu } from '../formattedText/RichTextMenu';
 import './FontIconBox.scss';
+import TrailsIcon from './TrailsIcon';
 
 export enum ButtonType {
     TextButton = 'textBtn',
@@ -92,8 +93,7 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
             else return null;
         }
         icon = StrCast(this.dataDoc[this.fieldKey ?? 'icon'] ?? this.dataDoc.icon, 'user') as any;
-        const trailsIcon = () => <img src={`/assets/${'presTrails.png'}`} style={{ width: 30, height: 30, filter: `invert(${color === Colors.DARK_GRAY ? '0%' : '100%'})` }} />;
-        return !icon ? null : icon === 'pres-trail' ? trailsIcon() : <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={icon} color={color} />;
+        return !icon ? null : icon === 'pres-trail' ? <TrailsIcon /> : <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={icon} color={color} />;
     };
     @computed get dropdown() {
         return BoolCast(this.rootDoc.dropDownOpen);
diff --git a/src/client/views/nodes/FontIconBox/TrailsIcon.tsx b/src/client/views/nodes/FontIconBox/TrailsIcon.tsx
new file mode 100644
index 000000000..99063b4a0
--- /dev/null
+++ b/src/client/views/nodes/FontIconBox/TrailsIcon.tsx
@@ -0,0 +1,83 @@
+import * as React from 'react';
+import { StrCast } from '../../../../fields/Types';
+import { Doc } from '../../../../fields/Doc';
+
+const TrailsIcon = () => (
+    <svg version="1.0" xmlns="http://www.w3.org/2000/svg" width="30" height="30" viewBox="0 0 1080.000000 1080.000000" preserveAspectRatio="xMidYMid meet">
+        <g transform="translate(0.000000,1080.000000) scale(0.100000,-0.100000)" fill={StrCast(Doc.UserDoc().userColor)} stroke="none">
+            <path
+                d="M665 9253 c-74 -10 -157 -38 -240 -81 -74 -37 -107 -63 -186 -141
+-104 -104 -156 -191 -201 -334 l-23 -72 0 -3215 c0 -3072 1 -3218 18 -3280 10
+-36 39 -108 64 -160 40 -82 59 -107 142 -190 81 -81 111 -103 191 -143 52 -26
+122 -55 155 -65 57 -16 322 -17 4775 -20 3250 -2 4736 1 4784 8 256 39 486
+220 588 462 63 148 59 -96 56 3413 -3 3049 -4 3203 -21 3260 -78 260 -285 467
+-542 542 -57 17 -308 18 -4795 19 -2604 1 -4748 -1 -4765 -3z m9187 -787 c65
+-19 114 -60 143 -120 l25 -51 0 -2898 c0 -2582 -2 -2901 -15 -2934 -24 -57
+-62 -101 -108 -126 l-42 -22 -4435 -3 c-3954 -2 -4440 0 -4481 13 -26 9 -63
+33 -87 56 -79 79 -72 -205 -72 3012 0 2156 3 2889 12 2918 20 70 91 136 168
+160 14 4 2010 8 4436 8 3710 1 4418 -1 4456 -13z"
+            />
+            <path
+                d="M7692 7839 c-46 -14 -109 -80 -122 -128 -7 -27 -9 -472 -8 -1443 l3
+-1403 24 -38 c13 -21 42 -50 64 -65 l41 -27 816 0 816 0 41 27 c22 15 51 44
+64 65 l24 38 0 1425 0 1425 -24 38 c-13 21 -42 50 -64 65 l-41 27 -800 2
+c-488 1 -814 -2 -834 -8z"
+            />
+            <path
+                d="M1982 7699 c-46 -14 -109 -80 -122 -128 -7 -27 -10 -308 -8 -893 l3
+-853 24 -38 c13 -21 42 -50 64 -65 l41 -27 1386 0 1386 0 41 27 c22 15 51 44
+64 65 l24 38 0 876 0 875 -27 41 c-15 22 -44 51 -65 64 l-38 24 -1370 2 c-847
+1 -1383 -2 -1403 -8z"
+            />
+            <path
+                d="M6413 7093 c-13 -2 -23 -9 -23 -15 0 -24 21 -307 26 -343 l5 -40 182
+-1 c200 -1 307 -15 484 -65 57 -16 107 -29 112 -29 5 0 36 75 69 168 33 92 63
+175 67 184 6 14 -10 22 -92 48 -126 39 -308 76 -447 89 -106 11 -337 13 -383
+4z"
+            />
+            <path
+                d="M5840 7033 c-63 -8 -238 -29 -388 -47 -150 -18 -274 -35 -276 -37 -2
+-2 8 -89 23 -194 22 -163 29 -190 44 -193 10 -2 91 6 180 17 89 12 258 32 376
+46 118 14 216 27 218 28 7 8 -43 391 -52 392 -5 1 -62 -4 -125 -12z"
+            />
+            <path
+                d="M4762 4789 c-46 -14 -109 -80 -122 -128 -7 -27 -10 -323 -8 -943 l3
+-903 24 -38 c13 -21 42 -50 64 -65 l41 -27 926 0 926 0 41 27 c22 15 51 44 64
+65 l24 38 0 926 0 925 -27 41 c-15 22 -44 51 -65 64 l-38 24 -910 2 c-557 1
+-923 -2 -943 -8z"
+            />
+            <path
+                d="M8487 4297 c-26 -215 -161 -474 -307 -585 -27 -20 -49 -40 -49 -44
+-1 -3 49 -79 110 -167 l110 -161 44 31 c176 126 333 350 418 594 30 86 77 282
+77 320 0 8 -57 19 -167 34 -93 13 -182 25 -199 28 -31 5 -31 5 -37 -50z"
+            />
+            <path
+                d="M3965 4233 c-106 -9 -348 -36 -415 -47 -55 -8 -75 -15 -74 -26 1 -20
+56 -374 59 -377 1 -2 46 4 101 12 159 24 409 45 526 45 l108 0 0 200 0 200
+-132 -2 c-73 -1 -151 -3 -173 -5z"
+            />
+            <path
+                d="M3020 4079 c-85 -23 -292 -94 -368 -125 -97 -40 -298 -140 -305 -151
+-5 -7 172 -315 192 -336 4 -4 41 10 82 32 103 55 272 123 414 165 66 20 125
+38 132 41 11 4 -4 70 -78 348 -10 39 -14 41 -69 26z"
+            />
+            <path
+                d="M6955 3538 c-21 -91 -74 -362 -72 -364 7 -7 260 -44 367 -54 146 -13
+359 -13 475 0 49 6 90 12 91 13 2 1 -12 90 -29 197 -26 155 -36 194 -47 192
+-8 -2 -85 -6 -170 -9 -160 -6 -357 7 -505 33 -103 18 -104 18 -110 -8z"
+            />
+            <path
+                d="M1993 3513 c-52 -67 -71 -106 -98 -198 -35 -122 -44 -284 -21 -415 9
+-51 18 -96 21 -98 4 -5 360 79 375 88 7 4 7 24 0 60 -21 109 -7 244 31 307
+l20 31 -146 131 c-80 72 -147 131 -149 131 -2 0 -17 -17 -33 -37z"
+            />
+            <path
+                d="M2210 2519 c-91 -50 -166 -92 -168 -94 -2 -1 11 -26 28 -54 l32 -51
+244 0 c134 0 244 2 244 5 0 3 -23 33 -51 67 -28 35 -72 98 -97 140 -26 43 -51
+77 -57 77 -5 0 -84 -41 -175 -90z"
+            />
+        </g>
+    </svg>
+);
+
+export default TrailsIcon;
-- 
cgit v1.2.3-70-g09d2


From 3960e2ed80317a14edaafeaeac07c9eeb405f513 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Sat, 26 Aug 2023 13:30:21 -0400
Subject: fixed color of trails icon

---
 src/client/views/nodes/FontIconBox/FontIconBox.tsx | 4 ++--
 src/client/views/nodes/FontIconBox/TrailsIcon.tsx  | 6 ++----
 2 files changed, 4 insertions(+), 6 deletions(-)

(limited to 'src/client/views/nodes/FontIconBox/FontIconBox.tsx')

diff --git a/src/client/views/nodes/FontIconBox/FontIconBox.tsx b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
index 225df555b..d132707fa 100644
--- a/src/client/views/nodes/FontIconBox/FontIconBox.tsx
+++ b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
@@ -7,6 +7,7 @@ import * as React from 'react';
 import { Doc, DocListCast, StrListCast } from '../../../../fields/Doc';
 import { ScriptField } from '../../../../fields/ScriptField';
 import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from '../../../../fields/Types';
+import { colorMapping } from '../../../../server/DashSession/Session/utilities/session_config';
 import { Utils } from '../../../../Utils';
 import { CollectionViewType, DocumentType } from '../../../documents/DocumentTypes';
 import { SelectionManager } from '../../../util/SelectionManager';
@@ -14,7 +15,6 @@ import { undoable, UndoManager } from '../../../util/UndoManager';
 import { ContextMenu } from '../../ContextMenu';
 import { DocComponent } from '../../DocComponent';
 import { EditableView } from '../../EditableView';
-import { Colors } from '../../global/globalEnums';
 import { SelectedDocView } from '../../selectedDoc';
 import { StyleProp } from '../../StyleProvider';
 import { OpenWhere } from '../DocumentView';
@@ -93,7 +93,7 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
             else return null;
         }
         icon = StrCast(this.dataDoc[this.fieldKey ?? 'icon'] ?? this.dataDoc.icon, 'user') as any;
-        return !icon ? null : icon === 'pres-trail' ? <TrailsIcon /> : <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={icon} color={color} />;
+        return !icon ? null : icon === 'pres-trail' ? TrailsIcon(color) : <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={icon} color={color} />;
     };
     @computed get dropdown() {
         return BoolCast(this.rootDoc.dropDownOpen);
diff --git a/src/client/views/nodes/FontIconBox/TrailsIcon.tsx b/src/client/views/nodes/FontIconBox/TrailsIcon.tsx
index 99063b4a0..09fd6e3ae 100644
--- a/src/client/views/nodes/FontIconBox/TrailsIcon.tsx
+++ b/src/client/views/nodes/FontIconBox/TrailsIcon.tsx
@@ -1,10 +1,8 @@
 import * as React from 'react';
-import { StrCast } from '../../../../fields/Types';
-import { Doc } from '../../../../fields/Doc';
 
-const TrailsIcon = () => (
+const TrailsIcon = (fill: string) => (
     <svg version="1.0" xmlns="http://www.w3.org/2000/svg" width="30" height="30" viewBox="0 0 1080.000000 1080.000000" preserveAspectRatio="xMidYMid meet">
-        <g transform="translate(0.000000,1080.000000) scale(0.100000,-0.100000)" fill={StrCast(Doc.UserDoc().userColor)} stroke="none">
+        <g transform="translate(0.000000,1080.000000) scale(0.100000,-0.100000)" fill={fill} stroke="none">
             <path
                 d="M665 9253 c-74 -10 -157 -38 -240 -81 -74 -37 -107 -63 -186 -141
 -104 -104 -156 -191 -201 -334 l-23 -72 0 -3215 c0 -3072 1 -3218 18 -3280 10
-- 
cgit v1.2.3-70-g09d2


From 8a43ea9c37fe9ae671391bc264e3760cd90d53c5 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Sun, 27 Aug 2023 14:21:10 -0400
Subject: working cleanup version

---
 src/client/util/GroupManager.tsx                   | 14 +++++++-------
 src/client/util/SettingsManager.tsx                | 15 ++-------------
 src/client/util/SharingManager.tsx                 |  1 -
 src/client/views/MainView.tsx                      | 17 ++++++++---------
 src/client/views/MainViewModal.tsx                 |  9 ++++-----
 src/client/views/nodes/FontIconBox/FontIconBox.tsx |  1 -
 6 files changed, 21 insertions(+), 36 deletions(-)

(limited to 'src/client/views/nodes/FontIconBox/FontIconBox.tsx')

diff --git a/src/client/util/GroupManager.tsx b/src/client/util/GroupManager.tsx
index f35844020..c79894032 100644
--- a/src/client/util/GroupManager.tsx
+++ b/src/client/util/GroupManager.tsx
@@ -1,22 +1,22 @@
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { Button, IconButton, Size, Type } from 'browndash-components';
 import { action, computed, observable } from 'mobx';
 import { observer } from 'mobx-react';
 import * as React from 'react';
 import Select from 'react-select';
 import * as RequestPromise from 'request-promise';
-import { Doc, DocListCast, DocListCastAsync, Opt } from '../../fields/Doc';
-import { StrCast, Cast } from '../../fields/Types';
+import { DateField } from '../../fields/DateField';
+import { Doc, DocListCast, Opt } from '../../fields/Doc';
+import { Id } from '../../fields/FieldSymbols';
+import { listSpec } from '../../fields/Schema';
+import { Cast, StrCast } from '../../fields/Types';
 import { Utils } from '../../Utils';
 import { MainViewModal } from '../views/MainViewModal';
 import { TaskCompletionBox } from '../views/nodes/TaskCompletedBox';
 import './GroupManager.scss';
 import { GroupMemberView } from './GroupMemberView';
-import { SharingManager, User } from './SharingManager';
-import { listSpec } from '../../fields/Schema';
-import { DateField } from '../../fields/DateField';
-import { Id } from '../../fields/FieldSymbols';
-import { Button, IconButton, Size, Type } from 'browndash-components';
 import { SettingsManager } from './SettingsManager';
+import { SharingManager, User } from './SharingManager';
 
 /**
  * Interface for options for the react-select component
diff --git a/src/client/util/SettingsManager.tsx b/src/client/util/SettingsManager.tsx
index 4814c3644..bb370e1a4 100644
--- a/src/client/util/SettingsManager.tsx
+++ b/src/client/util/SettingsManager.tsx
@@ -48,13 +48,6 @@ export class SettingsManager extends React.Component<{}> {
     @observable public static propertiesWidth: number = 0;
     @observable public static headerBarHeight: number = 0;
 
-    @computed get backgroundColor() {
-        return Doc.UserDoc().activeCollectionBackground;
-    }
-    @computed get userTheme() {
-        return Doc.UserDoc().userTheme;
-    }
-
     constructor(props: {}) {
         super(props);
         SettingsManager.Instance = this;
@@ -94,12 +87,8 @@ export class SettingsManager extends React.Component<{}> {
         Doc.UserDoc().userBackgroundColor = color;
         addStyleSheetRule(SettingsManager._settingsStyle, 'lm_header', { background: `${color} !important` });
     });
-    @undoBatch switchUserColor = action((color: string) => {
-        Doc.UserDoc().userColor = color;
-    });
-    @undoBatch switchUserVariantColor = action((color: string) => {
-        Doc.UserDoc().userVariantColor = color;
-    });
+    @undoBatch switchUserColor = action((color: string) => (Doc.UserDoc().userColor = color));
+    @undoBatch switchUserVariantColor = action((color: string) => (Doc.UserDoc().userVariantColor = color));
     @undoBatch playgroundModeToggle = action(() => {
         this.playgroundMode = !this.playgroundMode;
         if (this.playgroundMode) {
diff --git a/src/client/util/SharingManager.tsx b/src/client/util/SharingManager.tsx
index 6171c01d7..81ddeb9e3 100644
--- a/src/client/util/SharingManager.tsx
+++ b/src/client/util/SharingManager.tsx
@@ -22,7 +22,6 @@ import { SearchBox } from '../views/search/SearchBox';
 import { DocumentManager } from './DocumentManager';
 import { GroupManager, UserOptions } from './GroupManager';
 import { GroupMemberView } from './GroupMemberView';
-import { LinkManager } from './LinkManager';
 import { SelectionManager } from './SelectionManager';
 import { SettingsManager } from './SettingsManager';
 import './SharingManager.scss';
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 9ffb804f2..6a743a5e6 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -43,7 +43,6 @@ import { DictationOverlay } from './DictationOverlay';
 import { DocumentDecorations } from './DocumentDecorations';
 import { GestureOverlay } from './GestureOverlay';
 import { LEFT_MENU_WIDTH, TOPBAR_HEIGHT } from './global/globalCssVariables.scss';
-import { Colors } from './global/globalEnums';
 import { KeyManager } from './GlobalKeyHandler';
 import { InkTranscription } from './InkTranscription';
 import { LightboxView } from './LightboxView';
@@ -748,7 +747,7 @@ export class MainView extends React.Component {
 
     @computed get leftMenuPanel() {
         return (
-            <div key="menu" className="mainView-leftMenuPanel" style={{ background: SettingsManager.Instance.userBackgroundColor, display: LightboxView.LightboxDoc ? 'none' : undefined }}>
+            <div key="menu" className="mainView-leftMenuPanel" style={{ background: StrCast(Doc.UserDoc().userBackgroundColor), display: LightboxView.LightboxDoc ? 'none' : undefined }}>
                 <DocumentView
                     Document={Doc.MyLeftSidebarMenu}
                     DataDoc={undefined}
@@ -805,16 +804,16 @@ export class MainView extends React.Component {
                     {this.flyout}
                     <div
                         className="mainView-libraryHandle"
-                        style={{ background: SettingsManager.Instance.userBackgroundColor, left: leftMenuFlyoutWidth - 10 /* ~half width of handle */, display: !this._leftMenuFlyoutWidth ? 'none' : undefined }}
+                        style={{ background: StrCast(Doc.UserDoc().userBackgroundColor), left: leftMenuFlyoutWidth - 10 /* ~half width of handle */, display: !this._leftMenuFlyoutWidth ? 'none' : undefined }}
                         onPointerDown={this.onFlyoutPointerDown}>
-                        <FontAwesomeIcon icon="chevron-left" color={SettingsManager.Instance.userColor} style={{ opacity: '50%' }} size="sm" />
+                        <FontAwesomeIcon icon="chevron-left" color={StrCast(Doc.UserDoc().userColor)} style={{ opacity: '50%' }} size="sm" />
                     </div>
                     <div className="mainView-innerContainer" style={{ width: `calc(100% - ${width}px)` }}>
                         {this.dockingContent}
 
                         {this._hideUI ? null : (
-                            <div className="mainView-propertiesDragger" key="props" onPointerDown={this.onPropertiesPointerDown} style={{ background: SettingsManager.Instance.userBackgroundColor, right: this.propertiesWidth() - 1 }}>
-                                <FontAwesomeIcon icon={this.propertiesWidth() < 10 ? 'chevron-left' : 'chevron-right'} color={SettingsManager.Instance.userColor} size="sm" />
+                            <div className="mainView-propertiesDragger" key="props" onPointerDown={this.onPropertiesPointerDown} style={{ background: StrCast(Doc.UserDoc().userBackgroundColor), right: this.propertiesWidth() - 1 }}>
+                                <FontAwesomeIcon icon={this.propertiesWidth() < 10 ? 'chevron-left' : 'chevron-right'} color={StrCast(Doc.UserDoc().userColor)} size="sm" />
                             </div>
                         )}
                         <div className="properties-container" style={{ width: this.propertiesWidth() }}>
@@ -880,7 +879,7 @@ export class MainView extends React.Component {
 
     @computed get docButtons() {
         return !Doc.MyDockedBtns ? null : (
-            <div className="mainView-docButtons" style={{ background: SettingsManager.Instance.userBackgroundColor, color: SettingsManager.Instance.userColor }} ref={this._docBtnRef}>
+            <div className="mainView-docButtons" style={{ background: StrCast(Doc.UserDoc().userBackgroundColor), color: StrCast(Doc.UserDoc().userColor) }} ref={this._docBtnRef}>
                 <CollectionLinearView
                     Document={Doc.MyDockedBtns}
                     DataDoc={undefined}
@@ -999,8 +998,8 @@ export class MainView extends React.Component {
             <div
                 className={`mainView-container ${this.colorScheme}`}
                 style={{
-                    color: SettingsManager.Instance.userColor,
-                    background: SettingsManager.Instance.userBackgroundColor,
+                    color: StrCast(Doc.UserDoc().userColor),
+                    background: StrCast(Doc.UserDoc().userBackgroundColor),
                 }}
                 onScroll={() => (ele => (ele.scrollTop = ele.scrollLeft = 0))(document.getElementById('root')!)}
                 ref={r => {
diff --git a/src/client/views/MainViewModal.tsx b/src/client/views/MainViewModal.tsx
index 42df99864..d0a79eb70 100644
--- a/src/client/views/MainViewModal.tsx
+++ b/src/client/views/MainViewModal.tsx
@@ -1,10 +1,9 @@
-import * as React from 'react';
-import './MainViewModal.scss';
+import { isDark } from 'browndash-components';
 import { observer } from 'mobx-react';
+import * as React from 'react';
 import { Doc } from '../../fields/Doc';
 import { StrCast } from '../../fields/Types';
-import { isDark } from 'browndash-components';
-import { Colors } from './global/globalEnums';
+import './MainViewModal.scss';
 
 export interface MainViewOverlayProps {
     isDisplayed: boolean;
@@ -45,7 +44,7 @@ export class MainViewModal extends React.Component<MainViewOverlayProps> {
                     className="overlay"
                     onClick={this.props?.closeOnExternalClick}
                     style={{
-                        backgroundColor: isDark(StrCast(Doc.UserDoc().userColor)) ? "#DFDFDF30" : "#32323230",
+                        backgroundColor: isDark(StrCast(Doc.UserDoc().userColor)) ? '#DFDFDF30' : '#32323230',
                         ...(p.overlayStyle || {}),
                     }}
                 />
diff --git a/src/client/views/nodes/FontIconBox/FontIconBox.tsx b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
index d132707fa..94650cc88 100644
--- a/src/client/views/nodes/FontIconBox/FontIconBox.tsx
+++ b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
@@ -7,7 +7,6 @@ import * as React from 'react';
 import { Doc, DocListCast, StrListCast } from '../../../../fields/Doc';
 import { ScriptField } from '../../../../fields/ScriptField';
 import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from '../../../../fields/Types';
-import { colorMapping } from '../../../../server/DashSession/Session/utilities/session_config';
 import { Utils } from '../../../../Utils';
 import { CollectionViewType, DocumentType } from '../../../documents/DocumentTypes';
 import { SelectionManager } from '../../../util/SelectionManager';
-- 
cgit v1.2.3-70-g09d2


From 9d6c7f8100de3a952d20ad41ab20872737cb909e Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Sun, 27 Aug 2023 20:25:55 -0400
Subject: lots of cleanup to streamline import orderings (ie packages should
 not mutually import each other directly or via a chain).  change
 raiseWhenDragged to be keepZWhenDragged and got rid of system wide default.

---
 src/Utils.ts                                       |   2 +-
 src/client/DocServer.ts                            |  15 ++-
 src/client/apis/youtube/YoutubeBox.tsx             |   6 +-
 src/client/documents/Documents.ts                  |  10 +-
 src/client/util/CurrentUserUtils.ts                |  11 +-
 src/client/util/DictationManager.ts                |   2 +-
 src/client/util/DocumentManager.ts                 |  22 +++-
 src/client/util/DragManager.ts                     |  21 +---
 src/client/util/DropConverter.ts                   |  14 +--
 src/client/util/GroupManager.tsx                   |   4 +-
 src/client/util/GroupMemberView.tsx                |   2 +-
 src/client/util/SearchUtil.ts                      | 104 ++++++++++++++-
 src/client/util/SettingsManager.tsx                |  89 ++++++-------
 src/client/util/SharingManager.tsx                 |  10 +-
 src/client/util/reportManager/ReportManager.tsx    |   4 +-
 src/client/views/ContextMenuItem.tsx               |   6 +-
 src/client/views/DocumentDecorations.tsx           |  11 +-
 src/client/views/EditableView.tsx                  |   1 -
 src/client/views/FilterPanel.tsx                   |  23 ++--
 src/client/views/LightboxView.tsx                  |  11 +-
 src/client/views/Main.tsx                          |   6 +-
 src/client/views/MainView.tsx                      |  38 +++---
 src/client/views/PropertiesView.tsx                |  20 +--
 src/client/views/SidebarAnnos.tsx                  |   4 +-
 src/client/views/StyleProvider.tsx                 |  15 ++-
 src/client/views/UndoStack.tsx                     |   2 +-
 .../views/collections/CollectionDockingView.tsx    |   4 +-
 src/client/views/collections/CollectionMenu.tsx    |   2 +-
 .../collections/CollectionStackedTimeline.tsx      |   4 +-
 src/client/views/collections/TabDocView.tsx        |  13 +-
 src/client/views/collections/TreeSort.ts           |   6 +
 src/client/views/collections/TreeView.tsx          |  11 +-
 .../collectionFreeForm/CollectionFreeFormView.tsx  |   4 +-
 src/client/views/linking/LinkPopup.tsx             |   3 +-
 .../views/newlightbox/ButtonMenu/ButtonMenu.tsx    |  19 ++-
 src/client/views/newlightbox/NewLightboxView.tsx   | 139 ++++++++++-----------
 src/client/views/nodes/DocumentView.tsx            |  16 ++-
 src/client/views/nodes/FontIconBox/FontIconBox.tsx |  17 +--
 src/client/views/nodes/LinkDocPreview.tsx          |   6 +-
 src/client/views/nodes/LoadingBox.tsx              |   6 +-
 src/client/views/nodes/ScreenshotBox.tsx           |   6 +-
 src/client/views/nodes/VideoBox.tsx                |   5 +-
 .../views/nodes/formattedText/FormattedTextBox.tsx |  24 ++--
 .../views/nodes/generativeFill/GenerativeFill.tsx  |  33 +++--
 src/client/views/nodes/trails/PresBox.tsx          |   4 +-
 src/client/views/pdf/AnchorMenu.tsx                |  15 +--
 src/client/views/search/IconBar.tsx                |  28 +++--
 src/client/views/search/SearchBox.tsx              | 110 +---------------
 src/client/views/topbar/TopBar.tsx                 |  16 ++-
 src/client/views/webcam/DashWebRTCVideo.tsx        |   6 +-
 src/fields/Doc.ts                                  |  26 +++-
 src/fields/RichTextUtils.ts                        |  10 +-
 52 files changed, 492 insertions(+), 494 deletions(-)
 create mode 100644 src/client/views/collections/TreeSort.ts

(limited to 'src/client/views/nodes/FontIconBox/FontIconBox.tsx')

diff --git a/src/Utils.ts b/src/Utils.ts
index 7f83ab8f5..9a94694a2 100644
--- a/src/Utils.ts
+++ b/src/Utils.ts
@@ -3,10 +3,10 @@ import v5 = require('uuid/v5');
 import { ColorState } from 'react-color';
 import * as rp from 'request-promise';
 import { Socket } from 'socket.io';
+import { DocumentType } from './client/documents/DocumentTypes';
 import { Colors } from './client/views/global/globalEnums';
 import { Message } from './server/Message';
 import Color = require('color');
-import { DocumentType } from './client/documents/DocumentTypes';
 
 export namespace Utils {
     export let CLICK_TIME = 300;
diff --git a/src/client/DocServer.ts b/src/client/DocServer.ts
index 53c7b857a..5fdea131b 100644
--- a/src/client/DocServer.ts
+++ b/src/client/DocServer.ts
@@ -1,6 +1,5 @@
 import { runInAction } from 'mobx';
 import * as rp from 'request-promise';
-import * as io from 'socket.io-client';
 import { Doc, DocListCast, Opt } from '../fields/Doc';
 import { UpdatingFromServer } from '../fields/DocSymbols';
 import { FieldLoader } from '../fields/FieldLoader';
@@ -8,13 +7,13 @@ import { HandleUpdate, Id, Parent } from '../fields/FieldSymbols';
 import { ObjectField } from '../fields/ObjectField';
 import { RefField } from '../fields/RefField';
 import { DocCast, StrCast } from '../fields/Types';
-import MobileInkOverlay from '../mobile/MobileInkOverlay';
+//import MobileInkOverlay from '../mobile/MobileInkOverlay';
 import { emptyFunction, Utils } from '../Utils';
 import { GestureContent, MessageStore, MobileDocumentUploadContent, MobileInkOverlayContent, UpdateMobileInkOverlayPositionContent, YoutubeQueryTypes } from './../server/Message';
 import { DocumentType } from './documents/DocumentTypes';
 import { LinkManager } from './util/LinkManager';
 import { SerializationHelper } from './util/SerializationHelper';
-import { GestureOverlay } from './views/GestureOverlay';
+//import { GestureOverlay } from './views/GestureOverlay';
 
 /**
  * This class encapsulates the transfer and cross-client synchronization of
@@ -189,17 +188,17 @@ export namespace DocServer {
 
         // mobile ink overlay socket events to communicate between mobile view and desktop view
         _socket.addEventListener('receiveGesturePoints', (content: GestureContent) => {
-            MobileInkOverlay.Instance.drawStroke(content);
+            //   MobileInkOverlay.Instance.drawStroke(content);
         });
         _socket.addEventListener('receiveOverlayTrigger', (content: MobileInkOverlayContent) => {
-            GestureOverlay.Instance.enableMobileInkOverlay(content);
-            MobileInkOverlay.Instance.initMobileInkOverlay(content);
+            //GestureOverlay.Instance.enableMobileInkOverlay(content);
+            //    MobileInkOverlay.Instance.initMobileInkOverlay(content);
         });
         _socket.addEventListener('receiveUpdateOverlayPosition', (content: UpdateMobileInkOverlayPositionContent) => {
-            MobileInkOverlay.Instance.updatePosition(content);
+            //   MobileInkOverlay.Instance.updatePosition(content);
         });
         _socket.addEventListener('receiveMobileDocumentUpload', (content: MobileDocumentUploadContent) => {
-            MobileInkOverlay.Instance.uploadDocument(content);
+            //   MobileInkOverlay.Instance.uploadDocument(content);
         });
     }
 
diff --git a/src/client/apis/youtube/YoutubeBox.tsx b/src/client/apis/youtube/YoutubeBox.tsx
index 05879a247..2da9927c0 100644
--- a/src/client/apis/youtube/YoutubeBox.tsx
+++ b/src/client/apis/youtube/YoutubeBox.tsx
@@ -6,7 +6,7 @@ import { Cast, NumCast, StrCast } from '../../../fields/Types';
 import { Utils } from '../../../Utils';
 import { DocServer } from '../../DocServer';
 import { Docs } from '../../documents/Documents';
-import { DocumentDecorations } from '../../views/DocumentDecorations';
+import { DocumentView } from '../../views/nodes/DocumentView';
 import { FieldView, FieldViewProps } from '../../views/nodes/FieldView';
 import '../../views/nodes/WebBox.scss';
 import './YoutubeBox.scss';
@@ -355,9 +355,9 @@ export class YoutubeBox extends React.Component<FieldViewProps> {
             </div>
         );
 
-        const frozen = !this.props.isSelected() || DocumentDecorations.Instance.Interacting;
+        const frozen = !this.props.isSelected() || DocumentView.Interacting;
 
-        const classname = 'webBox-cont' + (this.props.isSelected() && Doc.ActiveTool === InkTool.None && !DocumentDecorations.Instance.Interacting ? '-interactive' : '');
+        const classname = 'webBox-cont' + (this.props.isSelected() && Doc.ActiveTool === InkTool.None && !DocumentView.Interacting ? '-interactive' : '');
         return (
             <>
                 <div className={classname}>{content}</div>
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 1186446e1..919958b24 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -19,7 +19,6 @@ import { aggregateBounds, OmitKeys, Utils } from '../../Utils';
 import { YoutubeBox } from '../apis/youtube/YoutubeBox';
 import { DocServer } from '../DocServer';
 import { Networking } from '../Network';
-import { DocumentManager } from '../util/DocumentManager';
 import { DragManager, dropActionType } from '../util/DragManager';
 import { DirectoryImportBox } from '../util/Import & Export/DirectoryImportBox';
 import { FollowLinkScript } from '../util/LinkFollower';
@@ -34,12 +33,12 @@ import { ContextMenuProps } from '../views/ContextMenuItem';
 import { DFLT_IMAGE_NATIVE_DIM } from '../views/global/globalCssVariables.scss';
 import { ActiveArrowEnd, ActiveArrowStart, ActiveDash, ActiveFillColor, ActiveInkBezierApprox, ActiveInkColor, ActiveInkWidth, ActiveIsInkMask, InkingStroke } from '../views/InkingStroke';
 import { AudioBox } from '../views/nodes/AudioBox';
-import { FontIconBox } from '../views/nodes/FontIconBox/FontIconBox';
 import { ColorBox } from '../views/nodes/ColorBox';
 import { ComparisonBox } from '../views/nodes/ComparisonBox';
 import { DataVizBox } from '../views/nodes/DataVizBox/DataVizBox';
 import { EquationBox } from '../views/nodes/EquationBox';
 import { FieldViewProps } from '../views/nodes/FieldView';
+import { FontIconBox } from '../views/nodes/FontIconBox/FontIconBox';
 import { FormattedTextBox } from '../views/nodes/formattedText/FormattedTextBox';
 import { FunctionPlotBox } from '../views/nodes/FunctionPlotBox';
 import { ImageBox } from '../views/nodes/ImageBox';
@@ -394,7 +393,7 @@ export class DocumentOptions {
     onPointerUp?: ScriptField;
     _forceActive?: BOOLt = new BoolInfo('flag to handle pointer events when not selected (or otherwise active)');
     _dragOnlyWithinContainer?: BOOLt = new BoolInfo('whether the document should remain in its collection when someone tries to drag and drop it elsewhere');
-    _raiseWhenDragged?: BOOLt = new BoolInfo('whether a document is brought to front when dragged.');
+    _keepZWhenDragged?: BOOLt = new BoolInfo('whether a document should keep its z-order when dragged.');
     childDragAction?: DROPt = new DAInfo('what should happen to the child documents when they are dragged from the collection');
     dropConverter?: ScriptField; // script to run when documents are dropped on this Document.
     dropAction?: DROPt = new DAInfo("what should happen to this document when it's dropped somewhere else");
@@ -1371,7 +1370,7 @@ export namespace DocUtils {
     export let ActiveRecordings: { props: FieldViewProps; getAnchor: (addAsAnnotation: boolean) => Doc }[] = [];
 
     export function MakeLinkToActiveAudio(getSourceDoc: () => Doc | undefined, broadcastEvent = true) {
-        broadcastEvent && runInAction(() => (DocumentManager.Instance.RecordingEvent = DocumentManager.Instance.RecordingEvent + 1));
+        broadcastEvent && runInAction(() => (Doc.RecordingEvent = Doc.RecordingEvent + 1));
         return DocUtils.ActiveRecordings.map(audio => {
             const sourceDoc = getSourceDoc();
             return sourceDoc && DocUtils.MakeLink(sourceDoc, audio.getAnchor(true) || audio.props.Document, { link_displayLine: false, link_relationship: 'recording annotation:linked recording', link_description: 'recording timeline' });
@@ -1380,7 +1379,6 @@ export namespace DocUtils {
 
     export function MakeLink(source: Doc, target: Doc, linkSettings: { link_relationship?: string; link_description?: string; link_displayLine?: boolean }, id?: string, showPopup?: number[]) {
         if (!linkSettings.link_relationship) linkSettings.link_relationship = target.type === DocumentType.RTF ? 'Commentary:Comments On' : 'link';
-        const sv = DocumentManager.Instance.getDocumentView(source);
         if (target.doc === Doc.UserDoc()) return undefined;
 
         const makeLink = action((linkDoc: Doc, showPopup?: number[]) => {
@@ -1840,8 +1838,6 @@ export namespace DocUtils {
             }
             if (overwriteDoc) {
                 Doc.removeCurrentlyLoading(overwriteDoc);
-                // loading doc icons are just labels. so any icon views of loading docs need to be replaced with the proper icon view.
-                DocumentManager.Instance.getAllDocumentViews(overwriteDoc).forEach(dv => StrCast(dv.rootDoc.layout_fieldKey) === 'layout_icon' && dv.iconify(() => dv.iconify()));
             }
             generatedDocuments.push(doc);
         }
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index ea995e4af..d52e389d6 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -18,7 +18,6 @@ import { CollectionViewType, DocumentType } from "../documents/DocumentTypes";
 import { TreeViewType } from "../views/collections/CollectionTreeView";
 import { DashboardView } from "../views/DashboardView";
 import { Colors } from "../views/global/globalEnums";
-import { MainView } from "../views/MainView";
 import { OpenWhere } from "../views/nodes/DocumentView";
 import { ButtonType } from "../views/nodes/FontIconBox/FontIconBox";
 import { ImportElementBox } from "../views/nodes/importBox/ImportElementBox";
@@ -621,9 +620,9 @@ export class CurrentUserUtils {
 
     static freeTools(): Button[] {
         return [
-            { title: "Bottom",  icon: "arrows-down-to-line",toolTip: "Make doc topmost",                                   btnType: ButtonType.ClickButton,  expertMode: false, funcs: {}, scripts: { onClick: 'sendToBack()'}}, // Only when floating document is selected in freeform
-            { title: "Top",     icon: "arrows-up-to-line",  toolTip: "Make doc bottommost",                                btnType: ButtonType.ClickButton,  expertMode: false, funcs: {}, scripts: { onClick: 'bringToFront()'}}, // Only when floating document is selected in freeform
-            { title: "Z order", icon: "z",                  toolTip: "Bring Forward on Drag (double click to set for all)",waitForDoubleClickToClick:true, btnType: ButtonType.ToggleButton, expertMode: false, funcs: {}, scripts: { onClick: 'toggleRaiseOnDrag(false, _readOnly_)', onDoubleClick:`{ return toggleRaiseOnDrag(true, _readOnly_)`}}, // Only when floating document is selected in freeform
+            { title: "Bottom",  icon: "arrows-down-to-line",toolTip: "Make doc topmost",     btnType: ButtonType.ClickButton,  expertMode: false, funcs: {}, scripts: { onClick: 'sendToBack()'}}, // Only when floating document is selected in freeform
+            { title: "Top",     icon: "arrows-up-to-line",  toolTip: "Make doc bottommost",  btnType: ButtonType.ClickButton,  expertMode: false, funcs: {}, scripts: { onClick: 'bringToFront()'}}, // Only when floating document is selected in freeform
+            { title: "Z order", icon: "z",                  toolTip: "Keep Z order on Drag", btnType: ButtonType.ToggleButton, expertMode: false, funcs: {}, scripts: { onClick: '{ return toggleRaiseOnDrag(_readOnly_);}'}}, // Only when floating document is selected in freeform
         ]
     }
     static viewTools(): Button[] {
@@ -841,7 +840,6 @@ export class CurrentUserUtils {
         doc.isSystem ?? (doc.isSystem = true);
         doc.title ?? (doc.title = Doc.CurrentUserEmail);
         Doc.noviceMode ?? (Doc.noviceMode = true);
-        doc._raiseWhenDragged ?? (doc._raiseWhenDragged = true);
         doc._showLabel ?? (doc._showLabel = true);
         doc.textAlign ?? (doc.textAlign = "left");
         doc.activeTool = InkTool.None;
@@ -996,8 +994,5 @@ export class CurrentUserUtils {
 ScriptingGlobals.add(function MySharedDocs() { return Doc.MySharedDocs; }, "document containing all shared Docs");
 ScriptingGlobals.add(function IsNoviceMode() { return Doc.noviceMode; }, "is Dash in novice mode");
 ScriptingGlobals.add(function toggleComicMode() { Doc.UserDoc().renderStyle = Doc.UserDoc().renderStyle === "comic" ? undefined : "comic"; }, "switches between comic and normal document rendering");
-ScriptingGlobals.add(function createNewPresentation() { return MainView.Instance.createNewPresentation(); }, "creates a new presentation when called");
-ScriptingGlobals.add(function openPresentation(pres:Doc) { return MainView.Instance.openPresentation(pres); }, "creates a new presentation when called");
-ScriptingGlobals.add(function createNewFolder() { return MainView.Instance.createNewFolder(); }, "creates a new folder in myFiles when called");
 ScriptingGlobals.add(function importDocument() { return CurrentUserUtils.importDocument(); }, "imports files from device directly into the import sidebar");
 ScriptingGlobals.add(function setInkToolDefaults() { Doc.ActiveTool = InkTool.None; });
\ No newline at end of file
diff --git a/src/client/util/DictationManager.ts b/src/client/util/DictationManager.ts
index 717473aa1..0fd7e840c 100644
--- a/src/client/util/DictationManager.ts
+++ b/src/client/util/DictationManager.ts
@@ -11,7 +11,7 @@ import { Utils } from '../../Utils';
 import { Docs } from '../documents/Documents';
 import { DocumentType } from '../documents/DocumentTypes';
 import { DictationOverlay } from '../views/DictationOverlay';
-import { DocumentView, OpenWhere, OpenWhereMod } from '../views/nodes/DocumentView';
+import { DocumentView, OpenWhere } from '../views/nodes/DocumentView';
 import { SelectionManager } from './SelectionManager';
 import { UndoManager } from './UndoManager';
 
diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts
index 5b627c2f3..c2827dac7 100644
--- a/src/client/util/DocumentManager.ts
+++ b/src/client/util/DocumentManager.ts
@@ -1,4 +1,4 @@
-import { action, computed, observable, ObservableSet } from 'mobx';
+import { action, computed, observable, ObservableSet, observe, reaction } from 'mobx';
 import { Doc, DocListCast, Opt } from '../../fields/Doc';
 import { AclAdmin, AclEdit, Animation } from '../../fields/DocSymbols';
 import { Id } from '../../fields/FieldSymbols';
@@ -23,7 +23,6 @@ export class DocumentManager {
     //global holds all of the nodes (regardless of which collection they're in)
     @observable _documentViews = new Set<DocumentView>();
     @observable public LinkAnchorBoxViews: DocumentView[] = [];
-    @observable public RecordingEvent = 0;
     @observable public LinkedDocumentViews: { a: DocumentView; b: DocumentView; l: Doc }[] = [];
     @computed public get DocumentViews() {
         return Array.from(this._documentViews).filter(view => !(view.ComponentView instanceof KeyValueBox) && (!LightboxView.LightboxDoc || LightboxView.IsLightboxDocView(view.docViewPath)));
@@ -41,7 +40,22 @@ export class DocumentManager {
     }
 
     //private constructor so no other class can create a nodemanager
-    private constructor() {}
+    private constructor() {
+        if (!Doc.CurrentlyLoading) Doc.CurrentlyLoading = [];
+        observe(Doc.CurrentlyLoading, change => {
+            // watch CurrentlyLoading-- when something is loaded, it's removed from the list and we have to update its icon if it were iconified since LoadingBox icons are different than the media they become
+            switch (change.type as any) {
+                case 'update':
+                    break;
+                case 'remove':
+                    // DocumentManager.Instance.getAllDocumentViews(change as any).forEach(dv => StrCast(dv.rootDoc.layout_fieldKey) === 'layout_icon' && dv.iconify(() => dv.iconify()));
+                    break;
+                case 'splice':
+                    (change as any).removed.forEach((doc: Doc) => DocumentManager.Instance.getAllDocumentViews(doc).forEach(dv => StrCast(dv.rootDoc.layout_fieldKey) === 'layout_icon' && dv.iconify(() => dv.iconify())));
+                    break;
+            }
+        });
+    }
 
     private _viewRenderedCbs: { doc: Doc; func: (dv: DocumentView) => any }[] = [];
     public AddViewRenderedCb = (doc: Opt<Doc>, func: (dv: DocumentView) => any) => {
@@ -310,7 +324,7 @@ export class DocumentManager {
         if (viewSpec && docView) {
             if (docView.ComponentView instanceof FormattedTextBox) docView.ComponentView?.focus(viewSpec, options);
             PresBox.restoreTargetDocView(docView, viewSpec, options.zoomTime ?? 500);
-            Doc.linkFollowHighlight(viewSpec ? [docView.rootDoc, viewSpec]: docView.rootDoc, undefined, options.effect);
+            Doc.linkFollowHighlight(viewSpec ? [docView.rootDoc, viewSpec] : docView.rootDoc, undefined, options.effect);
             if (options.playAudio) DocumentManager.playAudioAnno(docView.rootDoc);
             if (options.toggleTarget && (!options.didMove || docView.rootDoc.hidden)) docView.rootDoc.hidden = !docView.rootDoc.hidden;
             if (options.effect) docView.rootDoc[Animation] = options.effect;
diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index 489c9df4a..05da5ebed 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -61,12 +61,6 @@ export namespace DragManager {
     export let StartWindowDrag: Opt<(e: { pageX: number; pageY: number }, dragDocs: Doc[], finishDrag?: (aborted: boolean) => void) => void>;
     export let CompleteWindowDrag: Opt<(aborted: boolean) => void>;
 
-    export function GetRaiseWhenDragged() {
-        return BoolCast(Doc.UserDoc()._raiseWhenDragged);
-    }
-    export function SetRaiseWhenDragged(val: boolean) {
-        Doc.UserDoc()._raiseWhenDragged = val;
-    }
     export function Root() {
         const root = document.getElementById('root');
         if (!root) {
@@ -605,18 +599,9 @@ export namespace DragManager {
     }
 }
 
-ScriptingGlobals.add(function toggleRaiseOnDrag(forAllDocs: boolean, readOnly?: boolean) {
+ScriptingGlobals.add(function toggleRaiseOnDrag(readOnly?: boolean) {
     if (readOnly) {
-        if (SelectionManager.Views().length)
-            return SelectionManager.Views().some(dv => dv.rootDoc.raiseWhenDragged)
-                ? Colors.MEDIUM_BLUE
-                : SelectionManager.Views().some(dv => dv.rootDoc.raiseWhenDragged === false)
-                ? 'transparent'
-                : DragManager.GetRaiseWhenDragged()
-                ? Colors.MEDIUM_BLUE_ALT
-                : Colors.LIGHT_BLUE;
-        return DragManager.GetRaiseWhenDragged() ? Colors.MEDIUM_BLUE_ALT : 'transparent';
+        return SelectionManager.Views().some(dv => dv.rootDoc.keepZWhenDragged);
     }
-    if (!forAllDocs) SelectionManager.Views().map(dv => (dv.rootDoc.raiseWhenDragged ? (dv.rootDoc.raiseWhenDragged = undefined) : dv.rootDoc.raiseWhenDragged === false ? (dv.rootDoc.raiseWhenDragged = true) : (dv.rootDoc.raiseWhenDragged = false)));
-    else DragManager.SetRaiseWhenDragged(!DragManager.GetRaiseWhenDragged());
+    SelectionManager.Views().map(dv => (dv.rootDoc.keepZWhenDragged = !dv.rootDoc.keepZWhenDragged));
 });
diff --git a/src/client/util/DropConverter.ts b/src/client/util/DropConverter.ts
index f235be192..dbdf580cd 100644
--- a/src/client/util/DropConverter.ts
+++ b/src/client/util/DropConverter.ts
@@ -1,15 +1,15 @@
-import { DragManager } from './DragManager';
 import { Doc, DocListCast, Opt } from '../../fields/Doc';
-import { DocumentType } from '../documents/DocumentTypes';
 import { ObjectField } from '../../fields/ObjectField';
-import { StrCast, Cast } from '../../fields/Types';
-import { Docs } from '../documents/Documents';
-import { ScriptField, ComputedField } from '../../fields/ScriptField';
 import { RichTextField } from '../../fields/RichTextField';
-import { ImageField } from '../../fields/URLField';
-import { ScriptingGlobals } from './ScriptingGlobals';
 import { listSpec } from '../../fields/Schema';
+import { ScriptField } from '../../fields/ScriptField';
+import { Cast, StrCast } from '../../fields/Types';
+import { ImageField } from '../../fields/URLField';
+import { Docs } from '../documents/Documents';
+import { DocumentType } from '../documents/DocumentTypes';
 import { ButtonType } from '../views/nodes/FontIconBox/FontIconBox';
+import { DragManager } from './DragManager';
+import { ScriptingGlobals } from './ScriptingGlobals';
 
 export function MakeTemplate(doc: Doc, first: boolean = true, rename: Opt<string> = undefined, templateField: string = '') {
     if (templateField) Doc.GetProto(doc).title = templateField; /// the title determines which field is being templated
diff --git a/src/client/util/GroupManager.tsx b/src/client/util/GroupManager.tsx
index c79894032..8973306bf 100644
--- a/src/client/util/GroupManager.tsx
+++ b/src/client/util/GroupManager.tsx
@@ -282,7 +282,7 @@ export class GroupManager extends React.Component<{}> {
      */
     private get groupCreationModal() {
         const contents = (
-            <div className="group-create" style={{ background: SettingsManager.Instance.userBackgroundColor, color: SettingsManager.Instance.userColor }}>
+            <div className="group-create" style={{ background: SettingsManager.userBackgroundColor, color: SettingsManager.userColor }}>
                 <div className="group-heading" style={{ marginBottom: 0 }}>
                     <p>
                         <b>New Group</b>
@@ -367,7 +367,7 @@ export class GroupManager extends React.Component<{}> {
         const groups = this.groupSort === 'ascending' ? this.allGroups.sort(sortGroups) : this.groupSort === 'descending' ? this.allGroups.sort(sortGroups).reverse() : this.allGroups;
 
         return (
-            <div className="group-interface" style={{ background: SettingsManager.Instance.userBackgroundColor, color: SettingsManager.Instance.userColor }}>
+            <div className="group-interface" style={{ background: SettingsManager.userBackgroundColor, color: SettingsManager.userColor }}>
                 {this.groupCreationModal}
                 {this.currentGroup ? <GroupMemberView group={this.currentGroup} onCloseButtonClick={action(() => (this.currentGroup = undefined))} /> : null}
                 <div className="group-heading">
diff --git a/src/client/util/GroupMemberView.tsx b/src/client/util/GroupMemberView.tsx
index 535d8ccc2..7de0f336f 100644
--- a/src/client/util/GroupMemberView.tsx
+++ b/src/client/util/GroupMemberView.tsx
@@ -29,7 +29,7 @@ export class GroupMemberView extends React.Component<GroupMemberViewProps> {
         const hasEditAccess = GroupManager.Instance.hasEditAccess(this.props.group);
 
         return !this.props.group ? null : (
-            <div className="editing-interface" style={{ background: SettingsManager.Instance.userBackgroundColor, color: SettingsManager.Instance.userColor }}>
+            <div className="editing-interface" style={{ background: SettingsManager.userBackgroundColor, color: SettingsManager.userColor }}>
                 <div className="editing-header">
                     <input
                         className="group-title"
diff --git a/src/client/util/SearchUtil.ts b/src/client/util/SearchUtil.ts
index d154c48a4..64aa7ba9b 100644
--- a/src/client/util/SearchUtil.ts
+++ b/src/client/util/SearchUtil.ts
@@ -1,13 +1,115 @@
 import * as rp from 'request-promise';
 import { DocServer } from '../DocServer';
-import { Doc } from '../../fields/Doc';
+import { Doc, DocListCast, Field, Opt } from '../../fields/Doc';
 import { Id } from '../../fields/FieldSymbols';
 import { Utils } from '../../Utils';
 import { DocumentType } from '../documents/DocumentTypes';
+import { StrCast } from '../../fields/Types';
 
 export namespace SearchUtil {
     export type HighlightingResult = { [id: string]: { [key: string]: string[] } };
 
+    export function SearchCollection(rootDoc: Opt<Doc>, query: string) {
+        const blockedTypes = [DocumentType.PRESELEMENT, DocumentType.CONFIG, DocumentType.KVP, DocumentType.FONTICON, DocumentType.BUTTON, DocumentType.SCRIPTING];
+        const blockedKeys = [
+            'x',
+            'y',
+            'proto',
+            'width',
+            'layout_autoHeight',
+            'acl-Override',
+            'acl-Guest',
+            'embedContainer',
+            'zIndex',
+            'height',
+            'text_scrollHeight',
+            'text_height',
+            'cloneFieldFilter',
+            'isDataDoc',
+            'text_annotations',
+            'dragFactory_count',
+            'text_noTemplate',
+            'proto_embeddings',
+            'isSystem',
+            'layout_fieldKey',
+            'isBaseProto',
+            'xMargin',
+            'yMargin',
+            'links',
+            'layout',
+            'layout_keyValue',
+            'layout_fitWidth',
+            'type_collection',
+            'title_custom',
+            'freeform_panX',
+            'freeform_panY',
+            'freeform_scale',
+        ];
+        query = query.toLowerCase();
+
+        const results = new Map<Doc, string[]>();
+        if (rootDoc) {
+            const docs = DocListCast(rootDoc[Doc.LayoutFieldKey(rootDoc)]);
+            const docIDs: String[] = [];
+            SearchUtil.foreachRecursiveDoc(docs, (depth: number, doc: Doc) => {
+                const dtype = StrCast(doc.type) as DocumentType;
+                if (dtype && !blockedTypes.includes(dtype) && !docIDs.includes(doc[Id]) && depth >= 0) {
+                    const hlights = new Set<string>();
+                    SearchUtil.documentKeys(doc).forEach(
+                        key =>
+                            Field.toString(doc[key] as Field)
+                                .toLowerCase()
+                                .includes(query) && hlights.add(key)
+                    );
+                    blockedKeys.forEach(key => hlights.delete(key));
+
+                    if (Array.from(hlights.keys()).length > 0) {
+                        results.set(doc, Array.from(hlights.keys()));
+                    }
+                }
+                docIDs.push(doc[Id]);
+            });
+        }
+        return results;
+    }
+    /**
+     * @param {Doc} doc - doc for which keys are returned
+     *
+     * This method returns a list of a document doc's keys.
+     */
+    export function documentKeys(doc: Doc) {
+        const keys: { [key: string]: boolean } = {};
+        Doc.GetAllPrototypes(doc).map(proto => Object.keys(proto).forEach(key => (keys[key] = false)));
+        return Array.from(Object.keys(keys));
+    }
+
+    /**
+     * @param {Doc[]} docs - docs to be searched through recursively
+     * @param {number, Doc => void} func - function to be called on each doc
+     *
+     * This method iterates through an array of docs and all docs within those docs, calling
+     * the function func on each doc.
+     */
+    export function foreachRecursiveDoc(docs: Doc[], func: (depth: number, doc: Doc) => void) {
+        let newarray: Doc[] = [];
+        var depth = 0;
+        const visited: Doc[] = [];
+        while (docs.length > 0) {
+            newarray = [];
+            docs.filter(d => d && !visited.includes(d)).forEach(d => {
+                visited.push(d);
+                const fieldKey = Doc.LayoutFieldKey(d);
+                const annos = !Field.toString(Doc.LayoutField(d) as Field).includes('CollectionView');
+                const data = d[annos ? fieldKey + '_annotations' : fieldKey];
+                data && newarray.push(...DocListCast(data));
+                const sidebar = d[fieldKey + '_sidebar'];
+                sidebar && newarray.push(...DocListCast(sidebar));
+                func(depth, d);
+            });
+            docs = newarray;
+            depth++;
+        }
+    }
     export interface IdSearchResult {
         ids: string[];
         lines: string[][];
diff --git a/src/client/util/SettingsManager.tsx b/src/client/util/SettingsManager.tsx
index bb370e1a4..720badd40 100644
--- a/src/client/util/SettingsManager.tsx
+++ b/src/client/util/SettingsManager.tsx
@@ -13,7 +13,6 @@ import { GoogleAuthenticationManager } from '../apis/GoogleAuthenticationManager
 import { DocServer } from '../DocServer';
 import { Networking } from '../Network';
 import { MainViewModal } from '../views/MainViewModal';
-import { FontIconBox } from '../views/nodes/FontIconBox/FontIconBox';
 import { GroupManager } from './GroupManager';
 import './SettingsManager.scss';
 import { undoBatch } from './UndoManager';
@@ -67,15 +66,15 @@ export class SettingsManager extends React.Component<{}> {
         }
     };
 
-    @computed get userColor() {
+    @computed public static get userColor() {
         return StrCast(Doc.UserDoc().userColor);
     }
 
-    @computed get userVariantColor() {
+    @computed public static get userVariantColor() {
         return StrCast(Doc.UserDoc().userVariantColor);
     }
 
-    @computed get userBackgroundColor() {
+    @computed public static get userBackgroundColor() {
         return StrCast(Doc.UserDoc().userBackgroundColor);
     }
 
@@ -150,35 +149,35 @@ export class SettingsManager extends React.Component<{}> {
                         val: scheme,
                     }))}
                     dropdownType={DropdownType.SELECT}
-                    color={this.userColor}
+                    color={SettingsManager.userColor}
                     fillWidth
                 />
                 {userTheme === ColorScheme.Custom && (
                     <Group formLabel="Custom Theme">
                         <ColorPicker
                             tooltip={'User Color'} //
-                            color={this.userColor}
+                            color={SettingsManager.userColor}
                             type={Type.SEC}
                             icon={<FaFillDrip />}
-                            selectedColor={this.userColor}
+                            selectedColor={SettingsManager.userColor}
                             setSelectedColor={this.switchUserColor}
                             setFinalColor={this.switchUserColor}
                         />
                         <ColorPicker
                             tooltip={'User Background Color'}
-                            color={this.userColor}
+                            color={SettingsManager.userColor}
                             type={Type.SEC}
                             icon={<FaPalette />}
-                            selectedColor={this.userBackgroundColor}
+                            selectedColor={SettingsManager.userBackgroundColor}
                             setSelectedColor={this.switchUserBackgroundColor}
                             setFinalColor={this.switchUserBackgroundColor}
                         />
                         <ColorPicker
                             tooltip={'User Variant Color'}
-                            color={this.userColor}
+                            color={SettingsManager.userColor}
                             type={Type.SEC}
                             icon={<FaPalette />}
-                            selectedColor={this.userVariantColor}
+                            selectedColor={SettingsManager.userVariantColor}
                             setSelectedColor={this.switchUserVariantColor}
                             setFinalColor={this.switchUserVariantColor}
                         />
@@ -198,7 +197,7 @@ export class SettingsManager extends React.Component<{}> {
                     onClick={e => (Doc.UserDoc().layout_showTitle = Doc.UserDoc().layout_showTitle ? undefined : 'author_date')}
                     toggleStatus={Doc.UserDoc().layout_showTitle !== undefined}
                     size={Size.XSMALL}
-                    color={this.userColor}
+                    color={SettingsManager.userColor}
                 />
                 <Toggle
                     formLabel={'Show Full Toolbar'}
@@ -207,25 +206,25 @@ export class SettingsManager extends React.Component<{}> {
                     onClick={e => (Doc.UserDoc()['documentLinksButton-fullMenu'] = !Doc.UserDoc()['documentLinksButton-fullMenu'])}
                     toggleStatus={BoolCast(Doc.UserDoc()['documentLinksButton-fullMenu'])}
                     size={Size.XSMALL}
-                    color={this.userColor}
+                    color={SettingsManager.userColor}
                 />
                 <Toggle
                     formLabel={'Show Button Labels'}
                     formLabelPlacement={'right'}
                     toggleType={ToggleType.SWITCH}
-                    onClick={e => FontIconBox.SetShowLabels(!FontIconBox.GetShowLabels())}
-                    toggleStatus={FontIconBox.GetShowLabels()}
+                    onClick={e => Doc.SetShowIconLabels(!Doc.GetShowIconLabels())}
+                    toggleStatus={Doc.GetShowIconLabels()}
                     size={Size.XSMALL}
-                    color={this.userColor}
+                    color={SettingsManager.userColor}
                 />
                 <Toggle
                     formLabel={'Recognize Ink Gestures'}
                     formLabelPlacement={'right'}
                     toggleType={ToggleType.SWITCH}
-                    onClick={e => FontIconBox.SetRecognizeGestures(!FontIconBox.GetRecognizeGestures())}
-                    toggleStatus={FontIconBox.GetRecognizeGestures()}
+                    onClick={e => Doc.SetRecognizeGestures(!Doc.GetRecognizeGestures())}
+                    toggleStatus={Doc.GetRecognizeGestures()}
                     size={Size.XSMALL}
-                    color={this.userColor}
+                    color={SettingsManager.userColor}
                 />
                 <Toggle
                     formLabel={'Hide Labels In Ink Shapes'}
@@ -234,7 +233,7 @@ export class SettingsManager extends React.Component<{}> {
                     onClick={e => (Doc.UserDoc().activeInkHideTextLabels = !Doc.UserDoc().activeInkHideTextLabels)}
                     toggleStatus={BoolCast(Doc.UserDoc().activeInkHideTextLabels)}
                     size={Size.XSMALL}
-                    color={this.userColor}
+                    color={SettingsManager.userColor}
                 />
                 <Toggle
                     formLabel={'Open Ink Docs in Lightbox'}
@@ -243,7 +242,7 @@ export class SettingsManager extends React.Component<{}> {
                     onClick={e => (Doc.UserDoc().openInkInLightbox = !Doc.UserDoc().openInkInLightbox)}
                     toggleStatus={BoolCast(Doc.UserDoc().openInkInLightbox)}
                     size={Size.XSMALL}
-                    color={this.userColor}
+                    color={SettingsManager.userColor}
                 />
                 <Toggle
                     formLabel={'Show Link Lines'}
@@ -252,7 +251,7 @@ export class SettingsManager extends React.Component<{}> {
                     onClick={e => (Doc.UserDoc().showLinkLines = !Doc.UserDoc().showLinkLines)}
                     toggleStatus={BoolCast(Doc.UserDoc().showLinkLines)}
                     size={Size.XSMALL}
-                    color={this.userColor}
+                    color={SettingsManager.userColor}
                 />
             </div>
         );
@@ -284,7 +283,7 @@ export class SettingsManager extends React.Component<{}> {
                     <div className="tab-column-content">
                         {/* <NumberInput/> */}
                         <Group formLabel={'Default Font'}>
-                            <NumberDropdown color={this.userColor} numberDropdownType={'input'} min={0} max={50} step={2} type={Type.TERT} number={0} unit={'px'} setNumber={() => {}} />
+                            <NumberDropdown color={SettingsManager.userColor} numberDropdownType={'input'} min={0} max={50} step={2} type={Type.TERT} number={0} unit={'px'} setNumber={() => {}} />
                             <Dropdown
                                 items={fontFamilies.map(val => {
                                     return {
@@ -301,7 +300,7 @@ export class SettingsManager extends React.Component<{}> {
                                 setSelectedVal={val => {
                                     this.changeFontFamily(val as string);
                                 }}
-                                color={this.userColor}
+                                color={SettingsManager.userColor}
                                 fillWidth
                             />
                         </Group>
@@ -329,12 +328,12 @@ export class SettingsManager extends React.Component<{}> {
     @computed get passwordContent() {
         return (
             <div className="password-content">
-                <EditableText placeholder="Current password" type={Type.SEC} color={this.userColor} val={''} setVal={val => this.changeVal(val as string, 'curr')} fillWidth password />
-                <EditableText placeholder="New password" type={Type.SEC} color={this.userColor} val={''} setVal={val => this.changeVal(val as string, 'new')} fillWidth password />
-                <EditableText placeholder="Confirm new password" type={Type.SEC} color={this.userColor} val={''} setVal={val => this.changeVal(val as string, 'conf')} fillWidth password />
+                <EditableText placeholder="Current password" type={Type.SEC} color={SettingsManager.userColor} val={''} setVal={val => this.changeVal(val as string, 'curr')} fillWidth password />
+                <EditableText placeholder="New password" type={Type.SEC} color={SettingsManager.userColor} val={''} setVal={val => this.changeVal(val as string, 'new')} fillWidth password />
+                <EditableText placeholder="Confirm new password" type={Type.SEC} color={SettingsManager.userColor} val={''} setVal={val => this.changeVal(val as string, 'conf')} fillWidth password />
                 {!this.passwordResultText ? null : <div className={`${this.passwordResultText.startsWith('Error') ? 'error' : 'success'}-text`}>{this.passwordResultText}</div>}
-                <Button type={Type.SEC} text={'Forgot Password'} color={this.userColor} />
-                <Button type={Type.TERT} text={'Submit'} onClick={this.changePassword} color={this.userColor} />
+                <Button type={Type.SEC} text={'Forgot Password'} color={SettingsManager.userColor} />
+                <Button type={Type.TERT} text={'Submit'} onClick={this.changePassword} color={SettingsManager.userColor} />
             </div>
         );
     }
@@ -394,10 +393,10 @@ export class SettingsManager extends React.Component<{}> {
                             dropdownType={DropdownType.SELECT}
                             type={Type.TERT}
                             placement="bottom-start"
-                            color={this.userColor}
+                            color={SettingsManager.userColor}
                             fillWidth
                         />
-                        <Toggle formLabel={'Playground Mode'} toggleType={ToggleType.SWITCH} toggleStatus={this.playgroundMode} onClick={this.playgroundModeToggle} color={this.userColor} />
+                        <Toggle formLabel={'Playground Mode'} toggleType={ToggleType.SWITCH} toggleStatus={this.playgroundMode} onClick={this.playgroundModeToggle} color={SettingsManager.userColor} />
                     </div>
                     <div className="tab-column-title" style={{ marginTop: 20, marginBottom: 10 }}>
                         Freeform Navigation
@@ -422,15 +421,21 @@ export class SettingsManager extends React.Component<{}> {
                             dropdownType={DropdownType.SELECT}
                             type={Type.TERT}
                             placement="bottom-start"
-                            color={this.userColor}
+                            color={SettingsManager.userColor}
                         />
                     </div>
                 </div>
                 <div className="tab-column">
                     <div className="tab-column-title">Permissions</div>
                     <div className="tab-column-content">
-                        <Button text={'Manage Groups'} type={Type.TERT} onClick={() => GroupManager.Instance?.open()} color={this.userColor} />
-                        <Toggle toggleType={ToggleType.SWITCH} formLabel={'Default access private'} color={this.userColor} toggleStatus={BoolCast(Doc.defaultAclPrivate)} onClick={action(() => (Doc.defaultAclPrivate = !Doc.defaultAclPrivate))} />
+                        <Button text={'Manage Groups'} type={Type.TERT} onClick={() => GroupManager.Instance?.open()} color={SettingsManager.userColor} />
+                        <Toggle
+                            toggleType={ToggleType.SWITCH}
+                            formLabel={'Default access private'}
+                            color={SettingsManager.userColor}
+                            toggleStatus={BoolCast(Doc.defaultAclPrivate)}
+                            onClick={action(() => (Doc.defaultAclPrivate = !Doc.defaultAclPrivate))}
+                        />
                     </div>
                 </div>
             </div>
@@ -449,7 +454,7 @@ export class SettingsManager extends React.Component<{}> {
         ];
         return (
             <div className="settings-interface">
-                <div className="settings-panel" style={{ background: this.userColor }}>
+                <div className="settings-panel" style={{ background: SettingsManager.userColor }}>
                     <div className="settings-tabs">
                         {tabs.map(tab => {
                             const isActive = this.activeTab === tab.title;
@@ -457,8 +462,8 @@ export class SettingsManager extends React.Component<{}> {
                                 <div
                                     key={tab.title}
                                     style={{
-                                        background: isActive ? this.userBackgroundColor : this.userColor,
-                                        color: isActive ? this.userColor : this.userBackgroundColor,
+                                        background: isActive ? SettingsManager.userBackgroundColor : SettingsManager.userColor,
+                                        color: isActive ? SettingsManager.userColor : SettingsManager.userBackgroundColor,
                                     }}
                                     className={'tab-control ' + (isActive ? 'active' : 'inactive')}
                                     onClick={action(() => (this.activeTab = tab.title))}>
@@ -469,19 +474,19 @@ export class SettingsManager extends React.Component<{}> {
                     </div>
 
                     <div className="settings-user">
-                        <div style={{ color: this.userBackgroundColor }}>{DashVersion}</div>
-                        <div className="settings-username" style={{ color: this.userBackgroundColor }}>
+                        <div style={{ color: SettingsManager.userBackgroundColor }}>{DashVersion}</div>
+                        <div className="settings-username" style={{ color: SettingsManager.userBackgroundColor }}>
                             {Doc.CurrentUserEmail}
                         </div>
-                        <Button text={Doc.GuestDashboard ? 'Exit' : 'Log Out'} type={Type.TERT} color={this.userVariantColor} onClick={() => window.location.assign(Utils.prepend('/logout'))} />
+                        <Button text={Doc.GuestDashboard ? 'Exit' : 'Log Out'} type={Type.TERT} color={SettingsManager.userVariantColor} onClick={() => window.location.assign(Utils.prepend('/logout'))} />
                     </div>
                 </div>
 
                 <div className="close-button">
-                    <Button icon={<FontAwesomeIcon icon={'times'} size={'lg'} />} onClick={this.close} color={this.userColor} />
+                    <Button icon={<FontAwesomeIcon icon={'times'} size={'lg'} />} onClick={this.close} color={SettingsManager.userColor} />
                 </div>
 
-                <div className="settings-content" style={{ color: this.userColor, background: this.userBackgroundColor }}>
+                <div className="settings-content" style={{ color: SettingsManager.userColor, background: SettingsManager.userBackgroundColor }}>
                     {tabs.map(tab => (
                         <div key={tab.title} className={'tab-section ' + (this.activeTab === tab.title ? 'active' : 'inactive')}>
                             {tab.ele}
diff --git a/src/client/util/SharingManager.tsx b/src/client/util/SharingManager.tsx
index 81ddeb9e3..9a9097bf7 100644
--- a/src/client/util/SharingManager.tsx
+++ b/src/client/util/SharingManager.tsx
@@ -18,10 +18,10 @@ import { DictationOverlay } from '../views/DictationOverlay';
 import { MainViewModal } from '../views/MainViewModal';
 import { DocumentView } from '../views/nodes/DocumentView';
 import { TaskCompletionBox } from '../views/nodes/TaskCompletedBox';
-import { SearchBox } from '../views/search/SearchBox';
 import { DocumentManager } from './DocumentManager';
 import { GroupManager, UserOptions } from './GroupManager';
 import { GroupMemberView } from './GroupMemberView';
+import { SearchUtil } from './SearchUtil';
 import { SelectionManager } from './SelectionManager';
 import { SettingsManager } from './SettingsManager';
 import './SharingManager.scss';
@@ -446,7 +446,7 @@ export class SharingManager extends React.Component<{}> {
 
         if (this.myDocAcls) {
             const newDocs: Doc[] = [];
-            SearchBox.foreachRecursiveDoc(docs, (depth, doc) => newDocs.push(doc));
+            SearchUtil.foreachRecursiveDoc(docs, (depth, doc) => newDocs.push(doc));
             docs = newDocs.filter(doc => GetEffectiveAcl(doc) === AclAdmin);
         }
 
@@ -527,10 +527,10 @@ export class SharingManager extends React.Component<{}> {
             const permissions = uniform ? StrCast(targetDoc?.[groupKey]) : '-multiple-';
 
             return !permissions ? null : (
-                <div key={groupKey} className={'container'} style={{ background: SettingsManager.Instance.userBackgroundColor, color: SettingsManager.Instance.userColor }}>
+                <div key={groupKey} className={'container'} style={{ background: SettingsManager.userBackgroundColor, color: SettingsManager.userColor }}>
                     <div className={'padding'}>{StrCast(group.title)}</div>
                     &nbsp;
-                    {group instanceof Doc ? <IconButton icon={<FontAwesomeIcon icon={'info-circle'} />} size={Size.XSMALL} color={SettingsManager.Instance.userColor} onClick={action(() => (GroupManager.Instance.currentGroup = group))} /> : null}
+                    {group instanceof Doc ? <IconButton icon={<FontAwesomeIcon icon={'info-circle'} />} size={Size.XSMALL} color={SettingsManager.userColor} onClick={action(() => (GroupManager.Instance.currentGroup = group))} /> : null}
                     <div className={'edit-actions'}>
                         {admin || this.myDocAcls ? (
                             <select className={`permissions-dropdown-${permissions}`} value={permissions} onChange={e => this.setInternalGroupSharing(group, e.currentTarget.value)}>
@@ -552,7 +552,7 @@ export class SharingManager extends React.Component<{}> {
                 <div
                     className="sharing-contents"
                     style={{
-                        background: SettingsManager.Instance.userBackgroundColor,
+                        background: SettingsManager.userBackgroundColor,
                         color: StrCast(Doc.UserDoc().userColor),
                     }}>
                     <p className="share-title" style={{ color: StrCast(Doc.UserDoc().userColor) }}>
diff --git a/src/client/util/reportManager/ReportManager.tsx b/src/client/util/reportManager/ReportManager.tsx
index 3cd2d47a0..6a236face 100644
--- a/src/client/util/reportManager/ReportManager.tsx
+++ b/src/client/util/reportManager/ReportManager.tsx
@@ -211,11 +211,11 @@ export class ReportManager extends React.Component<{}> {
      * @returns the component that dispays all issues
      */
     private viewIssuesComponent = () => {
-        const darkMode = isDarkMode(SettingsManager.Instance.userBackgroundColor);
+        const darkMode = isDarkMode(SettingsManager.userBackgroundColor);
         const colors = darkMode ? darkColors : lightColors;
 
         return (
-            <div className="view-issues" style={{ backgroundColor: SettingsManager.Instance.userBackgroundColor, color: colors.text }}>
+            <div className="view-issues" style={{ backgroundColor: SettingsManager.userBackgroundColor, color: colors.text }}>
                 <div className="left" style={{ display: this.rightExpanded ? 'none' : 'flex' }}>
                     <div className="report-header">
                         <h2 style={{ color: colors.text }}>Open Issues</h2>
diff --git a/src/client/views/ContextMenuItem.tsx b/src/client/views/ContextMenuItem.tsx
index b53379435..c2cbca3e1 100644
--- a/src/client/views/ContextMenuItem.tsx
+++ b/src/client/views/ContextMenuItem.tsx
@@ -96,7 +96,7 @@ export class ContextMenuItem extends React.Component<ContextMenuProps & { select
                     <div
                         className={`contextMenu-item-background`}
                         style={{
-                            background: SettingsManager.Instance.userColor,
+                            background: SettingsManager.userColor,
                         }}
                     />
                 </div>
@@ -112,7 +112,7 @@ export class ContextMenuItem extends React.Component<ContextMenuProps & { select
                     style={{
                         marginLeft: window.innerHeight - this._overPosX - 50 > 0 ? '90%' : '20%',
                         marginTop,
-                        background: SettingsManager.Instance.userBackgroundColor,
+                        background: SettingsManager.userBackgroundColor,
                     }}>
                     {this._items.map(prop => (
                         <ContextMenuItem {...prop} key={prop.description} closeMenu={this.props.closeMenu} />
@@ -146,7 +146,7 @@ export class ContextMenuItem extends React.Component<ContextMenuProps & { select
                     <div
                         className={`contextMenu-item-background`}
                         style={{
-                            background: SettingsManager.Instance.userColor,
+                            background: SettingsManager.userColor,
                         }}
                     />
                     {submenu}
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 90425f264..3018dad79 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -57,7 +57,6 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P
     @observable private _editingTitle = false;
     @observable private _hidden = false;
     @observable public AddToSelection = false; // if Shift is pressed, then this should be set so that clicking on the selection background is ignored so overlapped documents can be added to the selection set.
-    @observable public Interacting = false;
     @observable public pushIcon: IconProp = 'arrow-alt-circle-up';
     @observable public pullIcon: IconProp = 'arrow-alt-circle-down';
     @observable public pullColor: string = 'white';
@@ -330,7 +329,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P
      */
     @action
     onRadiusDown = (e: React.PointerEvent): void => {
-        this._isRounding = DocumentDecorations.Instance.Interacting = true;
+        this._isRounding = DocumentView.Interacting = true;
         this._resizeUndo = UndoManager.StartBatch('DocDecs set radius');
         // Call util move event function
         setupMoveUpEvents(
@@ -353,7 +352,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P
                 return false;
             }, // moveEvent
             action(e => {
-                DocumentDecorations.Instance.Interacting = this._isRounding = false;
+                DocumentView.Interacting = this._isRounding = false;
                 this._resizeUndo?.end();
             }), // upEvent
             e => {}, // clickEvent,
@@ -478,7 +477,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P
     @action
     onPointerDown = (e: React.PointerEvent): void => {
         setupMoveUpEvents(this, e, this.onPointerMove, this.onPointerUp, emptyFunction);
-        this.Interacting = true; // turns off pointer events on things like youtube videos and web pages so that dragging doesn't get "stuck" when cursor moves over them
+        DocumentView.Interacting = true; // turns off pointer events on things like youtube videos and web pages so that dragging doesn't get "stuck" when cursor moves over them
         this._resizeHdlId = e.currentTarget.className;
         const bounds = e.currentTarget.getBoundingClientRect();
         this._offX = this._resizeHdlId.toLowerCase().includes('left') ? bounds.right - e.clientX : bounds.left - e.clientX;
@@ -688,7 +687,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P
     @action
     onPointerUp = (e: PointerEvent): void => {
         this._resizeHdlId = '';
-        this.Interacting = false;
+        DocumentView.Interacting = false;
         this._resizeUndo?.end();
         SnappingManager.clearSnapLines();
 
@@ -895,7 +894,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P
                         height: bounds.b - bounds.y + this._resizeBorderWidth + 'px',
                         left: bounds.x - this._resizeBorderWidth / 2,
                         top: bounds.y - this._resizeBorderWidth / 2,
-                        pointerEvents: DocumentDecorations.Instance.AddToSelection || this.Interacting ? 'none' : 'all',
+                        pointerEvents: DocumentDecorations.Instance.AddToSelection || DocumentView.Interacting ? 'none' : 'all',
                         display: SelectionManager.Views().length <= 1 || hideDecorations ? 'none' : undefined,
                     }}
                     onPointerDown={this.onBackgroundDown}
diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx
index d60617020..147921596 100644
--- a/src/client/views/EditableView.tsx
+++ b/src/client/views/EditableView.tsx
@@ -6,7 +6,6 @@ import { ObjectField } from '../../fields/ObjectField';
 import './EditableView.scss';
 import { DocumentIconContainer } from './nodes/DocumentIcon';
 import { OverlayView } from './OverlayView';
-import { EditableText } from 'browndash-components';
 
 export interface EditableProps {
     /**
diff --git a/src/client/views/FilterPanel.tsx b/src/client/views/FilterPanel.tsx
index 11c2fc86c..b61ff35c7 100644
--- a/src/client/views/FilterPanel.tsx
+++ b/src/client/views/FilterPanel.tsx
@@ -1,23 +1,20 @@
 import React = require('react');
 import { action, computed, observable, ObservableMap } from 'mobx';
 import { observer } from 'mobx-react';
+import { Handles, Rail, Slider, Ticks, Tracks } from 'react-compound-slider';
+import { AiOutlineMinusSquare, AiOutlinePlusSquare } from 'react-icons/ai';
+import { CiCircleRemove } from 'react-icons/ci';
 import Select from 'react-select';
-import { Checkbox, Tooltip } from '@material-ui/core';
 import { Doc, DocListCast, Field, StrListCast } from '../../fields/Doc';
 import { RichTextField } from '../../fields/RichTextField';
-import { StrCast } from '../../fields/Types';
+import { DocumentOptions, FInfo } from '../documents/Documents';
 import { DocumentManager } from '../util/DocumentManager';
 import { UserOptions } from '../util/GroupManager';
+import { SearchUtil } from '../util/SearchUtil';
+import { undoable } from '../util/UndoManager';
 import './FilterPanel.scss';
 import { FieldView } from './nodes/FieldView';
-import { SearchBox } from './search/SearchBox';
-import { undoable } from '../util/UndoManager';
-import { AiOutlineMinusSquare, AiOutlinePlusSquare } from 'react-icons/ai';
-import { CiCircleRemove } from 'react-icons/ci';
-import { Slider, Rail, Handles, Tracks, Ticks } from 'react-compound-slider';
-import { TooltipRail, Handle, Tick, Track } from './nodes/SliderBox-components';
-import { DocumentOptions, FInfo } from '../documents/Documents';
-import { string32 } from 'pdfjs-dist/types/src/shared/util';
+import { Handle, Tick, TooltipRail, Track } from './nodes/SliderBox-components';
 
 interface filterProps {
     rootDoc: Doc;
@@ -49,7 +46,7 @@ export class FilterPanel extends React.Component<filterProps> {
         const allDocs = new Set<Doc>();
         const targetDoc = this.targetDoc;
         if (targetDoc) {
-            SearchBox.foreachRecursiveDoc([this.targetDoc], (depth, doc) => allDocs.add(doc));
+            SearchUtil.foreachRecursiveDoc([this.targetDoc], (depth, doc) => allDocs.add(doc));
         }
         console.log('this is all Docs' + Array.from(allDocs));
         return Array.from(allDocs);
@@ -62,7 +59,7 @@ export class FilterPanel extends React.Component<filterProps> {
         const noviceFields = [...noviceReqFields, ...noviceLayoutFields];
 
         const keys = new Set<string>(noviceFields);
-        this.allDocs.forEach(doc => SearchBox.documentKeys(doc).filter(key => keys.add(key)));
+        this.allDocs.forEach(doc => SearchUtil.documentKeys(doc).filter(key => keys.add(key)));
         const sortedKeys = Array.from(keys.keys())
             .filter(key => key[0])
             .filter(key => key.indexOf('modificationDate') !== -1 || (key[0] === key[0].toUpperCase() && !key.startsWith('_')) || noviceFields.includes(key) || !Doc.noviceMode)
@@ -236,7 +233,7 @@ export class FilterPanel extends React.Component<filterProps> {
 
     facetValues = (facetHeader: string) => {
         const allCollectionDocs = new Set<Doc>();
-        SearchBox.foreachRecursiveDoc(this.targetDocChildren, (depth: number, doc: Doc) => allCollectionDocs.add(doc));
+        SearchUtil.foreachRecursiveDoc(this.targetDocChildren, (depth: number, doc: Doc) => allCollectionDocs.add(doc));
         const set = new Set<string>([String.fromCharCode(127) + '--undefined--']);
         if (facetHeader === 'tags')
             allCollectionDocs.forEach(child =>
diff --git a/src/client/views/LightboxView.tsx b/src/client/views/LightboxView.tsx
index afb76b9ac..8f081b321 100644
--- a/src/client/views/LightboxView.tsx
+++ b/src/client/views/LightboxView.tsx
@@ -16,7 +16,6 @@ import { CollectionStackedTimeline } from './collections/CollectionStackedTimeli
 import { TabDocView } from './collections/TabDocView';
 import { GestureOverlay } from './GestureOverlay';
 import './LightboxView.scss';
-import { MainView } from './MainView';
 import { DocumentView, OpenWhere, OpenWhereMod } from './nodes/DocumentView';
 import { DefaultStyleProvider, wavyBorderPath } from './StyleProvider';
 
@@ -61,7 +60,7 @@ export class LightboxView extends React.Component<LightboxViewProps> {
             this._childFilters && (this._childFilters.length = 0);
             this._future = this._history = [];
             Doc.ActiveTool = InkTool.None;
-            MainView.Instance._exploreMode = false;
+            DocumentView.ExploreMode = false;
         } else {
             const l = DocUtils.MakeLinkToActiveAudio(() => doc).lastElement();
             l && (Cast(l.link_anchor_2, Doc, null).backgroundColor = 'lightgreen');
@@ -270,7 +269,7 @@ export class LightboxView extends React.Component<LightboxViewProps> {
                             addDocTab={this.addDocTab}
                             pinToPres={TabDocView.PinDoc}
                             bringToFront={emptyFunction}
-                            onBrowseClick={MainView.Instance.exploreMode}
+                            onBrowseClick={DocumentView.exploreMode}
                             focus={emptyFunction}
                         />
                     </GestureOverlay>
@@ -335,12 +334,12 @@ export class LightboxView extends React.Component<LightboxViewProps> {
                 <div
                     className="lightboxView-exploreBtn"
                     title="toggle explore mode to navigate among documents only"
-                    style={{ background: MainView.Instance._exploreMode ? 'white' : undefined }}
+                    style={{ background: DocumentView.ExploreMode ? 'white' : undefined }}
                     onClick={action(e => {
                         e.stopPropagation();
-                        MainView.Instance._exploreMode = !MainView.Instance._exploreMode;
+                        DocumentView.ExploreMode = !DocumentView.ExploreMode;
                     })}>
-                    <FontAwesomeIcon color={MainView.Instance._exploreMode ? 'black' : 'white'} icon={'globe-americas'} size="2x" />
+                    <FontAwesomeIcon color={DocumentView.ExploreMode ? 'black' : 'white'} icon={'globe-americas'} size="2x" />
                 </div>
             </div>
         );
diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index 6dd1d53ee..a04309d0c 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -2,18 +2,18 @@
 //     (module as any).hot.accept();
 // }
 
+import * as dotenv from 'dotenv'; // see https://github.com/motdotla/dotenv#how-do-i-use-dotenv-with-import
 import * as React from 'react';
 import * as ReactDOM from 'react-dom/client';
 import { AssignAllExtensions } from '../../extensions/General/Extensions';
 import { FieldLoader } from '../../fields/FieldLoader';
 import { CurrentUserUtils } from '../util/CurrentUserUtils';
+import { PingManager } from '../util/PingManager';
 import { ReplayMovements } from '../util/ReplayMovements';
 import { TrackMovements } from '../util/TrackMovements';
 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';
+import { MainView } from './MainView';
 dotenv.config();
 
 AssignAllExtensions();
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 6a743a5e6..dde04dcc0 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -9,7 +9,6 @@ import { observer } from 'mobx-react';
 import 'normalize.css';
 import * as React from 'react';
 import { Doc, DocListCast, Opt } from '../../fields/Doc';
-import { ScriptField } from '../../fields/ScriptField';
 import { DocCast, StrCast } from '../../fields/Types';
 import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue, returnZero, setupMoveUpEvents, Utils } from '../../Utils';
 import { GoogleAuthenticationManager } from '../apis/GoogleAuthenticationManager';
@@ -77,7 +76,6 @@ export class MainView extends React.Component {
     public static Live: boolean = false;
     private _docBtnRef = React.createRef<HTMLDivElement>();
 
-    @observable public LastButton: Opt<Doc>;
     @observable private _windowWidth: number = 0;
     @observable private _windowHeight: number = 0;
     @observable private _dashUIWidth: number = 0; // width of entire main dashboard region including left menu buttons and properties panel (but not including the dashboard selector button row)
@@ -529,7 +527,6 @@ export class MainView extends React.Component {
         window.addEventListener('beforeunload', DocServer.UPDATE_SERVER_CACHE);
         window.addEventListener('drop', e => e.preventDefault(), false); // prevent default behavior of navigating to a new web page
         window.addEventListener('dragover', e => e.preventDefault(), false);
-        // document.addEventListener("pointermove", action(e => SearchBox.Instance._undoBackground = UndoManager.batchCounter ? "#000000a8" : undefined));
         document.addEventListener('pointerdown', this.globalPointerDown, true);
         document.addEventListener('pointermove', this.globalPointerMove, true);
         document.addEventListener('pointerup', this.globalPointerClick, true);
@@ -572,11 +569,7 @@ export class MainView extends React.Component {
         Doc.AddDocToList(Doc.MyFilesystem, 'data', folder);
     };
 
-    @observable _exploreMode = false;
-    @computed get exploreMode() {
-        return () => (this._exploreMode ? ScriptField.MakeScript('CollectionBrowseClick(documentView, clientX, clientY)', { documentView: 'any', clientX: 'number', clientY: 'number' })! : undefined);
-    }
-    waitForDoubleClick = () => (this._exploreMode ? 'never' : undefined);
+    waitForDoubleClick = () => (DocumentView.ExploreMode ? 'never' : undefined);
     headerBarScreenXf = () => new Transform(-this.leftScreenOffsetOfMainDocView - this.leftMenuFlyoutWidth(), -this.headerBarDocHeight(), 1);
     mainScreenToLocalXf = () => new Transform(-this.leftScreenOffsetOfMainDocView - this.leftMenuFlyoutWidth(), -this.topOfMainDocContent, 1);
     addHeaderDoc = (doc: Doc | Doc[], annotationKey?: string) => (doc instanceof Doc ? [doc] : doc).reduce((done, doc) => Doc.AddDocToList(this.headerBarDoc, 'data', doc), true);
@@ -747,7 +740,7 @@ export class MainView extends React.Component {
 
     @computed get leftMenuPanel() {
         return (
-            <div key="menu" className="mainView-leftMenuPanel" style={{ background: StrCast(Doc.UserDoc().userBackgroundColor), display: LightboxView.LightboxDoc ? 'none' : undefined }}>
+            <div key="menu" className="mainView-leftMenuPanel" style={{ background: SettingsManager.userBackgroundColor, display: LightboxView.LightboxDoc ? 'none' : undefined }}>
                 <DocumentView
                     Document={Doc.MyLeftSidebarMenu}
                     DataDoc={undefined}
@@ -804,16 +797,16 @@ export class MainView extends React.Component {
                     {this.flyout}
                     <div
                         className="mainView-libraryHandle"
-                        style={{ background: StrCast(Doc.UserDoc().userBackgroundColor), left: leftMenuFlyoutWidth - 10 /* ~half width of handle */, display: !this._leftMenuFlyoutWidth ? 'none' : undefined }}
+                        style={{ background: SettingsManager.userBackgroundColor, left: leftMenuFlyoutWidth - 10 /* ~half width of handle */, display: !this._leftMenuFlyoutWidth ? 'none' : undefined }}
                         onPointerDown={this.onFlyoutPointerDown}>
-                        <FontAwesomeIcon icon="chevron-left" color={StrCast(Doc.UserDoc().userColor)} style={{ opacity: '50%' }} size="sm" />
+                        <FontAwesomeIcon icon="chevron-left" color={SettingsManager.userColor} style={{ opacity: '50%' }} size="sm" />
                     </div>
                     <div className="mainView-innerContainer" style={{ width: `calc(100% - ${width}px)` }}>
                         {this.dockingContent}
 
                         {this._hideUI ? null : (
-                            <div className="mainView-propertiesDragger" key="props" onPointerDown={this.onPropertiesPointerDown} style={{ background: StrCast(Doc.UserDoc().userBackgroundColor), right: this.propertiesWidth() - 1 }}>
-                                <FontAwesomeIcon icon={this.propertiesWidth() < 10 ? 'chevron-left' : 'chevron-right'} color={StrCast(Doc.UserDoc().userColor)} size="sm" />
+                            <div className="mainView-propertiesDragger" key="props" onPointerDown={this.onPropertiesPointerDown} style={{ background: SettingsManager.userBackgroundColor, right: this.propertiesWidth() - 1 }}>
+                                <FontAwesomeIcon icon={this.propertiesWidth() < 10 ? 'chevron-left' : 'chevron-right'} color={SettingsManager.userColor} size="sm" />
                             </div>
                         )}
                         <div className="properties-container" style={{ width: this.propertiesWidth() }}>
@@ -857,11 +850,11 @@ export class MainView extends React.Component {
         //setTimeout(action(() => (this._leftMenuFlyoutWidth += 0.5)));
 
         this._sidebarContent.proto = DocCast(button.target);
-        this.LastButton = button;
+        DocumentView.LastPressedSidebarBtn = button;
     });
 
     closeFlyout = action(() => {
-        this.LastButton = undefined;
+        DocumentView.LastPressedSidebarBtn = undefined;
         this._panelContent = 'none';
         this._sidebarContent.proto = undefined;
         this._leftMenuFlyoutWidth = 0;
@@ -879,7 +872,7 @@ export class MainView extends React.Component {
 
     @computed get docButtons() {
         return !Doc.MyDockedBtns ? null : (
-            <div className="mainView-docButtons" style={{ background: StrCast(Doc.UserDoc().userBackgroundColor), color: StrCast(Doc.UserDoc().userColor) }} ref={this._docBtnRef}>
+            <div className="mainView-docButtons" style={{ background: SettingsManager.userBackgroundColor, color: SettingsManager.userColor }} ref={this._docBtnRef}>
                 <CollectionLinearView
                     Document={Doc.MyDockedBtns}
                     DataDoc={undefined}
@@ -998,8 +991,8 @@ export class MainView extends React.Component {
             <div
                 className={`mainView-container ${this.colorScheme}`}
                 style={{
-                    color: StrCast(Doc.UserDoc().userColor),
-                    background: StrCast(Doc.UserDoc().userBackgroundColor),
+                    color: SettingsManager.userColor,
+                    background: SettingsManager.userBackgroundColor,
                 }}
                 onScroll={() => (ele => (ele.scrollTop = ele.scrollLeft = 0))(document.getElementById('root')!)}
                 ref={r => {
@@ -1068,3 +1061,12 @@ export class MainView extends React.Component {
 ScriptingGlobals.add(function selectMainMenu(doc: Doc, title: string) {
     MainView.Instance.selectMenu(doc);
 });
+ScriptingGlobals.add(function createNewPresentation() {
+    return MainView.Instance.createNewPresentation();
+}, 'creates a new presentation when called');
+ScriptingGlobals.add(function openPresentation(pres: Doc) {
+    return MainView.Instance.openPresentation(pres);
+}, 'creates a new presentation when called');
+ScriptingGlobals.add(function createNewFolder() {
+    return MainView.Instance.createNewFolder();
+}, 'creates a new folder in myFiles when called');
diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx
index 4fe6847c3..83bd1b860 100644
--- a/src/client/views/PropertiesView.tsx
+++ b/src/client/views/PropertiesView.tsx
@@ -188,7 +188,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
             });
 
             rows.push(
-                <div className="propertiesView-field" key="newKeyValue" style={{ marginTop: '3px', backgroundColor: SettingsManager.Instance.userBackgroundColor, textAlign: 'center' }}>
+                <div className="propertiesView-field" key="newKeyValue" style={{ marginTop: '3px', backgroundColor: SettingsManager.userBackgroundColor, textAlign: 'center' }}>
                     <EditableView key="editableView" oneLine contents={'add key:value or #tags'} height={13} fontSize={10} GetValue={() => ''} SetValue={this.setKeyValue} />
                 </div>
             );
@@ -1664,7 +1664,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                             <div className="propertiesView-title" style={{ width: this.props.width }}>
                                 Properties
                                 <div className="propertiesView-info" onClick={() => window.open('https://brown-dash.github.io/Dash-Documentation/properties')}>
-                                    <IconButton icon={<FontAwesomeIcon icon="info-circle" />} color={SettingsManager.Instance.userColor} />
+                                    <IconButton icon={<FontAwesomeIcon icon="info-circle" />} color={SettingsManager.userColor} />
                                 </div>
                             </div>
                         </div>
@@ -1706,8 +1706,8 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                                     className="propertiesView-presentationTrails-title"
                                     onPointerDown={action(() => (this.openPresTransitions = !this.openPresTransitions))}
                                     style={{
-                                        color: SettingsManager.Instance.userColor,
-                                        backgroundColor: this.openPresTransitions ? SettingsManager.Instance.userVariantColor : SettingsManager.Instance.userBackgroundColor,
+                                        color: SettingsManager.userColor,
+                                        backgroundColor: this.openPresTransitions ? SettingsManager.userVariantColor : SettingsManager.userBackgroundColor,
                                     }}>
                                     &nbsp; <FontAwesomeIcon style={{ alignSelf: 'center' }} icon={'rocket'} /> &nbsp; Transitions
                                     <div className="propertiesView-presentationTrails-title-icon">
@@ -1723,8 +1723,8 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                                     className="propertiesView-presentationTrails-title"
                                     onPointerDown={action(() => (this.openPresVisibilityAndDuration = !this.openPresVisibilityAndDuration))}
                                     style={{
-                                        color: SettingsManager.Instance.userColor,
-                                        backgroundColor: this.openPresVisibilityAndDuration ? SettingsManager.Instance.userVariantColor : SettingsManager.Instance.userBackgroundColor,
+                                        color: SettingsManager.userColor,
+                                        backgroundColor: this.openPresVisibilityAndDuration ? SettingsManager.userVariantColor : SettingsManager.userBackgroundColor,
                                     }}>
                                     &nbsp; <FontAwesomeIcon style={{ alignSelf: 'center' }} icon={'rocket'} /> &nbsp; Visibilty
                                     <div className="propertiesView-presentationTrails-title-icon">
@@ -1740,8 +1740,8 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                                     className="propertiesView-presentationTrails-title"
                                     onPointerDown={action(() => (this.openPresProgressivize = !this.openPresProgressivize))}
                                     style={{
-                                        color: SettingsManager.Instance.userColor,
-                                        backgroundColor: this.openPresProgressivize ? SettingsManager.Instance.userVariantColor : SettingsManager.Instance.userBackgroundColor,
+                                        color: SettingsManager.userColor,
+                                        backgroundColor: this.openPresProgressivize ? SettingsManager.userVariantColor : SettingsManager.userBackgroundColor,
                                     }}>
                                     &nbsp; <FontAwesomeIcon style={{ alignSelf: 'center' }} icon={'rocket'} /> &nbsp; Progressivize
                                     <div className="propertiesView-presentationTrails-title-icon">
@@ -1757,8 +1757,8 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                                     className="propertiesView-presentationTrails-title"
                                     onPointerDown={action(() => (this.openSlideOptions = !this.openSlideOptions))}
                                     style={{
-                                        color: SettingsManager.Instance.userColor,
-                                        backgroundColor: this.openSlideOptions ? SettingsManager.Instance.userVariantColor : SettingsManager.Instance.userBackgroundColor,
+                                        color: SettingsManager.userColor,
+                                        backgroundColor: this.openSlideOptions ? SettingsManager.userVariantColor : SettingsManager.userBackgroundColor,
                                     }}>
                                     &nbsp; <FontAwesomeIcon style={{ alignSelf: 'center' }} icon={type === DocumentType.AUDIO ? 'file-audio' : 'file-video'} /> &nbsp; {type === DocumentType.AUDIO ? 'Audio Options' : 'Video Options'}
                                     <div className="propertiesView-presentationTrails-title-icon">
diff --git a/src/client/views/SidebarAnnos.tsx b/src/client/views/SidebarAnnos.tsx
index c48a7241a..f3452c780 100644
--- a/src/client/views/SidebarAnnos.tsx
+++ b/src/client/views/SidebarAnnos.tsx
@@ -9,11 +9,11 @@ import { emptyFunction, returnAll, returnFalse, returnOne, returnTrue, returnZer
 import { Docs, DocUtils } from '../documents/Documents';
 import { CollectionViewType, DocumentType } from '../documents/DocumentTypes';
 import { LinkManager } from '../util/LinkManager';
+import { SearchUtil } from '../util/SearchUtil';
 import { Transform } from '../util/Transform';
 import { CollectionStackingView } from './collections/CollectionStackingView';
 import { FieldViewProps } from './nodes/FieldView';
 import { FormattedTextBox } from './nodes/formattedText/FormattedTextBox';
-import { SearchBox } from './search/SearchBox';
 import './SidebarAnnos.scss';
 import { StyleProp } from './StyleProvider';
 import React = require('react');
@@ -43,7 +43,7 @@ export class SidebarAnnos extends React.Component<FieldViewProps & ExtraProps> {
     @computed get allMetadata() {
         const keys = new Map<string, FieldResult<Field>>();
         DocListCast(this.props.rootDoc[this.sidebarKey]).forEach(doc =>
-            SearchBox.documentKeys(doc)
+            SearchUtil.documentKeys(doc)
                 .filter(key => key[0] && key[0] !== '_' && key[0] === key[0].toUpperCase())
                 .map(key => keys.set(key, doc[key]))
         );
diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx
index 24a269927..12935400b 100644
--- a/src/client/views/StyleProvider.tsx
+++ b/src/client/views/StyleProvider.tsx
@@ -4,6 +4,7 @@ import { Tooltip } from '@material-ui/core';
 import { IconButton, Shadows, Size } from 'browndash-components';
 import { action, runInAction } from 'mobx';
 import { extname } from 'path';
+import { BsArrowDown, BsArrowDownUp, BsArrowUp } from 'react-icons/bs';
 import { Doc, Opt, StrListCast } from '../../fields/Doc';
 import { BoolCast, Cast, DocCast, ImageCast, NumCast, StrCast } from '../../fields/Types';
 import { DashColor, lightOrDark, Utils } from '../../Utils';
@@ -14,15 +15,13 @@ import { LinkManager } from '../util/LinkManager';
 import { SelectionManager } from '../util/SelectionManager';
 import { ColorScheme, SettingsManager } from '../util/SettingsManager';
 import { undoBatch, UndoManager } from '../util/UndoManager';
-import { TreeSort } from './collections/TreeView';
+import { TreeSort } from './collections/TreeSort';
 import { Colors } from './global/globalEnums';
 import { InkingStroke } from './InkingStroke';
-import { MainView } from './MainView';
-import { DocumentViewProps } from './nodes/DocumentView';
+import { DocumentView, DocumentViewProps } from './nodes/DocumentView';
 import { FieldViewProps } from './nodes/FieldView';
 import { KeyValueBox } from './nodes/KeyValueBox';
 import { SliderBox } from './nodes/SliderBox';
-import { BsArrowDown, BsArrowUp, BsArrowDownUp } from 'react-icons/bs';
 import './StyleProvider.scss';
 import React = require('react');
 
@@ -159,7 +158,7 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
                 ''
             );
         case StyleProp.Color:
-            if (MainView.Instance.LastButton === doc) return SettingsManager.Instance.userBackgroundColor;
+            if (DocumentView.LastPressedSidebarBtn === doc) return SettingsManager.userBackgroundColor;
             if (Doc.IsSystem(doc!)) return StrCast(Doc.UserDoc().userColor)
             if (doc?.type === DocumentType.FONTICON) return Doc.UserDoc().userColor;
             const docColor: Opt<string> = StrCast(doc?.[fieldKey + 'color'], StrCast(doc?._color));
@@ -194,7 +193,7 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
                 ? 15
                 : 0;
         case StyleProp.BackgroundColor: {
-            if (MainView.Instance.LastButton === doc) return StrCast(Doc.UserDoc().userColor); // hack to indicate active menu panel item
+            if (DocumentView.LastPressedSidebarBtn === doc) return StrCast(Doc.UserDoc().userColor); // hack to indicate active menu panel item
             let docColor: Opt<string> = StrCast(doc?.[fieldKey + '_backgroundColor'], StrCast(doc?._backgroundColor, isCaption ? 'rgba(0,0,0,0.4)' : ''));
             // prettier-ignore
             switch (doc?.type) {
@@ -217,7 +216,7 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
                 case DocumentType.COL:
                     if (StrCast(Doc.LayoutField(doc)).includes(SliderBox.name)) break;
                     docColor = docColor || (Doc.IsSystem(doc)
-                            ? SettingsManager.Instance.userBackgroundColor
+                            ? SettingsManager.userBackgroundColor
                             : doc.annotationOn
                             ? '#00000010' // faint interior for collections on PDFs, images, etc
                             : doc?._isGroup
@@ -264,7 +263,7 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
             const isInk = doc && StrCast(Doc.Layout(doc).layout).includes(InkingStroke.name) && !props?.LayoutTemplateString;
             if (StrCast(doc?.pointerEvents) && !props?.LayoutTemplateString?.includes(KeyValueBox.name)) return StrCast(doc!.pointerEvents); // honor pointerEvents field (set by lock button usually) if it's not a keyValue view of the Doc
             if (docProps?.DocumentView?.().ComponentView?.overridePointerEvents?.() !== undefined) return docProps?.DocumentView?.().ComponentView?.overridePointerEvents?.();
-            if (MainView.Instance._exploreMode || doc?.layout_unrendered) return isInk ? 'visiblePainted' : 'all';
+            if (DocumentView.ExploreMode || doc?.layout_unrendered) return isInk ? 'visiblePainted' : 'all';
             if (props?.contentPointerEvents) return StrCast(props.contentPointerEvents);
             if (props?.pointerEvents?.() === 'none') return 'none';
             if (opacity() === 0) return 'none';
diff --git a/src/client/views/UndoStack.tsx b/src/client/views/UndoStack.tsx
index a551e5332..3fd64d1fd 100644
--- a/src/client/views/UndoStack.tsx
+++ b/src/client/views/UndoStack.tsx
@@ -19,7 +19,7 @@ export class UndoStack extends React.Component<UndoStackProps> {
     @observable static HideInline: boolean;
     @observable static Expand: boolean;
     render() {
-        const background = UndoManager.batchCounter.get() ? 'yellow' : SettingsManager.Instance.userBackgroundColor;
+        const background = UndoManager.batchCounter.get() ? 'yellow' : SettingsManager.userBackgroundColor;
         return this.props.inline && UndoStack.HideInline ? null : (
             <div className="undoStack-outerContainer">
                 <Popup
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index e15d57306..519b7c905 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -3,6 +3,7 @@ import { observer } from 'mobx-react';
 import * as ReactDOM from 'react-dom/client';
 import * as GoldenLayout from '../../../client/goldenLayout';
 import { Doc, DocListCast, Opt } from '../../../fields/Doc';
+import { AclAdmin, AclEdit } from '../../../fields/DocSymbols';
 import { Id } from '../../../fields/FieldSymbols';
 import { InkTool } from '../../../fields/InkField';
 import { List } from '../../../fields/List';
@@ -13,6 +14,7 @@ import { emptyFunction, incrementTitleCopy } from '../../../Utils';
 import { DocServer } from '../../DocServer';
 import { Docs } from '../../documents/Documents';
 import { CollectionViewType, DocumentType } from '../../documents/DocumentTypes';
+import { DocumentManager } from '../../util/DocumentManager';
 import { DragManager } from '../../util/DragManager';
 import { InteractionUtils } from '../../util/InteractionUtils';
 import { ScriptingGlobals } from '../../util/ScriptingGlobals';
@@ -28,8 +30,6 @@ import './CollectionDockingView.scss';
 import { CollectionFreeFormView } from './collectionFreeForm';
 import { CollectionSubView, SubCollectionViewProps } from './CollectionSubView';
 import { TabDocView } from './TabDocView';
-import { DocumentManager } from '../../util/DocumentManager';
-import { AclAdmin, AclEdit } from '../../../fields/DocSymbols';
 import React = require('react');
 const _global = (window /* browser */ || global) /* node */ as any;
 
diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx
index f65e8698f..5c9dd2058 100644
--- a/src/client/views/collections/CollectionMenu.tsx
+++ b/src/client/views/collections/CollectionMenu.tsx
@@ -181,7 +181,7 @@ export class CollectionMenu extends AntimodeMenu<CollectionMenuProps> {
             <div
                 className="collectionMenu-container"
                 style={{
-                    background: SettingsManager.Instance.userBackgroundColor,
+                    background: SettingsManager.userBackgroundColor,
                     // borderColor: StrCast(Doc.UserDoc().userColor)
                 }}>
                 {this.contMenuButtons}
diff --git a/src/client/views/collections/CollectionStackedTimeline.tsx b/src/client/views/collections/CollectionStackedTimeline.tsx
index de58e1fe7..d2be70577 100644
--- a/src/client/views/collections/CollectionStackedTimeline.tsx
+++ b/src/client/views/collections/CollectionStackedTimeline.tsx
@@ -2,12 +2,12 @@ import React = require('react');
 import { action, computed, IReactionDisposer, observable, reaction } from 'mobx';
 import { observer } from 'mobx-react';
 import { computedFn } from 'mobx-utils';
-import { Doc, Opt, StrListCast } from '../../../fields/Doc';
+import { Doc, Opt } from '../../../fields/Doc';
 import { Id } from '../../../fields/FieldSymbols';
 import { List } from '../../../fields/List';
 import { listSpec } from '../../../fields/Schema';
 import { ComputedField, ScriptField } from '../../../fields/ScriptField';
-import { Cast, NumCast, ScriptCast } from '../../../fields/Types';
+import { Cast, NumCast } from '../../../fields/Types';
 import { ImageField } from '../../../fields/URLField';
 import { emptyFunction, formatTime, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnNone, returnTrue, returnZero, setupMoveUpEvents, smoothScrollHorizontal, StopEvent } from '../../../Utils';
 import { Docs } from '../../documents/Documents';
diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
index f379d09ff..f6acafa95 100644
--- a/src/client/views/collections/TabDocView.tsx
+++ b/src/client/views/collections/TabDocView.tsx
@@ -1,6 +1,6 @@
 import { IconProp } from '@fortawesome/fontawesome-svg-core';
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { Tooltip } from '@material-ui/core';
+import { Popup, Type } from 'browndash-components';
 import { clamp } from 'lodash';
 import { action, computed, IReactionDisposer, observable, ObservableSet, reaction } from 'mobx';
 import { observer } from 'mobx-react';
@@ -10,7 +10,7 @@ import { DocData, Height, Width } from '../../../fields/DocSymbols';
 import { Id } from '../../../fields/FieldSymbols';
 import { List } from '../../../fields/List';
 import { FieldId } from '../../../fields/RefField';
-import { BoolCast, Cast, DocCast, NumCast, StrCast } from '../../../fields/Types';
+import { Cast, DocCast, NumCast, StrCast } from '../../../fields/Types';
 import { emptyFunction, lightOrDark, returnEmptyDoclist, returnFalse, returnTrue, setupMoveUpEvents, simulateMouseClick, Utils } from '../../../Utils';
 import { DocServer } from '../../DocServer';
 import { CollectionViewType, DocumentType } from '../../documents/DocumentTypes';
@@ -21,9 +21,8 @@ import { SnappingManager } from '../../util/SnappingManager';
 import { Transform } from '../../util/Transform';
 import { undoable, UndoManager } from '../../util/UndoManager';
 import { DashboardView } from '../DashboardView';
-import { Colors, Shadows } from '../global/globalEnums';
+import { Colors } from '../global/globalEnums';
 import { LightboxView } from '../LightboxView';
-import { MainView } from '../MainView';
 import { DocFocusOptions, DocumentView, DocumentViewProps, OpenWhere, OpenWhereMod } from '../nodes/DocumentView';
 import { DashFieldView } from '../nodes/formattedText/DashFieldView';
 import { KeyValueBox } from '../nodes/KeyValueBox';
@@ -34,7 +33,6 @@ import { CollectionFreeFormView } from './collectionFreeForm/CollectionFreeFormV
 import { CollectionView } from './CollectionView';
 import './TabDocView.scss';
 import React = require('react');
-import { Popup, Toggle, Type } from 'browndash-components';
 const _global = (window /* browser */ || global) /* node */ as any;
 
 interface TabDocViewProps {
@@ -426,6 +424,7 @@ export class TabDocView extends React.Component<TabDocViewProps> {
     disableMinimap = () => !this._document || this._document.layout !== CollectionView.LayoutString(Doc.LayoutFieldKey(this._document)) || this._document?._type_collection !== CollectionViewType.Freeform;
     whenChildContentActiveChanges = (isActive: boolean) => (this._isAnyChildContentActive = isActive);
     isContentActive = () => this._isContentActive;
+    waitForDoubleClick = () => (DocumentView.ExploreMode ? 'never' : undefined);
     @computed get docView() {
         return !this._activated || !this._document ? null : (
             <>
@@ -441,8 +440,8 @@ export class TabDocView extends React.Component<TabDocViewProps> {
                     hideTitle={this.props.keyValue}
                     Document={this._document}
                     DataDoc={!Doc.AreProtosEqual(this._document[DocData], this._document) ? this._document[DocData] : undefined}
-                    onBrowseClick={MainView.Instance.exploreMode}
-                    waitForDoubleClickToClick={MainView.Instance.waitForDoubleClick}
+                    onBrowseClick={DocumentView.exploreMode}
+                    waitForDoubleClickToClick={this.waitForDoubleClick}
                     isContentActive={this.isContentActive}
                     isDocumentActive={returnFalse}
                     PanelWidth={this.PanelWidth}
diff --git a/src/client/views/collections/TreeSort.ts b/src/client/views/collections/TreeSort.ts
new file mode 100644
index 000000000..977acd030
--- /dev/null
+++ b/src/client/views/collections/TreeSort.ts
@@ -0,0 +1,6 @@
+export enum TreeSort {
+    AlphaUp = 'alphabetical from z',
+    AlphaDown = 'alphabetical from A',
+    Zindex = 'by Z index',
+    WhenAdded = 'when added',
+}
diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx
index 3402a8c8d..701150769 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -35,6 +35,7 @@ import { CollectionView } from './CollectionView';
 import './TreeView.scss';
 import React = require('react');
 import { IconButton, Size } from 'browndash-components';
+import { TreeSort } from './TreeSort';
 
 export interface TreeViewProps {
     treeView: CollectionTreeView;
@@ -77,12 +78,6 @@ const treeBulletWidth = function () {
     return Number(TREE_BULLET_WIDTH.replace('px', ''));
 };
 
-export enum TreeSort {
-    AlphaUp = 'alphabetical from z',
-    AlphaDown = 'alphabetical from A',
-    Zindex = 'by Z index',
-    WhenAdded = 'when added',
-}
 /**
  * Renders a treeView of a collection of documents
  *
@@ -578,7 +573,7 @@ export class TreeView extends React.Component<TreeViewProps> {
             return (
                 <div>
                     {!docs?.length || this.props.AddToMap /* hack to identify pres box trees */ ? null : (
-                        <div className='treeView-sorting'>
+                        <div className="treeView-sorting">
                             <IconButton
                                 color={sortings[sorting]?.color}
                                 size={Size.XSMALL}
@@ -602,7 +597,7 @@ export class TreeView extends React.Component<TreeViewProps> {
                         style={{ cursor: 'inherit' }}
                         key={expandKey + 'more'}
                         title={`Sorted by : ${this.doc.treeView_SortCriterion}. click to cycle`}
-                        className='' //this.doc.treeView_HideTitle ? 'no-indent' : ''}
+                        className="" //this.doc.treeView_HideTitle ? 'no-indent' : ''}
                         onPointerDown={e => {
                             downX = e.clientX;
                             downY = e.clientY;
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index f5cc1eb53..16d6f1270 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -371,7 +371,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
             const nd = [Doc.NativeWidth(layoutDoc), Doc.NativeHeight(layoutDoc)];
             layoutDoc._width = NumCast(layoutDoc._width, 300);
             layoutDoc._height = NumCast(layoutDoc._height, nd[0] && nd[1] ? (nd[1] / nd[0]) * NumCast(layoutDoc._width) : 300);
-            (d._raiseWhenDragged === undefined ? DragManager.GetRaiseWhenDragged() : d._raiseWhenDragged) && (d.zIndex = zsorted.length + 1 + i); // bringToFront
+            !d._keepZWhenDragged && (d.zIndex = zsorted.length + 1 + i); // bringToFront
         }
 
         if (this.layoutDoc._autoArrange || de.metaKey) {
@@ -1267,7 +1267,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
     };
     @computed get _pointerEvents() {
         const engine = this.props.layoutEngine?.() || StrCast(this.props.Document._layoutEngine);
-        const pointerEvents = DocumentDecorations.Instance.Interacting
+        const pointerEvents = DocumentView.Interacting
             ? 'none'
             : this.props.childPointerEvents ?? (this.props.viewDefDivClick || (engine === computePassLayout.name && !this.props.isSelected(true)) || this.isContentActive() === false ? 'none' : this.props.pointerEvents?.());
         return pointerEvents;
diff --git a/src/client/views/linking/LinkPopup.tsx b/src/client/views/linking/LinkPopup.tsx
index 6895c0746..9a9a89732 100644
--- a/src/client/views/linking/LinkPopup.tsx
+++ b/src/client/views/linking/LinkPopup.tsx
@@ -3,15 +3,14 @@ import { observer } from 'mobx-react';
 import { EditorView } from 'prosemirror-view';
 import { Doc } from '../../../fields/Doc';
 import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue } from '../../../Utils';
-import { DocUtils } from '../../documents/Documents';
 import { Transform } from '../../util/Transform';
 import { undoBatch } from '../../util/UndoManager';
+import { OpenWhere } from '../nodes/DocumentView';
 import { FormattedTextBox } from '../nodes/formattedText/FormattedTextBox';
 import { SearchBox } from '../search/SearchBox';
 import { DefaultStyleProvider } from '../StyleProvider';
 import './LinkPopup.scss';
 import React = require('react');
-import { OpenWhere } from '../nodes/DocumentView';
 
 interface LinkPopupProps {
     linkFrom?: () => Doc | undefined;
diff --git a/src/client/views/newlightbox/ButtonMenu/ButtonMenu.tsx b/src/client/views/newlightbox/ButtonMenu/ButtonMenu.tsx
index ff17e5c12..3a95e5f74 100644
--- a/src/client/views/newlightbox/ButtonMenu/ButtonMenu.tsx
+++ b/src/client/views/newlightbox/ButtonMenu/ButtonMenu.tsx
@@ -1,14 +1,13 @@
-import './ButtonMenu.scss';
+import { action } from 'mobx';
 import * as React from 'react';
-import { IButtonMenu } from './utils';
-import { NewLightboxView } from '../NewLightboxView';
-import { SelectionManager } from '../../../util/SelectionManager';
-import { CollectionDockingView } from '../../collections/CollectionDockingView';
-import { OpenWhereMod } from '../../nodes/DocumentView';
 import { Doc } from '../../../../fields/Doc';
 import { InkTool } from '../../../../fields/InkField';
-import { MainView } from '../../MainView';
-import { action } from 'mobx';
+import { SelectionManager } from '../../../util/SelectionManager';
+import { CollectionDockingView } from '../../collections/CollectionDockingView';
+import { DocumentView, OpenWhereMod } from '../../nodes/DocumentView';
+import { NewLightboxView } from '../NewLightboxView';
+import './ButtonMenu.scss';
+import { IButtonMenu } from './utils';
 
 export const ButtonMenu = (props: IButtonMenu) => {
     return (
@@ -40,10 +39,10 @@ export const ButtonMenu = (props: IButtonMenu) => {
             <div
                 className="newLightboxView-exploreBtn"
                 title="toggle explore mode to navigate among documents only"
-                style={{ background: MainView.Instance._exploreMode ? 'white' : undefined }}
+                style={{ background: DocumentView.ExploreMode ? 'white' : undefined }}
                 onClick={action(e => {
                     e.stopPropagation();
-                    MainView.Instance._exploreMode = !MainView.Instance._exploreMode;
+                    DocumentView.ExploreMode = !DocumentView.ExploreMode;
                 })}></div>
         </div>
     );
diff --git a/src/client/views/newlightbox/NewLightboxView.tsx b/src/client/views/newlightbox/NewLightboxView.tsx
index 3acbd1a32..ca90f6a0f 100644
--- a/src/client/views/newlightbox/NewLightboxView.tsx
+++ b/src/client/views/newlightbox/NewLightboxView.tsx
@@ -2,35 +2,32 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { action, computed, observable } from 'mobx';
 import { observer } from 'mobx-react';
 import * as React from 'react';
-import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnTrue } from '../../../Utils';
-import { Doc, DocListCast, Opt, StrListCast } from '../../../fields/Doc';
+import { Doc, DocListCast, Opt } from '../../../fields/Doc';
 import { InkTool } from '../../../fields/InkField';
 import { Cast, NumCast, StrCast } from '../../../fields/Types';
+import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnTrue } from '../../../Utils';
 import { DocUtils } from '../../documents/Documents';
 import { DocumentManager } from '../../util/DocumentManager';
 import { LinkManager } from '../../util/LinkManager';
 import { SelectionManager } from '../../util/SelectionManager';
 import { Transform } from '../../util/Transform';
-import { GestureOverlay } from '../GestureOverlay';
-import { MainView } from '../MainView';
-import { DefaultStyleProvider } from '../StyleProvider';
 import { CollectionStackedTimeline } from '../collections/CollectionStackedTimeline';
 import { TabDocView } from '../collections/TabDocView';
+import { GestureOverlay } from '../GestureOverlay';
+import { LightboxView } from '../LightboxView';
 import { DocumentView, OpenWhere } from '../nodes/DocumentView';
+import { DefaultStyleProvider } from '../StyleProvider';
+import { IRecommendation } from './components';
 import { ExploreView } from './ExploreView';
-import { IBounds, emptyBounds } from './ExploreView/utils';
+import { emptyBounds, IBounds } from './ExploreView/utils';
 import { NewLightboxHeader } from './Header';
 import './NewLightboxView.scss';
 import { RecommendationList } from './RecommendationList';
-import { IRecommendation } from './components';
-import { fetchKeywords, fetchRecommendations } from './utils';
-import { List } from '../../../fields/List';
-import { LightboxView } from '../LightboxView';
 
 enum LightboxStatus {
-    RECOMMENDATIONS = "recommendations",
-    ANNOTATIONS = "annotations",
-    NONE = "none"
+    RECOMMENDATIONS = 'recommendations',
+    ANNOTATIONS = 'annotations',
+    NONE = 'none',
 }
 
 interface LightboxViewProps {
@@ -63,30 +60,30 @@ export class NewLightboxView extends React.Component<LightboxViewProps> {
     @observable private static _docView: Opt<DocumentView>;
 
     // keywords
-    @observable private static _keywords: string[] = []
+    @observable private static _keywords: string[] = [];
     @action public static SetKeywords(kw: string[]) {
-        this._keywords = kw
+        this._keywords = kw;
     }
     @computed public static get Keywords() {
-        return this._keywords
+        return this._keywords;
     }
 
     // query
-    @observable private static _query: string = ''
+    @observable private static _query: string = '';
     @action public static SetQuery(query: string) {
-        this._query = query
+        this._query = query;
     }
     @computed public static get Query() {
-        return this._query
+        return this._query;
     }
 
     // keywords
-    @observable private static _recs: IRecommendation[] = []
+    @observable private static _recs: IRecommendation[] = [];
     @action public static SetRecs(recs: IRecommendation[]) {
-        this._recs = recs
+        this._recs = recs;
     }
     @computed public static get Recs() {
-        return this._recs
+        return this._recs;
     }
 
     // bounds
@@ -108,7 +105,7 @@ export class NewLightboxView extends React.Component<LightboxViewProps> {
     }
 
     // newLightbox sidebar status
-    @observable private static _sidebarStatus: Opt<string> = "";
+    @observable private static _sidebarStatus: Opt<string> = '';
     @action public static SetSidebarStatus(sidebarStatus: Opt<string>) {
         this._sidebarStatus = sidebarStatus;
     }
@@ -129,7 +126,7 @@ export class NewLightboxView extends React.Component<LightboxViewProps> {
             this._docFilters && (this._docFilters.length = 0);
             this._future = this._history = [];
             Doc.ActiveTool = InkTool.None;
-            MainView.Instance._exploreMode = false;
+            DocumentView.ExploreMode = false;
         } else {
             const l = DocUtils.MakeLinkToActiveAudio(() => doc).lastElement();
             l && (Cast(l.link_anchor_2, Doc, null).backgroundColor = 'lightgreen');
@@ -289,35 +286,38 @@ export class NewLightboxView extends React.Component<LightboxViewProps> {
 
     @computed
     get documentView() {
-        if (!LightboxView.LightboxDoc) return null
-        else return (<GestureOverlay isActive={true}>
-                            <DocumentView
-                                ref={action((r: DocumentView | null) => (NewLightboxView._docView = r !== null ? r : undefined))}
-                                Document={LightboxView.LightboxDoc}
-                                DataDoc={undefined}
-                                PanelWidth={this.newLightboxWidth}
-                                PanelHeight={this.newLightboxHeight}
-                                LayoutTemplate={NewLightboxView.LightboxDocTemplate}
-                                isDocumentActive={returnTrue} // without this being true, sidebar annotations need to be activated before text can be selected.
-                                isContentActive={returnTrue}
-                                styleProvider={DefaultStyleProvider}
-                                ScreenToLocalTransform={this.newLightboxScreenToLocal}
-                                renderDepth={0}
-                                rootSelected={returnTrue}
-                                docViewPath={returnEmptyDoclist}
-                                childFilters={this.docFilters}
-                                childFiltersByRanges={returnEmptyFilter}
-                                searchFilterDocs={returnEmptyDoclist}
-                                addDocument={undefined}
-                                removeDocument={undefined}
-                                whenChildContentsActiveChanged={emptyFunction}
-                                addDocTab={this.addDocTab}
-                                pinToPres={TabDocView.PinDoc}
-                                bringToFront={emptyFunction}
-                                onBrowseClick={MainView.Instance.exploreMode}
-                                focus={emptyFunction}
-                            />
-                        </GestureOverlay>)
+        if (!LightboxView.LightboxDoc) return null;
+        else
+            return (
+                <GestureOverlay isActive={true}>
+                    <DocumentView
+                        ref={action((r: DocumentView | null) => (NewLightboxView._docView = r !== null ? r : undefined))}
+                        Document={LightboxView.LightboxDoc}
+                        DataDoc={undefined}
+                        PanelWidth={this.newLightboxWidth}
+                        PanelHeight={this.newLightboxHeight}
+                        LayoutTemplate={NewLightboxView.LightboxDocTemplate}
+                        isDocumentActive={returnTrue} // without this being true, sidebar annotations need to be activated before text can be selected.
+                        isContentActive={returnTrue}
+                        styleProvider={DefaultStyleProvider}
+                        ScreenToLocalTransform={this.newLightboxScreenToLocal}
+                        renderDepth={0}
+                        rootSelected={returnTrue}
+                        docViewPath={returnEmptyDoclist}
+                        childFilters={this.docFilters}
+                        childFiltersByRanges={returnEmptyFilter}
+                        searchFilterDocs={returnEmptyDoclist}
+                        addDocument={undefined}
+                        removeDocument={undefined}
+                        whenChildContentsActiveChanged={emptyFunction}
+                        addDocTab={this.addDocTab}
+                        pinToPres={TabDocView.PinDoc}
+                        bringToFront={emptyFunction}
+                        onBrowseClick={DocumentView.exploreMode}
+                        focus={emptyFunction}
+                    />
+                </GestureOverlay>
+            );
     }
 
     future = () => NewLightboxView._future;
@@ -337,29 +337,28 @@ export class NewLightboxView extends React.Component<LightboxViewProps> {
                         NewLightboxView.SetNewLightboxDoc(undefined);
                     }
                 }}>
-                <div className={`app-document`} style={{gridTemplateColumns: `calc(100% - 400px) 400px`}}>
-                <div
-                    className="newLightboxView-contents"
-                    style={{
-                        top: 20,
-                        left: 20,
-                        width: this.newLightboxWidth(),
-                        height: this.newLightboxHeight() - 40,
-                    }}>
+                <div className={`app-document`} style={{ gridTemplateColumns: `calc(100% - 400px) 400px` }}>
+                    <div
+                        className="newLightboxView-contents"
+                        style={{
+                            top: 20,
+                            left: 20,
+                            width: this.newLightboxWidth(),
+                            height: this.newLightboxHeight() - 40,
+                        }}>
                         <NewLightboxHeader height={newLightboxHeaderHeight} width={this.newLightboxWidth()} />
-                        {!NewLightboxView._explore ? 
-                            <div className="newLightboxView-doc" style={{height: this.newLightboxHeight()}}>
+                        {!NewLightboxView._explore ? (
+                            <div className="newLightboxView-doc" style={{ height: this.newLightboxHeight() }}>
                                 {this.documentView}
                             </div>
-                        :
+                        ) : (
                             <div className={`explore`}>
-                                <ExploreView recs={NewLightboxView.Recs} bounds={NewLightboxView.Bounds}/>
+                                <ExploreView recs={NewLightboxView.Recs} bounds={NewLightboxView.Bounds} />
                             </div>
-                        }
-                </div>
-                    <RecommendationList keywords={NewLightboxView.Keywords}/>
+                        )}
+                    </div>
+                    <RecommendationList keywords={NewLightboxView.Keywords} />
                 </div>
-                
             </div>
         );
     }
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index be1eb3901..74eee49e0 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -28,6 +28,7 @@ import { FollowLinkScript } from '../../util/LinkFollower';
 import { LinkManager } from '../../util/LinkManager';
 import { ScriptingGlobals } from '../../util/ScriptingGlobals';
 import { SelectionManager } from '../../util/SelectionManager';
+import { SettingsManager } from '../../util/SettingsManager';
 import { SharingManager } from '../../util/SharingManager';
 import { SnappingManager } from '../../util/SnappingManager';
 import { Transform } from '../../util/Transform';
@@ -51,7 +52,6 @@ import { LinkAnchorBox } from './LinkAnchorBox';
 import { PresEffect, PresEffectDirection } from './trails';
 import { PinProps, PresBox } from './trails/PresBox';
 import React = require('react');
-import { SettingsManager } from '../../util/SettingsManager';
 const { Howl } = require('howler');
 
 interface Window {
@@ -428,7 +428,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
         if (!this.Document.ignoreClick && this.pointerEvents !== 'none' && this.props.renderDepth >= 0 && Utils.isClick(e.clientX, e.clientY, this._downX, this._downY, this._downTime)) {
             let stopPropagate = true;
             let preventDefault = true;
-            (this.rootDoc._raiseWhenDragged === undefined ? DragManager.GetRaiseWhenDragged() : this.rootDoc._raiseWhenDragged) && this.props.bringToFront(this.rootDoc);
+            !this.rootDoc._keepZWhenDragged && this.props.bringToFront(this.rootDoc);
             if (this._doubleTap) {
                 const defaultDblclick = this.props.defaultDoubleClick?.() || this.Document.defaultDoubleClick;
                 if (this.onDoubleClickHandler?.script) {
@@ -744,8 +744,8 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
                     zorderItems.push({ description: 'Bring to Front', event: () => SelectionManager.Views().forEach(dv => dv.props.bringToFront(dv.rootDoc, false)), icon: 'arrow-up' });
                     zorderItems.push({ description: 'Send to Back', event: () => SelectionManager.Views().forEach(dv => dv.props.bringToFront(dv.rootDoc, true)), icon: 'arrow-down' });
                     zorderItems.push({
-                        description: this.rootDoc._raiseWhenDragged !== false ? 'Keep ZIndex when dragged' : 'Allow ZIndex to change when dragged',
-                        event: undoBatch(action(() => (this.rootDoc._raiseWhenDragged = this.rootDoc._raiseWhenDragged === undefined ? false : undefined))),
+                        description: !this.rootDoc._keepZDragged ? 'Keep ZIndex when dragged' : 'Allow ZIndex to change when dragged',
+                        event: undoBatch(action(() => (this.rootDoc._keepZWhenDragged = !this.rootDoc._keepZWhenDragged))),
                         icon: 'hand-point-up',
                     });
                     !zorders && cm.addItem({ description: 'Z Order...', addDivider: true, noexpand: true, subitems: zorderItems, icon: 'layer-group' });
@@ -1114,7 +1114,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
             </div>
         );
         const targetDoc = showTitle?.startsWith('_') ? this.layoutDoc : this.rootDoc;
-        const background = StrCast(SharingManager.Instance.users.find(u => u.user.email === this.dataDoc.author)?.sharingDoc.headingColor, StrCast(Doc.SharingDoc().headingColor, SettingsManager.Instance.userVariantColor));
+        const background = StrCast(SharingManager.Instance.users.find(u => u.user.email === this.dataDoc.author)?.sharingDoc.headingColor, StrCast(Doc.SharingDoc().headingColor, SettingsManager.userVariantColor));
         const sidebarWidthPercent = +StrCast(this.layoutDoc.layout_sidebarWidthPercent).replace('%', '');
         const titleView = !showTitle ? null : (
             <div
@@ -1276,7 +1276,13 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
 @observer
 export class DocumentView extends React.Component<DocumentViewProps> {
     public static ROOT_DIV = 'documentView-effectsWrapper';
+    @observable public static Interacting = false;
     @observable public static LongPress = false;
+    @observable public static ExploreMode = false;
+    @observable public static LastPressedSidebarBtn: Opt<Doc>; // bcz: this is a hack to handle highlighting buttons in the leftpanel menu .. need to find a cleaner approach
+    @computed public static get exploreMode() {
+        return () => (DocumentView.ExploreMode ? ScriptField.MakeScript('CollectionBrowseClick(documentView, clientX, clientY)', { documentView: 'any', clientX: 'number', clientY: 'number' })! : undefined);
+    }
     @observable public docView: DocumentViewInternal | undefined | null;
     @observable public textHtmlOverlay: Opt<string>;
     @observable private _isHovering = false;
diff --git a/src/client/views/nodes/FontIconBox/FontIconBox.tsx b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
index 94650cc88..fc66d40db 100644
--- a/src/client/views/nodes/FontIconBox/FontIconBox.tsx
+++ b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
@@ -67,19 +67,6 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
         }
     };
 
-    static GetShowLabels() {
-        return BoolCast(Doc.UserDoc()._showLabel);
-    }
-    static SetShowLabels(show: boolean) {
-        Doc.UserDoc()._showLabel = show;
-    }
-    static GetRecognizeGestures() {
-        return BoolCast(Doc.UserDoc()._recognizeGestures);
-    }
-    static SetRecognizeGestures(show: boolean) {
-        Doc.UserDoc()._recognizeGestures = show;
-    }
-
     // Determining UI Specs
     @computed get label() {
         return StrCast(this.rootDoc.icon_label, StrCast(this.rootDoc.title));
@@ -139,7 +126,7 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
         const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color);
         // Script for checking the outcome of the toggle
         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 label = !Doc.GetShowIconLabels() ? null : <div className="fontIconBox-label">{this.label}</div>;
 
         return (
             <NumberDropdown
@@ -174,7 +161,7 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
                     Doc.UnBrushAllDocs();
                 })}>
                 {this.Icon(color)}
-                {!this.label || !FontIconBox.GetShowLabels() ? null : (
+                {!this.label || !Doc.GetShowIconLabels() ? null : (
                     <div className="fontIconBox-label" style={{ color: color, backgroundColor: backgroundColor }}>
                         {' '}
                         {this.label}{' '}
diff --git a/src/client/views/nodes/LinkDocPreview.tsx b/src/client/views/nodes/LinkDocPreview.tsx
index d69009415..42c8ea6a4 100644
--- a/src/client/views/nodes/LinkDocPreview.tsx
+++ b/src/client/views/nodes/LinkDocPreview.tsx
@@ -4,7 +4,7 @@ import { action, computed, observable } from 'mobx';
 import { observer } from 'mobx-react';
 import wiki from 'wikijs';
 import { Doc, DocCastAsync, Opt } from '../../../fields/Doc';
-import { DirectLinks, Height, Width } from '../../../fields/DocSymbols';
+import { Height, Width } from '../../../fields/DocSymbols';
 import { Cast, DocCast, NumCast, PromiseValue, StrCast } from '../../../fields/Types';
 import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnEmptyString, returnFalse, returnNone, setupMoveUpEvents } from '../../../Utils';
 import { DocServer } from '../../DocServer';
@@ -13,9 +13,9 @@ import { DocumentType } from '../../documents/DocumentTypes';
 import { DragManager } from '../../util/DragManager';
 import { LinkFollower } from '../../util/LinkFollower';
 import { LinkManager } from '../../util/LinkManager';
+import { SearchUtil } from '../../util/SearchUtil';
 import { SettingsManager } from '../../util/SettingsManager';
 import { Transform } from '../../util/Transform';
-import { SearchBox } from '../search/SearchBox';
 import { DocumentView, DocumentViewSharedProps, OpenWhere } from './DocumentView';
 import './LinkDocPreview.scss';
 import React = require('react');
@@ -174,7 +174,7 @@ export class LinkDocPreview extends React.Component<LinkDocPreviewProps> {
             LinkFollower.FollowLink(this._linkDoc, this._linkSrc, false);
         } else if (this.props.hrefs?.length) {
             const webDoc =
-                Array.from(SearchBox.staticSearchCollection(Doc.MyFilesystem, this.props.hrefs[0]).keys()).lastElement() ??
+                Array.from(SearchUtil.SearchCollection(Doc.MyFilesystem, this.props.hrefs[0]).keys()).lastElement() ??
                 Docs.Create.WebDocument(this.props.hrefs[0], { title: this.props.hrefs[0], _nativeWidth: 850, _width: 200, _height: 400, data_useCors: true });
             this.props.docProps?.addDocTab(webDoc, OpenWhere.lightbox);
         }
diff --git a/src/client/views/nodes/LoadingBox.tsx b/src/client/views/nodes/LoadingBox.tsx
index fcbd0128d..0b02626e9 100644
--- a/src/client/views/nodes/LoadingBox.tsx
+++ b/src/client/views/nodes/LoadingBox.tsx
@@ -1,14 +1,14 @@
-import { action, observable, runInAction } from 'mobx';
+import { observable, runInAction } from 'mobx';
 import { observer } from 'mobx-react';
 import * as React from 'react';
 import ReactLoading from 'react-loading';
 import { Doc } from '../../../fields/Doc';
+import { Id } from '../../../fields/FieldSymbols';
 import { StrCast } from '../../../fields/Types';
 import { Networking } from '../../Network';
 import { ViewBoxAnnotatableComponent } from '../DocComponent';
 import { FieldView, FieldViewProps } from './FieldView';
 import './LoadingBox.scss';
-import { Id } from '../../../fields/FieldSymbols';
 
 /**
  * LoadingBox Class represents a placeholder doc for documents that are currently
@@ -44,7 +44,7 @@ export class LoadingBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
             this.rootDoc.loadingError = 'Upload interrupted, please try again';
         } else {
             const updateFunc = async () => {
-                const result = await Networking.QueryYoutubeProgress(StrCast(this.rootDoc[Id])); // We use the guid of the overwriteDoc to track file uploads. 
+                const result = await Networking.QueryYoutubeProgress(StrCast(this.rootDoc[Id])); // We use the guid of the overwriteDoc to track file uploads.
                 runInAction(() => (this.progress = result.progress));
                 this._timer = setTimeout(updateFunc, 1000);
             };
diff --git a/src/client/views/nodes/ScreenshotBox.tsx b/src/client/views/nodes/ScreenshotBox.tsx
index 83a29f071..fa19caae1 100644
--- a/src/client/views/nodes/ScreenshotBox.tsx
+++ b/src/client/views/nodes/ScreenshotBox.tsx
@@ -314,7 +314,7 @@ export class ScreenshotBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatabl
                             </>
                         </CollectionFreeFormView>
                     </div>
-                    <div style={{ background: SettingsManager.Instance.userColor, position: 'relative', height: this.formattedPanelHeight() }}>
+                    <div style={{ background: SettingsManager.userColor, position: 'relative', height: this.formattedPanelHeight() }}>
                         {!(this.dataDoc[this.fieldKey + '_dictation'] instanceof Doc) ? null : (
                             <FormattedTextBox
                                 {...this.props}
@@ -336,8 +336,8 @@ export class ScreenshotBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatabl
                     </div>
                 </div>
                 {!this.props.isSelected() ? null : (
-                    <div className="screenshotBox-uiButtons" style={{ background: SettingsManager.Instance.userColor }}>
-                        <div className="screenshotBox-recorder" style={{ color: SettingsManager.Instance.userBackgroundColor, background: SettingsManager.Instance.userVariantColor }} key="snap" onPointerDown={this.toggleRecording}>
+                    <div className="screenshotBox-uiButtons" style={{ background: SettingsManager.userColor }}>
+                        <div className="screenshotBox-recorder" style={{ color: SettingsManager.userBackgroundColor, background: SettingsManager.userVariantColor }} key="snap" onPointerDown={this.toggleRecording}>
                             <FontAwesomeIcon icon="file" size="lg" />
                         </div>
                     </div>
diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx
index 2177adeff..48716b867 100644
--- a/src/client/views/nodes/VideoBox.tsx
+++ b/src/client/views/nodes/VideoBox.tsx
@@ -26,11 +26,10 @@ import { CollectionStackedTimeline, TrimScope } from '../collections/CollectionS
 import { ContextMenu } from '../ContextMenu';
 import { ContextMenuProps } from '../ContextMenuItem';
 import { ViewBoxAnnotatableComponent, ViewBoxAnnotatableProps } from '../DocComponent';
-import { DocumentDecorations } from '../DocumentDecorations';
 import { MarqueeAnnotator } from '../MarqueeAnnotator';
 import { AnchorMenu } from '../pdf/AnchorMenu';
 import { StyleProp } from '../StyleProvider';
-import { OpenWhere } from './DocumentView';
+import { DocumentView, OpenWhere } from './DocumentView';
 import { FieldView, FieldViewProps } from './FieldView';
 import { RecordingBox } from './RecordingBox';
 import { PinProps, PresBox } from './trails';
@@ -624,7 +623,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
                 () => !this._playing && this.Seek(NumCast(this.layoutDoc._layout_currentTimecode))
             );
             this._disposers.youtubeReactionDisposer = reaction(
-                () => Doc.ActiveTool === InkTool.None && this.props.isSelected(true) && !SnappingManager.GetIsDragging() && !DocumentDecorations.Instance.Interacting,
+                () => Doc.ActiveTool === InkTool.None && this.props.isSelected(true) && !SnappingManager.GetIsDragging() && !DocumentView.Interacting,
                 interactive => (iframe.style.pointerEvents = interactive ? 'all' : 'none'),
                 { fireImmediately: true }
             );
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index 200d06a0b..bd969b527 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -11,9 +11,10 @@ import { keymap } from 'prosemirror-keymap';
 import { Fragment, Mark, Node, Slice } from 'prosemirror-model';
 import { EditorState, NodeSelection, Plugin, TextSelection, Transaction } from 'prosemirror-state';
 import { EditorView } from 'prosemirror-view';
+import { BsMarkdownFill } from 'react-icons/bs';
 import { DateField } from '../../../../fields/DateField';
-import { Doc, DocListCast, StrListCast, Field, Opt } from '../../../../fields/Doc';
-import { AclAdmin, AclAugment, AclEdit, AclSelfEdit, DocCss, Height, Width, ForceServerWrite, UpdatingFromServer } from '../../../../fields/DocSymbols';
+import { Doc, DocListCast, Field, Opt } from '../../../../fields/Doc';
+import { AclAdmin, AclAugment, AclEdit, AclSelfEdit, DocCss, ForceServerWrite, Height, UpdatingFromServer, Width } from '../../../../fields/DocSymbols';
 import { Id } from '../../../../fields/FieldSymbols';
 import { InkTool } from '../../../../fields/InkField';
 import { List } from '../../../../fields/List';
@@ -25,11 +26,10 @@ import { BoolCast, Cast, DocCast, FieldValue, NumCast, ScriptCast, StrCast } fro
 import { GetEffectiveAcl, TraceMobx } from '../../../../fields/util';
 import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, emptyFunction, numberRange, returnFalse, returnZero, setupMoveUpEvents, smoothScroll, unimplementedFunction, Utils } from '../../../../Utils';
 import { GoogleApiClientUtils, Pulls, Pushes } from '../../../apis/google_docs/GoogleApiClientUtils';
-import { gptAPICall, GPTCallType, gptImageCall } from '../../../apis/gpt/GPT';
+import { gptAPICall, GPTCallType } from '../../../apis/gpt/GPT';
 import { DocServer } from '../../../DocServer';
 import { Docs, DocUtils } from '../../../documents/Documents';
-import { CollectionViewType, DocumentType } from '../../../documents/DocumentTypes';
-import { Networking } from '../../../Network';
+import { CollectionViewType } from '../../../documents/DocumentTypes';
 import { DictationManager } from '../../../util/DictationManager';
 import { DocumentManager } from '../../../util/DocumentManager';
 import { DragManager } from '../../../util/DragManager';
@@ -49,6 +49,7 @@ import { DocumentButtonBar } from '../../DocumentButtonBar';
 import { Colors } from '../../global/globalEnums';
 import { LightboxView } from '../../LightboxView';
 import { AnchorMenu } from '../../pdf/AnchorMenu';
+import { GPTPopup } from '../../pdf/GPTPopup/GPTPopup';
 import { SidebarAnnos } from '../../SidebarAnnos';
 import { StyleProp } from '../../StyleProvider';
 import { DocFocusOptions, DocumentView, DocumentViewInternal, OpenWhere } from '../DocumentView';
@@ -70,8 +71,6 @@ import { schema } from './schema_rts';
 import { SummaryView } from './SummaryView';
 import applyDevTools = require('prosemirror-dev-tools');
 import React = require('react');
-import { GPTPopup, GPTPopupMode } from '../../pdf/GPTPopup/GPTPopup';
-import { BsMarkdownFill } from 'react-icons/bs';
 const translateGoogleApi = require('translate-google-api');
 export const GoogleRef = 'googleDocId';
 type PullHandler = (exportState: Opt<GoogleApiClientUtils.Docs.ImportResult>, dataDoc: Doc) => void;
@@ -575,7 +574,14 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
                         draggedDoc._freeform_fitContentsToBox = true;
                         Doc.SetContainer(draggedDoc, this.rootDoc);
                         const view = this._editorView!;
-                        view.dispatch(view.state.tr.insert(view.posAtCoords({ left: de.x, top: de.y })!.pos, node));
+                        try {
+                            const pos = view.posAtCoords({ left: de.x, top: de.y })?.pos;
+                            pos && view.dispatch(view.state.tr.insert(pos, node));
+                            added = pos ? true : false; // pos will be null if you don't drop onto an actual text location
+                        } catch (e) {
+                            console.log('Drop failed', e);
+                            added = false;
+                        }
                     }
                 }
             } // otherwise, fall through to outer collection to handle drop
@@ -1119,7 +1125,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
     componentDidMount() {
         !this.props.dontSelectOnLoad && this.props.setContentView?.(this); // this tells the DocumentView that this AudioBox is the "content" of the document.  this allows the DocumentView to indirectly call getAnchor() on the AudioBox when making a link.
         this._cachedLinks = LinkManager.Links(this.Document);
-        this._disposers.breakupDictation = reaction(() => DocumentManager.Instance.RecordingEvent, this.breakupDictation);
+        this._disposers.breakupDictation = reaction(() => Doc.RecordingEvent, this.breakupDictation);
         this._disposers.layout_autoHeight = reaction(
             () => this.layout_autoHeight,
             layout_autoHeight => layout_autoHeight && this.tryUpdateScrollHeight()
diff --git a/src/client/views/nodes/generativeFill/GenerativeFill.tsx b/src/client/views/nodes/generativeFill/GenerativeFill.tsx
index 1400d0f6d..1ec6d6e3f 100644
--- a/src/client/views/nodes/generativeFill/GenerativeFill.tsx
+++ b/src/client/views/nodes/generativeFill/GenerativeFill.tsx
@@ -1,26 +1,25 @@
-import './GenerativeFill.scss';
-import React = require('react');
-import { useEffect, useRef, useState } from 'react';
-import { APISuccess, ImageUtility } from './generativeFillUtils/ImageHandler';
-import { BrushHandler } from './generativeFillUtils/BrushHandler';
-import { IconButton } from 'browndash-components';
 import { Checkbox, FormControlLabel, Slider, TextField } from '@mui/material';
-import { CursorData, ImageDimensions, Point } from './generativeFillUtils/generativeFillInterfaces';
-import { activeColor, canvasSize, eraserColor, freeformRenderSize, newCollectionSize, offsetDistanceY, offsetX } from './generativeFillUtils/generativeFillConstants';
-import { PointerHandler } from './generativeFillUtils/PointerHandler';
-import { IoMdUndo, IoMdRedo } from 'react-icons/io';
-import { MainView } from '../../MainView';
+import { IconButton } from 'browndash-components';
+import { useEffect, useRef, useState } from 'react';
+import { CgClose } from 'react-icons/cg';
+import { IoMdRedo, IoMdUndo } from 'react-icons/io';
 import { Doc, DocListCast } from '../../../../fields/Doc';
-import { Networking } from '../../../Network';
-import { Utils } from '../../../../Utils';
-import { DocUtils, Docs } from '../../../documents/Documents';
+import { List } from '../../../../fields/List';
 import { NumCast } from '../../../../fields/Types';
+import { Utils } from '../../../../Utils';
+import { Docs, DocUtils } from '../../../documents/Documents';
+import { Networking } from '../../../Network';
 import { CollectionDockingView } from '../../collections/CollectionDockingView';
 import { OpenWhereMod } from '../DocumentView';
-import Buttons from './GenerativeFillButtons';
-import { List } from '../../../../fields/List';
-import { CgClose } from 'react-icons/cg';
 import { ImageBox } from '../ImageBox';
+import './GenerativeFill.scss';
+import Buttons from './GenerativeFillButtons';
+import { BrushHandler } from './generativeFillUtils/BrushHandler';
+import { activeColor, canvasSize, eraserColor, freeformRenderSize, newCollectionSize, offsetDistanceY, offsetX } from './generativeFillUtils/generativeFillConstants';
+import { CursorData, ImageDimensions, Point } from './generativeFillUtils/generativeFillInterfaces';
+import { APISuccess, ImageUtility } from './generativeFillUtils/ImageHandler';
+import { PointerHandler } from './generativeFillUtils/PointerHandler';
+import React = require('react');
 
 enum BrushStyle {
     ADD,
diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx
index 6ff22e929..f750392f5 100644
--- a/src/client/views/nodes/trails/PresBox.tsx
+++ b/src/client/views/nodes/trails/PresBox.tsx
@@ -3,7 +3,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { Tooltip } from '@material-ui/core';
 import { action, computed, IReactionDisposer, observable, ObservableSet, reaction, runInAction } from 'mobx';
 import { observer } from 'mobx-react';
-import { Doc, DocListCast, Field, FieldResult, Opt, StrListCast } from '../../../../fields/Doc';
+import { Doc, DocListCast, FieldResult, Opt, StrListCast } from '../../../../fields/Doc';
 import { Animation } from '../../../../fields/DocSymbols';
 import { Copy, Id } from '../../../../fields/FieldSymbols';
 import { InkField } from '../../../../fields/InkField';
@@ -15,7 +15,7 @@ import { BoolCast, Cast, DocCast, NumCast, StrCast } from '../../../../fields/Ty
 import { AudioField } from '../../../../fields/URLField';
 import { emptyFunction, emptyPath, returnFalse, returnOne, setupMoveUpEvents, StopEvent } from '../../../../Utils';
 import { DocServer } from '../../../DocServer';
-import { Docs, DocUtils } from '../../../documents/Documents';
+import { Docs } from '../../../documents/Documents';
 import { CollectionViewType, DocumentType } from '../../../documents/DocumentTypes';
 import { DocumentManager } from '../../../util/DocumentManager';
 import { ScriptingGlobals } from '../../../util/ScriptingGlobals';
diff --git a/src/client/views/pdf/AnchorMenu.tsx b/src/client/views/pdf/AnchorMenu.tsx
index b0924888a..6a8b06377 100644
--- a/src/client/views/pdf/AnchorMenu.tsx
+++ b/src/client/views/pdf/AnchorMenu.tsx
@@ -1,23 +1,20 @@
 import React = require('react');
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { Tooltip } from '@material-ui/core';
+import { ColorPicker, Group, IconButton, Popup, Size, Toggle, ToggleType, Type } from 'browndash-components';
 import { action, computed, IReactionDisposer, observable, ObservableMap, reaction } from 'mobx';
 import { observer } from 'mobx-react';
+import { EditorView } from 'prosemirror-view';
 import { ColorState } from 'react-color';
 import { Doc, Opt } from '../../../fields/Doc';
+import { StrCast } from '../../../fields/Types';
 import { returnFalse, setupMoveUpEvents, unimplementedFunction, Utils } from '../../../Utils';
+import { gptAPICall, GPTCallType } from '../../apis/gpt/GPT';
+import { DocumentType } from '../../documents/DocumentTypes';
 import { SelectionManager } from '../../util/SelectionManager';
 import { AntimodeMenu, AntimodeMenuProps } from '../AntimodeMenu';
 import { LinkPopup } from '../linking/LinkPopup';
-import { ButtonDropdown } from '../nodes/formattedText/RichTextMenu';
-import { gptAPICall, GPTCallType } from '../../apis/gpt/GPT';
-import { GPTPopup, GPTPopupMode } from './GPTPopup/GPTPopup';
-import { LightboxView } from '../LightboxView';
-import { EditorView } from 'prosemirror-view';
 import './AnchorMenu.scss';
-import { ColorPicker, Group, IconButton, Popup, Size, Toggle, ToggleType, Type } from 'browndash-components';
-import { StrCast } from '../../../fields/Types';
-import { DocumentType } from '../../documents/DocumentTypes';
+import { GPTPopup, GPTPopupMode } from './GPTPopup/GPTPopup';
 
 @observer
 export class AnchorMenu extends AntimodeMenu<AntimodeMenuProps> {
diff --git a/src/client/views/search/IconBar.tsx b/src/client/views/search/IconBar.tsx
index 6103b245c..540c1b5e1 100644
--- a/src/client/views/search/IconBar.tsx
+++ b/src/client/views/search/IconBar.tsx
@@ -1,17 +1,15 @@
 import { action, observable } from 'mobx';
 import { observer } from 'mobx-react';
 import * as React from 'react';
-import { DocumentType } from "../../documents/DocumentTypes";
-// import "./SearchBox.scss";
-import "./IconBar.scss";
+import { DocumentType } from '../../documents/DocumentTypes';
+import './IconBar.scss';
 import { IconButton } from './IconButton';
-import "./IconButton.scss";
+import './IconButton.scss';
 
 export interface IconBarProps {
     setIcons: (icons: string[]) => void;
 }
 
-
 @observer
 export class IconBar extends React.Component<IconBarProps> {
     public _allIcons: string[] = [DocumentType.AUDIO, DocumentType.COL, DocumentType.IMG, DocumentType.LINK, DocumentType.PDF, DocumentType.RTF, DocumentType.VID, DocumentType.WEB, DocumentType.MAP];
@@ -32,7 +30,9 @@ export class IconBar extends React.Component<IconBarProps> {
     }
 
     @action.bound
-    getIcons(): string[] { return this._icons; }
+    getIcons(): string[] {
+        return this._icons;
+    }
 
     constructor(props: any) {
         super(props);
@@ -40,29 +40,33 @@ export class IconBar extends React.Component<IconBarProps> {
     }
 
     @action.bound
-    getList(): string[] { return this.getIcons(); }
+    getList(): string[] {
+        return this.getIcons();
+    }
 
     @action.bound
-    updateList(newList: string[]) { this.updateIcon(newList); }
+    updateList(newList: string[]) {
+        this.updateIcon(newList);
+    }
 
     @action.bound
     resetSelf = () => {
         this._resetClicked = true;
         this.updateList([]);
-    }
+    };
 
     @action.bound
     selectAll = () => {
         this._selectAllClicked = true;
         this.updateList(this._allIcons);
-    }
+    };
 
     render() {
         return (
             <div className="icon-bar">
-                {this._allIcons.map((type: string) =>
+                {this._allIcons.map((type: string) => (
                     <IconButton key={type.toString()} type={type} />
-                )}
+                ))}
             </div>
         );
     }
diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx
index 1ceea697a..6b6b0f2ff 100644
--- a/src/client/views/search/SearchBox.tsx
+++ b/src/client/views/search/SearchBox.tsx
@@ -19,6 +19,7 @@ import { fetchRecommendations } from '../newlightbox/utils';
 import { IRecommendation, Recommendation } from '../newlightbox/components';
 import { Colors } from '../global/globalEnums';
 import { SettingsManager } from '../../util/SettingsManager';
+import { SearchUtil } from '../../util/SearchUtil';
 
 const DAMPENING_FACTOR = 0.9;
 const MAX_ITERATIONS = 25;
@@ -128,34 +129,6 @@ export class SearchBox extends ViewBoxBaseComponent<SearchBoxProps>() {
         }
     });
 
-    /**
-     * @param {Doc[]} docs - docs to be searched through recursively
-     * @param {number, Doc => void} func - function to be called on each doc
-     *
-     * This method iterates through an array of docs and all docs within those docs, calling
-     * the function func on each doc.
-     */
-    static foreachRecursiveDoc(docs: Doc[], func: (depth: number, doc: Doc) => void) {
-        let newarray: Doc[] = [];
-        var depth = 0;
-        const visited: Doc[] = [];
-        while (docs.length > 0) {
-            newarray = [];
-            docs.filter(d => d && !visited.includes(d)).forEach(d => {
-                visited.push(d);
-                const fieldKey = Doc.LayoutFieldKey(d);
-                const annos = !Field.toString(Doc.LayoutField(d) as Field).includes('CollectionView');
-                const data = d[annos ? fieldKey + '_annotations' : fieldKey];
-                data && newarray.push(...DocListCast(data));
-                const sidebar = d[fieldKey + '_sidebar'];
-                sidebar && newarray.push(...DocListCast(sidebar));
-                func(depth, d);
-            });
-            docs = newarray;
-            depth++;
-        }
-    }
-
     /**
      * @param {Doc[]} docs - docs to be searched through recursively
      * @param {number, Doc => void} func - function to be called on each doc
@@ -213,74 +186,10 @@ export class SearchBox extends ViewBoxBaseComponent<SearchBoxProps>() {
     @action
     searchCollection(query: string) {
         this._selectedResult = undefined;
-        this._results = SearchBox.staticSearchCollection(CollectionDockingView.Instance?.rootDoc, query);
+        this._results = SearchUtil.SearchCollection(CollectionDockingView.Instance?.rootDoc, query);
 
         this.computePageRanks();
     }
-    @action
-    static staticSearchCollection(rootDoc: Opt<Doc>, query: string) {
-        const blockedTypes = [DocumentType.PRESELEMENT, DocumentType.CONFIG, DocumentType.KVP, DocumentType.SEARCH, DocumentType.FONTICON, DocumentType.BUTTON, DocumentType.SCRIPTING];
-        const blockedKeys = [
-            'x',
-            'y',
-            'proto',
-            'width',
-            'layout_autoHeight',
-            'acl-Override',
-            'acl-Guest',
-            'embedContainer',
-            'zIndex',
-            'height',
-            'text_scrollHeight',
-            'text_height',
-            'cloneFieldFilter',
-            'isDataDoc',
-            'text_annotations',
-            'dragFactory_count',
-            'text_noTemplate',
-            'proto_embeddings',
-            'isSystem',
-            'layout_fieldKey',
-            'isBaseProto',
-            'xMargin',
-            'yMargin',
-            'links',
-            'layout',
-            'layout_keyValue',
-            'layout_fitWidth',
-            'type_collection',
-            'title_custom',
-            'freeform_panX',
-            'freeform_panY',
-            'freeform_scale',
-        ];
-        query = query.toLowerCase();
-
-        const results = new Map<Doc, string[]>();
-        if (rootDoc) {
-            const docs = DocListCast(rootDoc[Doc.LayoutFieldKey(rootDoc)]);
-            const docIDs: String[] = [];
-            SearchBox.foreachRecursiveDoc(docs, (depth: number, doc: Doc) => {
-                const dtype = StrCast(doc.type) as DocumentType;
-                if (dtype && !blockedTypes.includes(dtype) && !docIDs.includes(doc[Id]) && depth >= 0) {
-                    const hlights = new Set<string>();
-                    SearchBox.documentKeys(doc).forEach(
-                        key =>
-                            Field.toString(doc[key] as Field)
-                                .toLowerCase()
-                                .includes(query) && hlights.add(key)
-                    );
-                    blockedKeys.forEach(key => hlights.delete(key));
-
-                    if (Array.from(hlights.keys()).length > 0) {
-                        results.set(doc, Array.from(hlights.keys()));
-                    }
-                }
-                docIDs.push(doc[Id]);
-            });
-        }
-        return results;
-    }
 
     /**
      * This method initializes the page rank of every document to the reciprocal
@@ -373,17 +282,6 @@ export class SearchBox extends ViewBoxBaseComponent<SearchBoxProps>() {
         }
     }
 
-    /**
-     * @param {Doc} doc - doc for which keys are returned
-     *
-     * This method returns a list of a document doc's keys.
-     */
-    static documentKeys(doc: Doc) {
-        const keys: { [key: string]: boolean } = {};
-        Doc.GetAllPrototypes(doc).map(proto => Object.keys(proto).forEach(key => (keys[key] = false)));
-        return Array.from(Object.keys(keys));
-    }
-
     /**
      * This method submits a search with the _searchString as its query and updates
      * the results array accordingly.
@@ -518,7 +416,7 @@ export class SearchBox extends ViewBoxBaseComponent<SearchBoxProps>() {
                             className={className}>
                             <div className="searchBox-result-title">{title as string}</div>
                             <div className="searchBox-result-type">{formattedType}</div>
-                            <div className="searchBox-result-keys" style={{ color: SettingsManager.Instance.userVariantColor }}>
+                            <div className="searchBox-result-keys" style={{ color: SettingsManager.userVariantColor }}>
                                 {result[1].join(', ')}
                             </div>
                         </div>
@@ -530,7 +428,7 @@ export class SearchBox extends ViewBoxBaseComponent<SearchBoxProps>() {
         const recommendationsJSX: JSX.Element[] = this._recommendations.map(props => <Recommendation {...props} />);
 
         return (
-            <div className="searchBox-container" style={{ pointerEvents: 'all', color: SettingsManager.Instance.userColor, background: SettingsManager.Instance.userBackgroundColor }}>
+            <div className="searchBox-container" style={{ pointerEvents: 'all', color: SettingsManager.userColor, background: SettingsManager.userBackgroundColor }}>
                 <div className="searchBox-bar">
                     {isLinkSearch ? null : (
                         <select name="type" id="searchBox-type" className="searchBox-type" onChange={this.onSelectChange}>
diff --git a/src/client/views/topbar/TopBar.tsx b/src/client/views/topbar/TopBar.tsx
index c194ede32..a2f9de9ab 100644
--- a/src/client/views/topbar/TopBar.tsx
+++ b/src/client/views/topbar/TopBar.tsx
@@ -1,13 +1,14 @@
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { Button, IconButton, Size, Type, isDark } from 'browndash-components';
+import { Button, IconButton, isDark, Size, Type } from 'browndash-components';
 import { action, computed, observable, reaction } from 'mobx';
 import { observer } from 'mobx-react';
 import * as React from 'react';
-import { FaBug, FaCamera, FaStamp } from 'react-icons/fa';
+import { FaBug, FaCamera } from 'react-icons/fa';
 import { Doc, DocListCast } from '../../../fields/Doc';
 import { AclAdmin, DashVersion } from '../../../fields/DocSymbols';
 import { StrCast } from '../../../fields/Types';
 import { GetEffectiveAcl } from '../../../fields/util';
+import { CurrentUserUtils } from '../../util/CurrentUserUtils';
 import { DocumentManager } from '../../util/DocumentManager';
 import { PingManager } from '../../util/PingManager';
 import { ReportManager } from '../../util/reportManager/ReportManager';
@@ -15,13 +16,12 @@ import { ServerStats } from '../../util/ServerStats';
 import { SettingsManager } from '../../util/SettingsManager';
 import { SharingManager } from '../../util/SharingManager';
 import { UndoManager } from '../../util/UndoManager';
+import { CollectionDockingView } from '../collections/CollectionDockingView';
 import { ContextMenu } from '../ContextMenu';
 import { DashboardView } from '../DashboardView';
-import { MainView } from '../MainView';
-import { CollectionDockingView } from '../collections/CollectionDockingView';
 import { Colors } from '../global/globalEnums';
+import { DocumentView } from '../nodes/DocumentView';
 import './TopBar.scss';
-import { CurrentUserUtils } from '../../util/CurrentUserUtils';
 
 /**
  * ABOUT: This is the topbar in Dash, which included the current Dashboard as well as access to information on the user
@@ -43,7 +43,7 @@ export class TopBar extends React.Component {
         return StrCast(Doc.UserDoc().userVariantColor, Colors.MEDIUM_BLUE);
     }
     @computed get backgroundColor() {
-        return PingManager.Instance.IsBeating ? SettingsManager.Instance.userBackgroundColor : Colors.MEDIUM_GRAY;
+        return PingManager.Instance.IsBeating ? SettingsManager.userBackgroundColor : Colors.MEDIUM_GRAY;
     }
 
     @observable happyHeart: boolean = PingManager.Instance.IsBeating;
@@ -76,9 +76,7 @@ export class TopBar extends React.Component {
                         <span style={{ color: isDark(this.backgroundColor) ? Colors.LIGHT_BLUE : Colors.MEDIUM_BLUE, fontWeight: 500 }}>dash</span>
                     </div>
                 )}
-                {Doc.ActiveDashboard && (
-                    <Button text="Explore" tooltip="Browsing mode for directly navigating to documents" size={Size.SMALL} color={this.color} onClick={action(() => (MainView.Instance._exploreMode = !MainView.Instance._exploreMode))} />
-                )}
+                {Doc.ActiveDashboard && <Button text="Explore" tooltip="Browsing mode for directly navigating to documents" size={Size.SMALL} color={this.color} onClick={action(() => (DocumentView.ExploreMode = !DocumentView.ExploreMode))} />}
             </div>
         );
     }
diff --git a/src/client/views/webcam/DashWebRTCVideo.tsx b/src/client/views/webcam/DashWebRTCVideo.tsx
index 02e44a793..524492226 100644
--- a/src/client/views/webcam/DashWebRTCVideo.tsx
+++ b/src/client/views/webcam/DashWebRTCVideo.tsx
@@ -6,8 +6,8 @@ import { observer } from 'mobx-react';
 import { Doc } from '../../../fields/Doc';
 import { InkTool } from '../../../fields/InkField';
 import '../../views/nodes/WebBox.scss';
-import { DocumentDecorations } from '../DocumentDecorations';
 import { CollectionFreeFormDocumentViewProps } from '../nodes/CollectionFreeFormDocumentView';
+import { DocumentView } from '../nodes/DocumentView';
 import { FieldView, FieldViewProps } from '../nodes/FieldView';
 import './DashWebRTCVideo.scss';
 import { hangup, initialize, refreshVideos } from './WebCamLogic';
@@ -71,8 +71,8 @@ export class DashWebRTCVideo extends React.Component<CollectionFreeFormDocumentV
             </div>
         );
 
-        const frozen = !this.props.isSelected() || DocumentDecorations.Instance.Interacting;
-        const classname = 'webBox-cont' + (this.props.isSelected() && Doc.ActiveTool === InkTool.None && !DocumentDecorations.Instance.Interacting ? '-interactive' : '');
+        const frozen = !this.props.isSelected() || DocumentView.Interacting;
+        const classname = 'webBox-cont' + (this.props.isSelected() && Doc.ActiveTool === InkTool.None && !DocumentView.Interacting ? '-interactive' : '');
 
         return (
             <>
diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts
index 4ad38e7fc..f17e10d9e 100644
--- a/src/fields/Doc.ts
+++ b/src/fields/Doc.ts
@@ -47,7 +47,7 @@ import { FieldId, RefField } from './RefField';
 import { RichTextField } from './RichTextField';
 import { listSpec } from './Schema';
 import { ComputedField, ScriptField } from './ScriptField';
-import { Cast, DocCast, FieldValue, NumCast, StrCast, ToConstructor } from './Types';
+import { BoolCast, Cast, DocCast, FieldValue, NumCast, StrCast, ToConstructor } from './Types';
 import { AudioField, CsvField, ImageField, PdfField, VideoField, WebField } from './URLField';
 import { containedFieldChangedHandler, deleteProperty, GetEffectiveAcl, getField, getter, makeEditable, makeReadOnly, normalizeEmail, setter, SharingPermissions } from './util';
 import JSZip = require('jszip');
@@ -156,7 +156,26 @@ export function updateCachedAcls(doc: Doc) {
 @scriptingGlobal
 @Deserializable('Doc', updateCachedAcls, ['id'])
 export class Doc extends RefField {
-    @observable public static CurrentlyLoading: Doc[];
+    @observable public static RecordingEvent = 0;
+
+    // this isn't really used at the moment, but is intended to indicate whether ink stroke are passed through a gesture recognizer
+    static GetRecognizeGestures() {
+        return BoolCast(Doc.UserDoc()._recognizeGestures);
+    }
+    static SetRecognizeGestures(show: boolean) {
+        Doc.UserDoc()._recognizeGestures = show;
+    }
+
+    //
+    // This controls whether fontIconButtons will display labels under their icons or not
+    //
+    static GetShowIconLabels() {
+        return BoolCast(Doc.UserDoc()._showLabel);
+    }
+    static SetShowIconLabels(show: boolean) {
+        Doc.UserDoc()._showLabel = show;
+    }
+    @observable public static CurrentlyLoading: Doc[] = []; // this assignment doesn't work. the actual assignment happens in DocumentManager's constructor
     // removes from currently loading display
     @action
     public static removeCurrentlyLoading(doc: Doc) {
@@ -169,9 +188,6 @@ export class Doc extends RefField {
     // adds doc to currently loading display
     @action
     public static addCurrentlyLoading(doc: Doc) {
-        if (!Doc.CurrentlyLoading) {
-            Doc.CurrentlyLoading = [];
-        }
         if (Doc.CurrentlyLoading.indexOf(doc) === -1) {
             Doc.CurrentlyLoading.push(doc);
         }
diff --git a/src/fields/RichTextUtils.ts b/src/fields/RichTextUtils.ts
index 24cd078f2..5ecf25e08 100644
--- a/src/fields/RichTextUtils.ts
+++ b/src/fields/RichTextUtils.ts
@@ -2,20 +2,20 @@ import { AssertionError } from 'assert';
 import { docs_v1 } from 'googleapis';
 import { Fragment, Mark, Node } from 'prosemirror-model';
 import { sinkListItem } from 'prosemirror-schema-list';
-import { Utils, DashColor } from '../Utils';
-import { Docs, DocUtils } from '../client/documents/Documents';
-import { schema } from '../client/views/nodes/formattedText/schema_rts';
+import { EditorState, TextSelection, Transaction } from 'prosemirror-state';
+import { GoogleApiClientUtils } from '../client/apis/google_docs/GoogleApiClientUtils';
 import { GooglePhotos } from '../client/apis/google_docs/GooglePhotosClientUtils';
 import { DocServer } from '../client/DocServer';
+import { Docs, DocUtils } from '../client/documents/Documents';
 import { Networking } from '../client/Network';
 import { FormattedTextBox } from '../client/views/nodes/formattedText/FormattedTextBox';
+import { schema } from '../client/views/nodes/formattedText/schema_rts';
+import { DashColor, Utils } from '../Utils';
 import { Doc, Opt } from './Doc';
 import { Id } from './FieldSymbols';
 import { RichTextField } from './RichTextField';
 import { Cast, StrCast } from './Types';
 import Color = require('color');
-import { EditorState, TextSelection, Transaction } from 'prosemirror-state';
-import { GoogleApiClientUtils } from '../client/apis/google_docs/GoogleApiClientUtils';
 
 export namespace RichTextUtils {
     const delimiter = '\n';
-- 
cgit v1.2.3-70-g09d2


From f82baffbe4269deb257604a8203e10d727ff0a1b Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Mon, 28 Aug 2023 02:55:30 -0400
Subject: trying to fix more colors

---
 package-lock.json                                  | 154 ++++++++-------------
 package.json                                       |   2 +-
 src/Utils.ts                                       |   4 +-
 src/client/views/MainView.scss                     |   4 +-
 .../views/PropertiesDocBacklinksSelector.tsx       |   3 +-
 src/client/views/PropertiesView.tsx                |  30 +++-
 src/client/views/UndoStack.tsx                     |  12 +-
 .../collectionLinear/CollectionLinearView.scss     |   2 +-
 .../collectionLinear/CollectionLinearView.tsx      |   6 +-
 src/client/views/linking/LinkMenu.scss             |   1 -
 src/client/views/linking/LinkMenu.tsx              |   3 +-
 src/client/views/linking/LinkMenuGroup.tsx         |   4 +-
 src/client/views/linking/LinkMenuItem.scss         |  24 +---
 src/client/views/linking/LinkMenuItem.tsx          |  12 +-
 .../views/nodes/DataVizBox/components/PieChart.tsx |  16 +--
 src/client/views/nodes/FontIconBox/FontIconBox.tsx |  54 +++++---
 src/client/views/nodes/LinkDocPreview.scss         |   2 -
 src/client/views/topbar/TopBar.tsx                 |   3 +-
 18 files changed, 156 insertions(+), 180 deletions(-)

(limited to 'src/client/views/nodes/FontIconBox/FontIconBox.tsx')

diff --git a/package-lock.json b/package-lock.json
index 250ac5f8b..0199d3d31 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1455,9 +1455,9 @@
             }
         },
         "@babel/plugin-transform-optional-chaining": {
-            "version": "7.22.11",
-            "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.22.11.tgz",
-            "integrity": "sha512-7X2vGqH2ZKu7Imx0C+o5OysRwtF/wzdCAqmcD1N1v2Ww8CtOSC+p+VoV76skm47DLvBZ8kBFic+egqxM9S/p4g==",
+            "version": "7.22.12",
+            "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.22.12.tgz",
+            "integrity": "sha512-7XXCVqZtyFWqjDsYDY4T45w4mlx1rf7aOgkc/Ww76xkgBiOlmjPkx36PBLHa1k1rwWvVgYMPsbuVnIamx2ZQJw==",
             "requires": {
                 "@babel/helper-plugin-utils": "^7.22.5",
                 "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5",
@@ -6537,9 +6537,9 @@
             }
         },
         "browndash-components": {
-            "version": "0.0.98",
-            "resolved": "https://registry.npmjs.org/browndash-components/-/browndash-components-0.0.98.tgz",
-            "integrity": "sha512-g69eW7TJGYo7w3foy68ebZ3A9+2vk2MExIEIV1pH/rWupm6nriZaP64tOOnmOd96oD8Efrb0KT5D3xQeVlfnjw==",
+            "version": "0.1.2",
+            "resolved": "https://registry.npmjs.org/browndash-components/-/browndash-components-0.1.2.tgz",
+            "integrity": "sha512-5ONrqd6qYYMjWuayhhdwU4tlrtr+7c0n9MAMXg4jccdd9OxnmdlWpjPzOBYl3slE+mSpKcycwKarwYND+eM0NA==",
             "requires": {
                 "@emotion/react": "^11.11.1",
                 "@emotion/styled": "^11.11.0",
@@ -7094,97 +7094,12 @@
                                         "strip-ansi": "^7.0.1"
                                     }
                                 },
-                                "string-width-cjs": {
-                                    "version": "npm:string-width@4.2.3",
-                                    "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
-                                    "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
-                                    "requires": {
-                                        "emoji-regex": "^8.0.0",
-                                        "is-fullwidth-code-point": "^3.0.0",
-                                        "strip-ansi": "^6.0.1"
-                                    },
-                                    "dependencies": {
-                                        "ansi-regex": {
-                                            "version": "5.0.1",
-                                            "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
-                                            "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="
-                                        },
-                                        "emoji-regex": {
-                                            "version": "8.0.0",
-                                            "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
-                                            "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
-                                        },
-                                        "strip-ansi": {
-                                            "version": "6.0.1",
-                                            "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
-                                            "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
-                                            "requires": {
-                                                "ansi-regex": "^5.0.1"
-                                            }
-                                        }
-                                    }
-                                },
                                 "strip-ansi": {
                                     "version": "7.1.0",
                                     "bundled": true,
                                     "requires": {
                                         "ansi-regex": "^6.0.1"
                                     }
-                                },
-                                "strip-ansi-cjs": {
-                                    "version": "npm:strip-ansi@6.0.1",
-                                    "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
-                                    "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
-                                    "requires": {
-                                        "ansi-regex": "^5.0.1"
-                                    },
-                                    "dependencies": {
-                                        "ansi-regex": {
-                                            "version": "5.0.1",
-                                            "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
-                                            "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="
-                                        }
-                                    }
-                                },
-                                "wrap-ansi-cjs": {
-                                    "version": "npm:wrap-ansi@7.0.0",
-                                    "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
-                                    "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
-                                    "requires": {
-                                        "ansi-styles": "^4.0.0",
-                                        "string-width": "^4.1.0",
-                                        "strip-ansi": "^6.0.0"
-                                    },
-                                    "dependencies": {
-                                        "ansi-regex": {
-                                            "version": "5.0.1",
-                                            "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
-                                            "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="
-                                        },
-                                        "emoji-regex": {
-                                            "version": "8.0.0",
-                                            "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
-                                            "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
-                                        },
-                                        "string-width": {
-                                            "version": "4.2.3",
-                                            "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
-                                            "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
-                                            "requires": {
-                                                "emoji-regex": "^8.0.0",
-                                                "is-fullwidth-code-point": "^3.0.0",
-                                                "strip-ansi": "^6.0.1"
-                                            }
-                                        },
-                                        "strip-ansi": {
-                                            "version": "6.0.1",
-                                            "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
-                                            "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
-                                            "requires": {
-                                                "ansi-regex": "^5.0.1"
-                                            }
-                                        }
-                                    }
                                 }
                             }
                         },
@@ -8689,7 +8604,7 @@
                             }
                         },
                         "string-width-cjs": {
-                            "version": "npm:string-width-cjs@4.2.3",
+                            "version": "npm:string-width@4.2.3",
                             "bundled": true,
                             "requires": {
                                 "emoji-regex": "^8.0.0",
@@ -8712,7 +8627,7 @@
                             }
                         },
                         "strip-ansi-cjs": {
-                            "version": "npm:strip-ansi-cjs@6.0.1",
+                            "version": "npm:strip-ansi@6.0.1",
                             "bundled": true,
                             "requires": {
                                 "ansi-regex": "^5.0.1"
@@ -8871,7 +8786,7 @@
                             }
                         },
                         "wrap-ansi-cjs": {
-                            "version": "npm:wrap-ansi-cjs@7.0.0",
+                            "version": "npm:wrap-ansi@7.0.0",
                             "bundled": true,
                             "requires": {
                                 "ansi-styles": "^4.0.0",
@@ -10081,14 +9996,14 @@
                     }
                 },
                 "caniuse-lite": {
-                    "version": "1.0.30001522",
-                    "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001522.tgz",
-                    "integrity": "sha512-TKiyTVZxJGhsTszLuzb+6vUZSjVOAhClszBr2Ta2k9IwtNBT/4dzmL6aywt0HCgEZlmwJzXJd8yNiob6HgwTRg=="
+                    "version": "1.0.30001524",
+                    "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001524.tgz",
+                    "integrity": "sha512-Jj917pJtYg9HSJBF95HVX3Cdr89JUyLT4IZ8SvM5aDRni95swKgYi3TgYLH5hnGfPE/U1dg6IfZ50UsIlLkwSA=="
                 },
                 "electron-to-chromium": {
-                    "version": "1.4.501",
-                    "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.501.tgz",
-                    "integrity": "sha512-NCF5hZUg73MEP0guvIM+BjPs9W07UeAuc5XCNqRZZTKJxLjE0ZS/Zo5UsV8bbs2y/jeKRPFPzdWdBfOGEZTXKg=="
+                    "version": "1.4.503",
+                    "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.503.tgz",
+                    "integrity": "sha512-LF2IQit4B0VrUHFeQkWhZm97KuJSGF2WJqq1InpY+ECpFRkXd8yTIaTtJxsO0OKDmiBYwWqcrNaXOurn2T2wiA=="
                 }
             }
         },
@@ -10445,6 +10360,16 @@
             "integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=",
             "dev": true
         },
+        "d": {
+            "version": "1.0.1",
+            "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz",
+            "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==",
+            "dev": true,
+            "requires": {
+                "es5-ext": "^0.10.50",
+                "type": "^1.0.1"
+            }
+        },
         "d3": {
             "version": "7.8.4",
             "resolved": "https://registry.npmjs.org/d3/-/d3-7.8.4.tgz",
@@ -11825,6 +11750,28 @@
                 "is-symbol": "^1.0.2"
             }
         },
+        "es5-ext": {
+            "version": "0.10.62",
+            "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.62.tgz",
+            "integrity": "sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA==",
+            "dev": true,
+            "requires": {
+                "es6-iterator": "^2.0.3",
+                "es6-symbol": "^3.1.3",
+                "next-tick": "^1.1.0"
+            }
+        },
+        "es6-iterator": {
+            "version": "2.0.3",
+            "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz",
+            "integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==",
+            "dev": true,
+            "requires": {
+                "d": "1",
+                "es5-ext": "^0.10.35",
+                "es6-symbol": "^3.1.1"
+            }
+        },
         "es6-promise": {
             "version": "3.2.1",
             "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.2.1.tgz",
@@ -11836,6 +11783,7 @@
             "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==",
             "dev": true,
             "requires": {
+                "d": "^1.0.1",
                 "ext": "^1.1.2"
             }
         },
@@ -27648,6 +27596,12 @@
             "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
             "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q="
         },
+        "type": {
+            "version": "1.2.0",
+            "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz",
+            "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==",
+            "dev": true
+        },
         "type-check": {
             "version": "0.4.0",
             "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
diff --git a/package.json b/package.json
index 576c95192..918c0633f 100644
--- a/package.json
+++ b/package.json
@@ -178,7 +178,7 @@
         "body-parser": "^1.19.2",
         "bootstrap": "^4.6.1",
         "brotli": "^1.3.3",
-        "browndash-components": "^0.0.98",
+        "browndash-components": "^0.1.02",
         "browser-assert": "^1.2.1",
         "bson": "^4.6.1",
         "canvas": "^2.9.3",
diff --git a/src/Utils.ts b/src/Utils.ts
index 9a94694a2..29824ba94 100644
--- a/src/Utils.ts
+++ b/src/Utils.ts
@@ -758,8 +758,8 @@ export function DashColor(color: string) {
 }
 
 export function lightOrDark(color: any) {
-    if (color === 'transparent') return 'gray';
-    if (color.startsWith?.('linear')) return 'black';
+    if (color === 'transparent') return Colors.DARK_GRAY;
+    if (color.startsWith?.('linear')) return Colors.BLACK;
     const nonAlphaColor = color.startsWith('#') ? (color as string).substring(0, 7) : color.startsWith('rgba') ? color.replace(/,.[^,]*\)/, ')').replace('rgba', 'rgb') : color;
     const col = DashColor(nonAlphaColor).rgb();
     const colsum = col.red() + col.green() + col.blue();
diff --git a/src/client/views/MainView.scss b/src/client/views/MainView.scss
index 8a7f5132b..c880dde9a 100644
--- a/src/client/views/MainView.scss
+++ b/src/client/views/MainView.scss
@@ -78,7 +78,7 @@ h1,
 .mainView-container-Dark {
     .lm_header .lm_tab {
         padding: 0px;
-        opacity: 0.7;
+        //opacity: 0.7;
         box-shadow: none;
         height: 25px;
         border-bottom: black solid;
@@ -194,7 +194,7 @@ h1,
         left: 0;
         position: absolute;
         z-index: 2;
-     //   background-color: linen; //$light-gray;
+        //   background-color: linen; //$light-gray;
 
         // .editable-title {
         //     background-color: linen; //$light-gray;
diff --git a/src/client/views/PropertiesDocBacklinksSelector.tsx b/src/client/views/PropertiesDocBacklinksSelector.tsx
index da4438481..91a7b3da3 100644
--- a/src/client/views/PropertiesDocBacklinksSelector.tsx
+++ b/src/client/views/PropertiesDocBacklinksSelector.tsx
@@ -5,6 +5,7 @@ import { Cast } from '../../fields/Types';
 import { DocumentType } from '../documents/DocumentTypes';
 import { LinkManager } from '../util/LinkManager';
 import { SelectionManager } from '../util/SelectionManager';
+import { SettingsManager } from '../util/SettingsManager';
 import { LinkMenu } from './linking/LinkMenu';
 import { OpenWhere, OpenWhereMod } from './nodes/DocumentView';
 import './PropertiesDocBacklinksSelector.scss';
@@ -31,7 +32,7 @@ export class PropertiesDocBacklinksSelector extends React.Component<PropertiesDo
 
     render() {
         return !SelectionManager.Views().length ? null : (
-            <div className="propertiesDocBacklinksSelector">
+            <div className="propertiesDocBacklinksSelector" style={{ color: SettingsManager.userColor, backgroundColor: SettingsManager.userBackgroundColor }}>
                 {this.props.hideTitle ? null : <p key="contexts">Contexts:</p>}
                 <LinkMenu docView={SelectionManager.Views().lastElement()} clearLinkEditor={undefined} itemHandler={this.getOnClick} style={{ left: 0, top: 0 }} />
             </div>
diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx
index 83bd1b860..5f9439cbc 100644
--- a/src/client/views/PropertiesView.tsx
+++ b/src/client/views/PropertiesView.tsx
@@ -673,7 +673,14 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                     marginLeft: title === '∠:' ? '39px' : '',
                 }}>
                 <div className="inputBox-title"> {title} </div>
-                <input className="inputBox-input" type="text" value={value} onChange={e => setter(e.target.value)} onKeyPress={e => e.stopPropagation()} />
+                <input
+                    className="inputBox-input"
+                    type="text"
+                    value={value}
+                    style={{ color: SettingsManager.userColor, backgroundColor: SettingsManager.userBackgroundColor }}
+                    onChange={e => setter(e.target.value)}
+                    onKeyPress={e => e.stopPropagation()}
+                />
                 <div className="inputBox-button">
                     <div className="inputBox-button-up" key="up2" onPointerDown={undoBatch(action(() => this.upDownButtons('up', key)))}>
                         <FontAwesomeIcon icon="caret-up" size="sm" />
@@ -930,7 +937,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
     regInput = (key: string, value: any, setter: (val: string) => {}) => {
         return (
             <div className="inputBox">
-                <input className="inputBox-input" type="text" value={value} onChange={e => setter(e.target.value)} />
+                <input className="inputBox-input" type="text" value={value} style={{ color: SettingsManager.userColor, backgroundColor: SettingsManager.userBackgroundColor }} onChange={e => setter(e.target.value)} />
                 <div className="inputBox-button">
                     <div className="inputBox-button-up" key="up2" onPointerDown={undoBatch(action(() => this.upDownButtons('up', key)))}>
                         <FontAwesomeIcon icon="caret-up" size="sm" />
@@ -966,6 +973,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                     <input
                         className="width-range"
                         type="range"
+                        style={{ color: SettingsManager.userColor, backgroundColor: SettingsManager.userBackgroundColor }}
                         defaultValue={Number(this.widthStk)}
                         min={1}
                         max={100}
@@ -990,6 +998,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                             className="width-range"
                             type="range"
                             defaultValue={this.markScal}
+                            style={{ color: SettingsManager.userColor, backgroundColor: SettingsManager.userBackgroundColor }}
                             min={0}
                             max={10}
                             onChange={action(e => (this.markScal = +e.target.value))}
@@ -1369,6 +1378,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
     get editRelationship() {
         return (
             <input
+                style={{ color: SettingsManager.userColor, backgroundColor: SettingsManager.userBackgroundColor }}
                 autoComplete={'off'}
                 id="link_relationship_input"
                 value={StrCast(LinkManager.currentLink?.link_relationship)}
@@ -1386,7 +1396,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
         return (
             <textarea
                 autoComplete="off"
-                style={{ textAlign: 'left' }}
+                style={{ textAlign: 'left', color: SettingsManager.userColor, backgroundColor: SettingsManager.userBackgroundColor }}
                 id="link_description_input"
                 value={StrCast(LinkManager.currentLink?.link_description)}
                 onKeyDown={this.onDescriptionKey}
@@ -1414,7 +1424,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
 
         return (
             <>
-                <div className="propertiesView-section" style={{ background: 'darkgray' }}>
+                <div className="propertiesView-section">
                     <div className="propertiesView-input first" style={{ display: 'grid', gridTemplateColumns: '84px auto' }}>
                         <p>Relationship</p>
                         {this.editRelationship}
@@ -1458,7 +1468,10 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                     <div className="propertiesView-section">
                         <div className="propertiesView-input inline first" style={{ display: 'grid', gridTemplateColumns: '84px calc(100% - 84px)' }}>
                             <p>Follow by</p>
-                            <select onChange={e => this.changeFollowBehavior(e.currentTarget.value === 'Default' ? undefined : e.currentTarget.value)} value={Cast(this.sourceAnchor?.followLinkLocation, 'string', null)}>
+                            <select
+                                style={{ color: SettingsManager.userColor, backgroundColor: SettingsManager.userBackgroundColor }}
+                                onChange={e => this.changeFollowBehavior(e.currentTarget.value === 'Default' ? undefined : e.currentTarget.value)}
+                                value={Cast(this.sourceAnchor?.followLinkLocation, 'string', null)}>
                                 <option value={undefined}>Default</option>
                                 <option value={OpenWhere.addLeft}>Opening in new left pane</option>
                                 <option value={OpenWhere.addRight}>Opening in new right pane</option>
@@ -1473,7 +1486,10 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                         </div>
                         <div className="propertiesView-input inline first" style={{ display: 'grid', gridTemplateColumns: '84px calc(100% - 134px) 50px' }}>
                             <p>Animation</p>
-                            <select style={{ width: '100%', gridColumn: 2 }} onChange={e => this.changeAnimationBehavior(e.currentTarget.value)} value={StrCast(this.sourceAnchor?.followLinkAnimEffect, 'default')}>
+                            <select
+                                style={{ width: '100%', gridColumn: 2, color: SettingsManager.userColor, backgroundColor: SettingsManager.userBackgroundColor }}
+                                onChange={e => this.changeAnimationBehavior(e.currentTarget.value)}
+                                value={StrCast(this.sourceAnchor?.followLinkAnimEffect, 'default')}>
                                 <option value="default">Default</option>
                                 {[PresEffect.None, PresEffect.Zoom, PresEffect.Lightspeed, PresEffect.Fade, PresEffect.Flip, PresEffect.Rotate, PresEffect.Bounce, PresEffect.Roll].map(effect => (
                                     <option key={effect.toString()} value={effect.toString()}>
@@ -1588,7 +1604,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                         <div className="propertiesView-input inline" style={{ display: 'grid', gridTemplateColumns: '78px calc(100% - 108px) 50px' }}>
                             <p>Zoom %</p>
                             <div className="ribbon-property" style={{ display: !targZoom ? 'none' : 'inline-flex' }}>
-                                <input className="presBox-input" style={{ width: '100%' }} readOnly={true} type="number" value={zoom} />
+                                <input className="presBox-input" style={{ width: '100%', color: SettingsManager.userColor, backgroundColor: SettingsManager.userBackgroundColor }} readOnly={true} type="number" value={zoom} />
                                 <div className="ribbon-propertyUpDown" style={{ display: 'flex', flexDirection: 'column' }}>
                                     <div className="ribbon-propertyUpDownItem" onClick={undoBatch(() => this.setZoom(String(zoom), 0.1))}>
                                         <FontAwesomeIcon icon={'caret-up'} />
diff --git a/src/client/views/UndoStack.tsx b/src/client/views/UndoStack.tsx
index 3fd64d1fd..4f971742b 100644
--- a/src/client/views/UndoStack.tsx
+++ b/src/client/views/UndoStack.tsx
@@ -19,12 +19,14 @@ export class UndoStack extends React.Component<UndoStackProps> {
     @observable static HideInline: boolean;
     @observable static Expand: boolean;
     render() {
-        const background = UndoManager.batchCounter.get() ? 'yellow' : SettingsManager.userBackgroundColor;
+        const background = UndoManager.batchCounter.get() ? 'yellow' : SettingsManager.userVariantColor;
+        const color = UndoManager.batchCounter.get() ? 'black' : SettingsManager.userColor;
         return this.props.inline && UndoStack.HideInline ? null : (
             <div className="undoStack-outerContainer">
                 <Popup
                     text={'Undo/Redo Stack'}
-                    color={UndoManager.batchCounter.get() ? 'yellow' : StrCast(Doc.UserDoc().userVariantColor)}
+                    color={color}
+                    background={background}
                     placement={`top-start`}
                     type={Type.TERT}
                     popup={
@@ -32,8 +34,8 @@ export class UndoStack extends React.Component<UndoStackProps> {
                             className="undoStack-commandsContainer"
                             ref={r => r?.scroll({ behavior: 'auto', top: r?.scrollHeight + 20 })}
                             style={{
-                                background: background,
-                                color: isDark(background) ? Colors.LIGHT_GRAY : Colors.DARK_GRAY,
+                                background,
+                                color,
                             }}>
                             {UndoManager.undoStackNames.map((name, i) => (
                                 <div className="undoStack-resultContainer" key={i}>
@@ -44,7 +46,7 @@ export class UndoStack extends React.Component<UndoStackProps> {
                                 .reverse()
                                 .map((name, i) => (
                                     <div className="undoStack-resultContainer" key={i}>
-                                        <div className="undoStack-commandString" style={{ fontWeight: 'bold', color: 'red' }}>
+                                        <div className="undoStack-commandString" style={{ fontWeight: 'bold', color: SettingsManager.userBackgroundColor }}>
                                             {name.replace(/[^\.]*\./, '')}
                                         </div>
                                     </div>
diff --git a/src/client/views/collections/collectionLinear/CollectionLinearView.scss b/src/client/views/collections/collectionLinear/CollectionLinearView.scss
index 6b3318bf3..d0c14a21d 100644
--- a/src/client/views/collections/collectionLinear/CollectionLinearView.scss
+++ b/src/client/views/collections/collectionLinear/CollectionLinearView.scss
@@ -17,7 +17,7 @@
     .collectionLinearView-menuOpener {
         user-select: none;
     }
-    
+
     > input:not(:checked) ~ &.true {
         background-color: transparent;
     }
diff --git a/src/client/views/collections/collectionLinear/CollectionLinearView.tsx b/src/client/views/collections/collectionLinear/CollectionLinearView.tsx
index 2254b2e5f..4bb5c5adf 100644
--- a/src/client/views/collections/collectionLinear/CollectionLinearView.tsx
+++ b/src/client/views/collections/collectionLinear/CollectionLinearView.tsx
@@ -22,6 +22,7 @@ import { CollectionSubView } from '../CollectionSubView';
 import './CollectionLinearView.scss';
 import { Button, Toggle, ToggleType, Type } from 'browndash-components';
 import { Colors } from '../../global/globalEnums';
+import { SettingsManager } from '../../../util/SettingsManager';
 
 /**
  * CollectionLinearView is the class for rendering the horizontal collection
@@ -205,9 +206,10 @@ export class CollectionLinearView extends CollectionSubView() {
         const menuOpener = (
             <Toggle
                 text={Cast(this.props.Document.icon, 'string', null)}
-                icon={Cast(this.props.Document.icon, 'string', null) ? undefined : <FontAwesomeIcon icon={isExpanded ? 'minus' : 'plus'} />}
+                icon={Cast(this.props.Document.icon, 'string', null) ? undefined : <FontAwesomeIcon color={SettingsManager.userColor} icon={isExpanded ? 'minus' : 'plus'} />}
+                color={SettingsManager.userColor}
+                background={SettingsManager.userVariantColor}
                 type={Type.TERT}
-                color={StrCast(Doc.UserDoc().userVariantColor, Colors.MEDIUM_BLUE)}
                 onPointerDown={e => e.stopPropagation()}
                 toggleType={ToggleType.BUTTON}
                 toggleStatus={BoolCast(this.layoutDoc.linearView_IsOpen)}
diff --git a/src/client/views/linking/LinkMenu.scss b/src/client/views/linking/LinkMenu.scss
index 80cf93ed8..0b9f32eee 100644
--- a/src/client/views/linking/LinkMenu.scss
+++ b/src/client/views/linking/LinkMenu.scss
@@ -12,7 +12,6 @@
         position: relative;
         border: 1px solid #e4e4e4;
         box-shadow: 0 10px 20px rgba(0, 0, 0, 0.19), 0 6px 6px rgba(0, 0, 0, 0.23);
-        background: white;
         max-height: 230px;
         overflow-y: scroll;
         z-index: 10;
diff --git a/src/client/views/linking/LinkMenu.tsx b/src/client/views/linking/LinkMenu.tsx
index 65d13a6c3..9dc133e28 100644
--- a/src/client/views/linking/LinkMenu.tsx
+++ b/src/client/views/linking/LinkMenu.tsx
@@ -7,6 +7,7 @@ import { LinkDocPreview } from '../nodes/LinkDocPreview';
 import './LinkMenu.scss';
 import { LinkMenuGroup } from './LinkMenuGroup';
 import React = require('react');
+import { SettingsManager } from '../../util/SettingsManager';
 
 interface Props {
     docView: DocumentView;
@@ -58,7 +59,7 @@ export class LinkMenu extends React.Component<Props> {
         const style = this.props.style ?? (dv => ({ left: dv?.left || 0, top: this.props.docView.topMost ? undefined : (dv?.bottom || 0) + 15, bottom: this.props.docView.topMost ? 20 : undefined, maxWidth: 200 }))(this.props.docView.getBounds());
 
         return (
-            <div className="linkMenu" ref={this._linkMenuRef} style={{ ...style }}>
+            <div className="linkMenu" ref={this._linkMenuRef} style={{ ...style, background: SettingsManager.userBackgroundColor, color: SettingsManager.userColor }}>
                 <div className="linkMenu-list">{this.renderAllGroups(LinkManager.Instance.getRelatedGroupedLinks(sourceAnchor))}</div>
             </div>
         );
diff --git a/src/client/views/linking/LinkMenuGroup.tsx b/src/client/views/linking/LinkMenuGroup.tsx
index 8324a97d9..c1a5a634c 100644
--- a/src/client/views/linking/LinkMenuGroup.tsx
+++ b/src/client/views/linking/LinkMenuGroup.tsx
@@ -23,10 +23,10 @@ interface LinkMenuGroupProps {
 export class LinkMenuGroup extends React.Component<LinkMenuGroupProps> {
     private _menuRef = React.createRef<HTMLDivElement>();
 
-    getBackgroundColor = (): string => {
+    getBackgroundColor = (): string | undefined => {
         const link_relationshipList = StrListCast(Doc.UserDoc().link_relationshipList);
         const linkColorList = StrListCast(Doc.UserDoc().link_ColorList);
-        let color = 'white';
+        let color: string | undefined;
         // if this link's relationship property is not default "link", set its color
         if (link_relationshipList) {
             const relationshipIndex = link_relationshipList.indexOf(this.props.groupType);
diff --git a/src/client/views/linking/LinkMenuItem.scss b/src/client/views/linking/LinkMenuItem.scss
index 806a2c381..e83f631a1 100644
--- a/src/client/views/linking/LinkMenuItem.scss
+++ b/src/client/views/linking/LinkMenuItem.scss
@@ -12,8 +12,6 @@
     padding-top: 1px;
     padding-bottom: 1px;
 
-    background-color: white;
-
     .linkMenu-name {
         position: relative;
         width: auto;
@@ -25,7 +23,7 @@
 
             .linkMenu-source-title {
                 text-decoration: none;
-                color: rgb(43, 43, 43);
+                //color: rgb(43, 43, 43);
                 font-size: 7px;
                 padding-bottom: 0.75px;
 
@@ -48,13 +46,12 @@
                         height: 12px;
                         padding: 1px;
                         margin-right: 3px;
-                        color: rgb(161, 161, 161);
+                        // color: rgb(161, 161, 161);
                     }
                 }
 
                 .linkMenu-destination-title {
                     text-decoration: none;
-                    color: #4476f7;
                     font-size: 13px;
                     line-height: 0.9;
                     padding-bottom: 2px;
@@ -64,7 +61,6 @@
 
                     &:hover {
                         text-decoration: underline;
-                        color: rgb(60, 90, 156);
                         //display: inline;
                         text-overflow: break;
                         cursor: pointer;
@@ -75,7 +71,6 @@
             .linkMenu-description {
                 text-decoration: none;
                 font-style: italic;
-                color: rgb(95, 97, 102);
                 font-size: 9px;
                 line-height: 0.9;
                 margin-left: 20px;
@@ -97,17 +92,7 @@
         width: 100%;
     }
 
-    .link-metadata {
-        padding: 0 10px 0 16px;
-        margin-bottom: 4px;
-        color: $medium-gray;
-        font-style: italic;
-        font-size: 10.5px;
-    }
-
     &:hover {
-        background-color: rgb(201, 239, 252);
-
         .linkMenu-item-buttons {
             opacity: 1;
         }
@@ -115,7 +100,6 @@
         .linkMenu-item-content {
             .linkMenu-destination-title {
                 text-decoration: underline;
-                color: rgb(60, 90, 156);
                 //display: inline;
                 text-overflow: break;
             }
@@ -129,7 +113,7 @@
     display: flex;
     opacity: 0;
 
-    .button {
+    .linkMenu-deleteButton {
         width: 20px;
         height: 20px;
         margin: 0;
@@ -137,7 +121,7 @@
         padding-right: 6px;
         border-radius: 50%;
         pointer-events: auto;
-        background-color: $dark-gray;
+        background-color: red;
         color: $white;
         font-size: 65%;
         transition: transform 0.2s;
diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx
index a81707ea4..9bc8f5e8b 100644
--- a/src/client/views/linking/LinkMenuItem.tsx
+++ b/src/client/views/linking/LinkMenuItem.tsx
@@ -130,7 +130,7 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
     };
 
     deleteLink = (e: React.PointerEvent): void => setupMoveUpEvents(this, e, returnFalse, emptyFunction, undoBatch(action(() => LinkManager.Instance.deleteLink(this.props.linkDoc))));
-
+    @observable _hover = false;
     render() {
         const destinationIcon = Doc.toIcon(this.props.destinationDoc) as any as IconProp;
 
@@ -146,7 +146,11 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
                 : undefined;
 
         return (
-            <div className="linkMenu-item" style={{ background: LinkManager.currentLink === this.props.linkDoc ? 'lightBlue' : undefined }}>
+            <div
+                className="linkMenu-item"
+                onPointerEnter={action(e => (this._hover = true))}
+                onPointerLeave={action(e => (this._hover = false))}
+                style={{ background: /*LinkManager.currentLink !== this.props.linkDoc*/ this._hover ? SettingsManager.userVariantColor : SettingsManager.userBackgroundColor }}>
                 <div className="linkMenu-item-content expand-two">
                     <div
                         ref={this._drag}
@@ -154,7 +158,7 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
                         onPointerDown={this.onLinkButtonDown}>
                         <div className="linkMenu-item-buttons">
                             <Tooltip title={<div className="dash-tooltip">Edit Link</div>}>
-                                <div className="button" style={{ background: LinkManager.currentLink === this.props.linkDoc ? 'black' : 'gray' }} ref={this._editRef} onPointerDown={this.onEdit} onClick={e => e.stopPropagation()}>
+                                <div className="button" ref={this._editRef} onPointerDown={this.onEdit} onClick={e => e.stopPropagation()}>
                                     <FontAwesomeIcon className="fa-icon" icon="edit" size="sm" />
                                 </div>
                             </Tooltip>
@@ -193,7 +197,7 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
 
                         <div className="linkMenu-item-buttons">
                             <Tooltip title={<div className="dash-tooltip">Delete Link</div>}>
-                                <div className="button" style={{ background: 'red' }} onPointerDown={this.deleteLink} onClick={e => e.stopPropagation()}>
+                                <div className="linkMenu-deleteButton" onPointerDown={this.deleteLink} onClick={e => e.stopPropagation()}>
                                     <FontAwesomeIcon className="fa-icon" icon="trash" size="sm" />
                                 </div>
                             </Tooltip>
diff --git a/src/client/views/nodes/DataVizBox/components/PieChart.tsx b/src/client/views/nodes/DataVizBox/components/PieChart.tsx
index 4bd476bf3..561f39141 100644
--- a/src/client/views/nodes/DataVizBox/components/PieChart.tsx
+++ b/src/client/views/nodes/DataVizBox/components/PieChart.tsx
@@ -52,7 +52,6 @@ export class PieChart extends React.Component<PieChartProps> {
     // organized by specified number percentages/ratios if one column is selected and it contains numbers
     // otherwise, assume data is organized by categories
     @computed get byCategory() {
-        if (this.props.layoutDoc.dataViz_pie_asHistogram==undefined) this.props.layoutDoc.dataViz_pie_asHistogram = false;
         return !/\d/.test(this.props.records[0][this.props.axes[0]]) || this.props.layoutDoc.dataViz_pie_asHistogram;
     }
     // filters all data to just display selected data if brushed (created from an incoming link)
@@ -324,9 +323,9 @@ export class PieChart extends React.Component<PieChartProps> {
     };
 
     @action changeHistogramCheckBox = () => {
-        this.props.layoutDoc.dataViz_pie_asHistogram = !this.props.layoutDoc.dataViz_pie_asHistogram 
-        this.drawChart(this._pieChartData, this.width, this.height)
-    }
+        this.props.layoutDoc.dataViz_pie_asHistogram = !this.props.layoutDoc.dataViz_pie_asHistogram;
+        this.drawChart(this._pieChartData, this.width, this.height);
+    };
 
     render() {
         var titleAccessor: any = '';
@@ -367,13 +366,12 @@ export class PieChart extends React.Component<PieChartProps> {
                             fillWidth
                         />
                     </div>
-                    { (this.props.axes.length === 1 && /\d/.test(this.props.records[0][this.props.axes[0]]))?
-                        <div className={"asHistogram-checkBox"} style={{width: this.props.width}}>
+                    {this.props.axes.length === 1 && /\d/.test(this.props.records[0][this.props.axes[0]]) ? (
+                        <div className={'asHistogram-checkBox'} style={{ width: this.props.width }}>
                             <Checkbox color="primary" onChange={this.changeHistogramCheckBox} checked={this.props.layoutDoc.dataViz_pie_asHistogram as boolean} />
                             Organize data as histogram
-                        </div> 
-                        : null
-                    }
+                        </div>
+                    ) : null}
                     <div ref={this._piechartRef} />
                     {selected != 'none' ? (
                         <div className={'selected-data'}>
diff --git a/src/client/views/nodes/FontIconBox/FontIconBox.tsx b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
index fc66d40db..64f289cf7 100644
--- a/src/client/views/nodes/FontIconBox/FontIconBox.tsx
+++ b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
@@ -10,6 +10,7 @@ import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from '../../../../fields
 import { Utils } from '../../../../Utils';
 import { CollectionViewType, DocumentType } from '../../../documents/DocumentTypes';
 import { SelectionManager } from '../../../util/SelectionManager';
+import { SettingsManager } from '../../../util/SettingsManager';
 import { undoable, UndoManager } from '../../../util/UndoManager';
 import { ContextMenu } from '../../ContextMenu';
 import { DocComponent } from '../../DocComponent';
@@ -126,11 +127,11 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
         const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color);
         // Script for checking the outcome of the toggle
         const checkResult = Number(Number(numScript().result ?? 0).toPrecision(NumCast(this.dataDoc.numPrecision, 3)));
-        const label = !Doc.GetShowIconLabels() ? null : <div className="fontIconBox-label">{this.label}</div>;
 
         return (
             <NumberDropdown
                 color={color}
+                background={SettingsManager.userBackgroundColor}
                 numberDropdownType={type}
                 showPlusMinus={false}
                 tooltip={this.label}
@@ -154,7 +155,7 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
         return (
             <div
                 className={`menuButton ${this.type} ${active}`}
-                style={{ color: color, backgroundColor: backgroundColor, borderBottomLeftRadius: this.dropdown ? 0 : undefined }}
+                style={{ color, backgroundColor, borderBottomLeftRadius: this.dropdown ? 0 : undefined }}
                 onClick={action(() => {
                     this.rootDoc.dropDownOpen = !this.rootDoc.dropDownOpen;
                     this.noTooltip = this.rootDoc.dropDownOpen;
@@ -179,10 +180,7 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
      * Dropdown list
      */
     @computed get dropdownListButton() {
-        const active: string = StrCast(this.rootDoc.dropDownOpen);
         const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color);
-        const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor);
-
         const script = ScriptCast(this.rootDoc.script);
 
         let noviceList: string[] = [];
@@ -206,11 +204,21 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
                             text = Utils.cleanDocumentType(StrCast(selected.type) as DocumentType);
                             icon = Doc.toIcon(selected);
                         }
-                        return <Popup icon={<FontAwesomeIcon size={'1x'} icon={icon} />} text={text} type={Type.TERT} color={color} popup={<SelectedDocView selectedDocs={selectedDocs} />} fillWidth />;
+                        return (
+                            <Popup
+                                icon={<FontAwesomeIcon size={'1x'} icon={icon} />}
+                                text={text}
+                                type={Type.TERT}
+                                color={SettingsManager.userColor}
+                                background={SettingsManager.userVariantColor}
+                                popup={<SelectedDocView selectedDocs={selectedDocs} />}
+                                fillWidth
+                            />
+                        );
                     }
                 } else {
                     dropdown = false;
-                    return <Button text={`None Selected`} type={Type.TERT} color={color} fillWidth inactive />;
+                    return <Button text="None Selected" type={Type.TERT} color={SettingsManager.userColor} background={SettingsManager.userVariantColor} fillWidth inactive />;
                 }
                 noviceList = [CollectionViewType.Freeform, CollectionViewType.Schema, CollectionViewType.Stacking, CollectionViewType.NoteTaking];
             } else {
@@ -235,16 +243,19 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
             }));
 
         return (
-            <Dropdown
-                selectedVal={text}
-                setSelectedVal={undoable(val => script.script.run({ this: this.layoutDoc, self: this.rootDoc, val }), `dropdown select ${this.label}`)}
-                color={color}
-                type={isViewDropdown ? Type.TERT : Type.PRIM}
-                dropdownType={DropdownType.SELECT}
-                items={list}
-                tooltip={this.label}
-                fillWidth
-            />
+            <div style={{ color: SettingsManager.userColor, background: SettingsManager.userBackgroundColor }}>
+                <Dropdown
+                    selectedVal={text}
+                    setSelectedVal={undoable(val => script.script.run({ this: this.layoutDoc, self: this.rootDoc, val }), `dropdown select ${this.label}`)}
+                    color={SettingsManager.userColor}
+                    background={isViewDropdown ? SettingsManager.userVariantColor : SettingsManager.userBackgroundColor}
+                    type={Type.TERT}
+                    dropdownType={DropdownType.SELECT}
+                    items={list}
+                    tooltip={this.label}
+                    fillWidth
+                />
+            </div>
         );
     }
 
@@ -276,6 +287,7 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
                 selectedColor={curColor}
                 type={Type.PRIM}
                 color={color}
+                background={SettingsManager.userBackgroundColor}
                 icon={this.Icon(color)!}
                 tooltip={tooltip}
                 label={this.label}
@@ -296,6 +308,7 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
                 tooltip={`Toggle ${tooltip}`}
                 type={Type.PRIM}
                 color={color}
+                background={SettingsManager.userBackgroundColor}
                 label={this.label}
                 items={DocListCast(this.rootDoc.data).map(item => ({
                     icon: <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={StrCast(item.icon) as any} color={color} />,
@@ -330,6 +343,7 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
                 toggleStatus={toggleStatus}
                 text={buttonText}
                 color={color}
+                background={SettingsManager.userBackgroundColor}
                 icon={this.Icon(color)!}
                 label={this.label}
                 onPointerDown={() => script.script.run({ this: this.layoutDoc, self: this.rootDoc, value: !toggleStatus, _readOnly_: false })}
@@ -386,8 +400,10 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
             case ButtonType.ToggleButton:       return this.toggleButton;
             case ButtonType.ClickButton:
             case ButtonType.ToolButton: return <IconButton {...btnProps} size={Size.LARGE} color={color} />;
-            case ButtonType.TextButton: return <Button     {...btnProps} text={StrCast(this.rootDoc.buttonText)}/>;
-            case ButtonType.MenuButton: return <IconButton {...btnProps} color={color}  size={Size.LARGE} tooltipPlacement='right' onPointerDown={scriptFunc} />; 
+            case ButtonType.TextButton: return <Button     {...btnProps} color={color} 
+            background={SettingsManager.userBackgroundColor} text={StrCast(this.rootDoc.buttonText)}/>;
+            case ButtonType.MenuButton: return <IconButton {...btnProps} color={color} 
+            background={SettingsManager.userBackgroundColor}  size={Size.LARGE} tooltipPlacement='right' onPointerDown={scriptFunc} />; 
         }
         return this.defaultButton;
     }
diff --git a/src/client/views/nodes/LinkDocPreview.scss b/src/client/views/nodes/LinkDocPreview.scss
index c68e55f73..28216394d 100644
--- a/src/client/views/nodes/LinkDocPreview.scss
+++ b/src/client/views/nodes/LinkDocPreview.scss
@@ -1,7 +1,6 @@
 .linkDocPreview {
     position: absolute;
     pointer-events: all;
-    background-color: lightblue;
     border: 8px solid white;
     border-radius: 7px;
     box-shadow: 3px 3px 1.5px grey;
@@ -11,7 +10,6 @@
     cursor: pointer;
 
     .linkDocPreview-inner {
-        background-color: white;
         width: 100%;
         height: 100%;
         pointer-events: none;
diff --git a/src/client/views/topbar/TopBar.tsx b/src/client/views/topbar/TopBar.tsx
index a2f9de9ab..68446d4e7 100644
--- a/src/client/views/topbar/TopBar.tsx
+++ b/src/client/views/topbar/TopBar.tsx
@@ -142,7 +142,8 @@ export class TopBar extends React.Component {
                     <Button
                         text={GetEffectiveAcl(Doc.ActiveDashboard) === AclAdmin ? 'Share' : 'View Original'}
                         type={Type.TERT}
-                        color={this.variantColor}
+                        color={SettingsManager.userColor}
+                        background={this.variantColor}
                         onClick={() => {
                             SharingManager.Instance.open(undefined, Doc.ActiveDashboard);
                         }}
-- 
cgit v1.2.3-70-g09d2


From 627276eb1c5816ffd3575e2f97a3f36a31f825fa Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Tue, 29 Aug 2023 01:33:30 -0400
Subject: fixed toggle button background.

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

(limited to 'src/client/views/nodes/FontIconBox/FontIconBox.tsx')

diff --git a/src/client/views/nodes/FontIconBox/FontIconBox.tsx b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
index 64f289cf7..f286e5a42 100644
--- a/src/client/views/nodes/FontIconBox/FontIconBox.tsx
+++ b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
@@ -343,7 +343,7 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
                 toggleStatus={toggleStatus}
                 text={buttonText}
                 color={color}
-                background={SettingsManager.userBackgroundColor}
+                //background={SettingsManager.userBackgroundColor}
                 icon={this.Icon(color)!}
                 label={this.label}
                 onPointerDown={() => script.script.run({ this: this.layoutDoc, self: this.rootDoc, value: !toggleStatus, _readOnly_: false })}
-- 
cgit v1.2.3-70-g09d2


From 0c4f57875c8aaf599ff111a8b8122895d2addab3 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Tue, 29 Aug 2023 16:33:37 -0400
Subject: more cleanup

---
 src/client/util/CurrentUserUtils.ts                |   4 +-
 src/client/util/DragManager.ts                     |   7 +-
 src/client/views/DocComponent.tsx                  |   2 +-
 src/client/views/MainView.tsx                      |   2 +-
 src/client/views/ScriptingRepl.tsx                 |  23 +++-
 src/client/views/nodes/DocumentIcon.tsx            |   2 +
 src/client/views/nodes/FontIconBox/FontIconBox.tsx |   2 +-
 .../views/nodes/RecordingBox/RecordingBox.tsx      | 139 ++++++++++++---------
 8 files changed, 105 insertions(+), 76 deletions(-)

(limited to 'src/client/views/nodes/FontIconBox/FontIconBox.tsx')

diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index b705bde7f..51ef51508 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -715,14 +715,14 @@ export class CurrentUserUtils {
             { title: "View",    icon: "View",          toolTip: "View tools",           subMenu: CurrentUserUtils.viewTools(),   expertMode: false, toolType:CollectionViewType.Freeform, funcs: {hidden: `!SelectionManager_selectedDocType(self.toolType, self.expertMode)`, linearView_IsOpen: `SelectionManager_selectedDocType(self.toolType, self.expertMode)`} }, // Always available
             { title: "Web",     icon: "Web",           toolTip: "Web functions",        subMenu: CurrentUserUtils.webTools(),    expertMode: false, toolType:DocumentType.WEB,            funcs: {hidden: `!SelectionManager_selectedDocType(self.toolType, self.expertMode)`, linearView_IsOpen: `SelectionManager_selectedDocType(self.toolType, self.expertMode)`} }, // Only when Web is selected
             { title: "Schema",  icon: "Schema",linearBtnWidth:58,toolTip: "Schema functions",subMenu: CurrentUserUtils.schemaTools(), expertMode: false, toolType:CollectionViewType.Schema,   funcs: {hidden: `!SelectionManager_selectedDocType(self.toolType, self.expertMode)`, linearView_IsOpen: `SelectionManager_selectedDocType(self.toolType, self.expertMode)`} }, // Only when Schema is selected
-            { title: "Video",   icon: 'video',    toolTip: "Dictate",              btnType: ButtonType.ToggleButton,        expertMode: false,                                       funcs: {hidden: `getIsRecording()`},                               ignoreClick: true,             scripts: { onClick:  'return toggleRecording(_readOnly_)'}},
+            { title: "Video",   icon: 'video',         toolTip: "Dictate",              btnType: ButtonType.ToggleButton,        expertMode: false,                                       funcs: {hidden: `getIsRecording()`},                               ignoreClick: true,             scripts: { onClick:  'return toggleRecording(_readOnly_)'}},
             { title: "StopRec", icon: "stop",          toolTip: "Stop",                 btnType: ButtonType.ToggleButton,        expertMode: false,                                       funcs: {hidden: `!getIsRecording()`},                              ignoreClick: true,             scripts: { onClick: `return toggleRecording(_readOnly_)`}},
             { title: "Dropdown",                       toolTip: "Workspace Recordings", btnType: ButtonType.DropdownList,        expertMode: false,                                       funcs: {hidden: `renderDropdown()`, btnList: `getWorkspaceRecordings()`},                      ignoreClick: true,             scripts: { script: `toggleRecPlayback(value)`}},
             { title: "Play Rec",icon: "play",          toolTip: "Play recording",       btnType: ButtonType.ToggleButton,        expertMode: false,                                       funcs: {hidden: `!getIsWorkspaceRecPlaying()`},                            ignoreClick: true,             scripts: { onClick: `return playWorkspaceRec(getCurrentRecording())`}},
             { title: "Pause Rec",icon: "pause",        toolTip: "Pause recording",      btnType: ButtonType.ToggleButton,        expertMode: false,                                       funcs: {hidden: `!getIsWorkspaceRecPaused()`},                            ignoreClick: true,             scripts: { onClick: `return pauseWorkspaceRec(getCurrentRecording())`}},
             { title: "Stop Rec", icon: "stop",         toolTip: "Stop recording",       btnType: ButtonType.ToggleButton,        expertMode: false,                                       funcs: {hidden: `!getIsRecPlayback()`},                            ignoreClick: true,             scripts: { onClick: `return closeWorkspaceRec(getCurrentRecording())`}},
             { title: "Add doc", icon: "down",          toolTip: "add to doc",           btnType: ButtonType.ToggleButton,        expertMode: false,                                       funcs: {hidden: `!getIsRecPlayback()`},                            ignoreClick: true,             scripts: { onClick: `addRectoWorkspace(getCurrentRecording())`}},
-            { title: "Delete Rec", icon: "trash",    toolTip: "delete selected recording", btnType: ButtonType.ToggleButton,   expertMode: false,                                       funcs: {hidden: `!getIsRecPlayback()`},                                                         ignoreClick: true,             scripts: { onClick: `removeWorkspaceRec(getCurrentRecording())`}}
+            { title: "Delete Rec", icon: "trash",      toolTip: "delete selected recording", btnType: ButtonType.ToggleButton,   expertMode: false,                                       funcs: {hidden: `!getIsRecPlayback()`},                                                         ignoreClick: true,             scripts: { onClick: `removeWorkspaceRec(getCurrentRecording())`}}
         ];
     }
 
diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index 5a11f2dca..065f17139 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -4,7 +4,7 @@ import { Doc, Field, Opt, StrListCast } from '../../fields/Doc';
 import { List } from '../../fields/List';
 import { PrefetchProxy } from '../../fields/Proxy';
 import { ScriptField } from '../../fields/ScriptField';
-import { BoolCast, Cast, ScriptCast, StrCast } from '../../fields/Types';
+import { BoolCast, Cast, DocCast, ScriptCast, StrCast } from '../../fields/Types';
 import { emptyFunction, Utils } from '../../Utils';
 import { Docs, DocUtils } from '../documents/Documents';
 import * as globalCssVariables from '../views/global/globalCssVariables.scss';
@@ -236,8 +236,7 @@ export namespace DragManager {
         return true;
     }
 
-    export function StartDropdownDrag(eles: HTMLElement[], dragData: DocumentDragData, downX: number, downY: number, recordingIndex: number, options?: DragOptions, dropEvent?: () => any,) {
-        
+    export function StartDropdownDrag(eles: HTMLElement[], dragData: DocumentDragData, downX: number, downY: number, recordingIndex: number, options?: DragOptions, dropEvent?: () => any) {
         const addAudioTag = (dropDoc: any) => {
             dropDoc && !dropDoc.author_date && (dropDoc.author_date = new DateField());
             dropDoc instanceof Doc && DocUtils.MakeLinkToActiveAudio(() => dropDoc);
@@ -245,7 +244,7 @@ export namespace DragManager {
         };
         const finishDrag = async (e: DragCompleteEvent) => {
             Doc.UserDoc().isAddRecToDocMode = false;
-            Doc.RemFromMyOverlay(Doc.UserDoc().currentRecording);
+            Doc.RemFromMyOverlay(DocCast(Doc.UserDoc().currentRecording));
             Doc.UserDoc().currentRecording = undefined;
             Doc.UserDoc().isRecPlayback = false;
             Doc.UserDoc().isWorkspaceRecPlaying = false;
diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx
index e076e69ca..6a1efdf9c 100644
--- a/src/client/views/DocComponent.tsx
+++ b/src/client/views/DocComponent.tsx
@@ -201,7 +201,7 @@ export function ViewBoxAnnotatableComponent<P extends ViewBoxAnnotatableProps>()
                     const annoDocs = targetDataDoc[annotationKey ?? this.annotationKey] as List<Doc>;
                     if (annoDocs instanceof List) annoDocs.push(...added.filter(add => !annoDocs.includes(add)));
                     else targetDataDoc[annotationKey ?? this.annotationKey] = new List<Doc>(added);
-                    targetDataDoc[(annotationKey ?? this.annotationKey) + '_modificationDate'] = new DateField(new Date(Date.now()));
+                    targetDataDoc[(annotationKey ?? this.annotationKey) + '_modificationDate'] = new DateField();
                 }
             }
             return true;
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index dde04dcc0..01a26559c 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -902,7 +902,7 @@ export class MainView extends React.Component {
                     childFiltersByRanges={returnEmptyFilter}
                     searchFilterDocs={returnEmptyDoclist}
                 />
-                {['watching', 'recording'].includes(String(this.userDoc?.presentationMode) ?? '') ? <div style={{ border: '.5rem solid green', padding: '5px' }}>{StrCast(this.userDoc?.presentationMode)}</div> : <></>}
+                {['watching', 'recording'].includes(StrCast(this.userDoc?.presentationMode)) ? <div style={{ border: '.5rem solid green', padding: '5px' }}>{StrCast(this.userDoc?.presentationMode)}</div> : <></>}
             </div>
         );
     }
diff --git a/src/client/views/ScriptingRepl.tsx b/src/client/views/ScriptingRepl.tsx
index 2bc2d5e6b..9966dbced 100644
--- a/src/client/views/ScriptingRepl.tsx
+++ b/src/client/views/ScriptingRepl.tsx
@@ -5,6 +5,7 @@ import * as React from 'react';
 import { DocumentManager } from '../util/DocumentManager';
 import { CompileScript, Transformer, ts } from '../util/Scripting';
 import { ScriptingGlobals } from '../util/ScriptingGlobals';
+import { SettingsManager } from '../util/SettingsManager';
 import { undoable } from '../util/UndoManager';
 import { DocumentIconContainer } from './nodes/DocumentIcon';
 import { OverlayView } from './OverlayView';
@@ -245,17 +246,29 @@ export class ScriptingRepl extends React.Component {
     render() {
         return (
             <div className="scriptingRepl-outerContainer">
-                <div className="scriptingRepl-commandsContainer" ref={this.commandsRef}>
+                <div className="scriptingRepl-commandsContainer" style={{ background: SettingsManager.userBackgroundColor }} ref={this.commandsRef}>
                     {this.commands.map(({ command, result }, i) => {
                         return (
-                            <div className="scriptingRepl-resultContainer" key={i}>
-                                <div className="scriptingRepl-commandString">{command || <br />}</div>
-                                <div className="scriptingRepl-commandResult">{<ScriptingValueDisplay scrollToBottom={this.maybeScrollToBottom} value={result} />}</div>
+                            <div className="scriptingRepl-resultContainer" style={{ background: SettingsManager.userBackgroundColor }} key={i}>
+                                <div className="scriptingRepl-commandString" style={{ background: SettingsManager.userBackgroundColor }}>
+                                    {command || <br />}
+                                </div>
+                                <div className="scriptingRepl-commandResult" style={{ background: SettingsManager.userBackgroundColor }}>
+                                    {<ScriptingValueDisplay scrollToBottom={this.maybeScrollToBottom} value={result} />}
+                                </div>
                             </div>
                         );
                     })}
                 </div>
-                <input className="scriptingRepl-commandInput" onFocus={this.onFocus} onBlur={this.onBlur} value={this.commandString} onChange={this.onChange} onKeyDown={this.onKeyDown}></input>
+                <input
+                    className="scriptingRepl-commandInput"
+                    style={{ background: SettingsManager.userBackgroundColor }} //
+                    onFocus={this.onFocus}
+                    onBlur={this.onBlur}
+                    value={this.commandString}
+                    onChange={this.onChange}
+                    onKeyDown={this.onKeyDown}
+                />
             </div>
         );
     }
diff --git a/src/client/views/nodes/DocumentIcon.tsx b/src/client/views/nodes/DocumentIcon.tsx
index 6e2ed72b8..bccbd66e8 100644
--- a/src/client/views/nodes/DocumentIcon.tsx
+++ b/src/client/views/nodes/DocumentIcon.tsx
@@ -9,6 +9,7 @@ import { action, observable } from 'mobx';
 import { Id } from '../../../fields/FieldSymbols';
 import { factory } from 'typescript';
 import { LightboxView } from '../LightboxView';
+import { SettingsManager } from '../../util/SettingsManager';
 
 @observer
 export class DocumentIcon extends React.Component<{ view: DocumentView; index: number }> {
@@ -29,6 +30,7 @@ export class DocumentIcon extends React.Component<{ view: DocumentView; index: n
                     pointerEvents: 'all',
                     opacity: this._hovered ? 0.3 : 1,
                     position: 'absolute',
+                    background: SettingsManager.userBackgroundColor,
                     transform: `translate(${(left + right) / 2}px, ${top}px)`,
                 }}>
                 <Tooltip title={<>{this.props.view.rootDoc.title}</>}>
diff --git a/src/client/views/nodes/FontIconBox/FontIconBox.tsx b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
index 1cf66fbdc..bb2069cc9 100644
--- a/src/client/views/nodes/FontIconBox/FontIconBox.tsx
+++ b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
@@ -235,7 +235,7 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
         const list: IListItemProps[] = this.buttonList
             .filter(value => !Doc.noviceMode || !noviceList.length || noviceList.includes(value))
             .map(value => ({
-                text: value === "string" ? value.charAt(0).toUpperCase() + value.slice(1) : StrCast(DocCast(value)?.title),
+                text: typeof value === 'string' ? value.charAt(0).toUpperCase() + value.slice(1) : StrCast(DocCast(value)?.title),
                 val: value,
                 style: getStyle(value),
                 onClick: undoable(() => script.script.run({ this: this.layoutDoc, self: this.rootDoc, value }), value),
diff --git a/src/client/views/nodes/RecordingBox/RecordingBox.tsx b/src/client/views/nodes/RecordingBox/RecordingBox.tsx
index 8a91b8102..9dd673591 100644
--- a/src/client/views/nodes/RecordingBox/RecordingBox.tsx
+++ b/src/client/views/nodes/RecordingBox/RecordingBox.tsx
@@ -1,32 +1,27 @@
-import { action, observable, runInAction } from 'mobx';
+import { action, observable } from 'mobx';
 import { observer } from 'mobx-react';
 import * as React from 'react';
-import { VideoField } from '../../../../fields/URLField';
-import { Upload } from '../../../../server/SharedMediaTypes';
-import { ViewBoxBaseComponent } from '../../DocComponent';
-import { FieldView, FieldViewProps } from '../FieldView';
-import { VideoBox } from '../VideoBox';
-import { RecordingView } from './RecordingView';
-import { DocumentType } from '../../../documents/DocumentTypes';
-import { Presentation } from '../../../util/TrackMovements';
+import { formatTime } from '../../../../Utils';
 import { Doc, DocListCast } from '../../../../fields/Doc';
 import { Id } from '../../../../fields/FieldSymbols';
+import { listSpec } from '../../../../fields/Schema';
 import { BoolCast, Cast, DocCast } from '../../../../fields/Types';
-import { ScriptingGlobals } from '../../../util/ScriptingGlobals';
-import { DocumentManager } from '../../../util/DocumentManager';
+import { VideoField } from '../../../../fields/URLField';
+import { Upload } from '../../../../server/SharedMediaTypes';
 import { Docs } from '../../../documents/Documents';
-import { CollectionFreeFormView } from '../../collections/collectionFreeForm/CollectionFreeFormView';
-import { CurrentUserUtils } from '../../../util/CurrentUserUtils';
-import { DocumentView } from '../DocumentView';
-import { SettingsManager } from '../../../util/SettingsManager';
-import { PropertiesView } from '../../PropertiesView';
-import { PropertiesSection } from '../../PropertiesSection';
-import { PropertiesDocContextSelector } from '../../PropertiesDocContextSelector';
-import { listSpec } from '../../../../fields/Schema';
+import { DocumentType } from '../../../documents/DocumentTypes';
+import { DocumentManager } from '../../../util/DocumentManager';
 import { DragManager } from '../../../util/DragManager';
+import { ScriptingGlobals } from '../../../util/ScriptingGlobals';
 import { SelectionManager } from '../../../util/SelectionManager';
-import { AudioBox } from '../AudioBox';
-import { UndoManager, undoBatch } from '../../../util/UndoManager';
+import { Presentation } from '../../../util/TrackMovements';
+import { undoBatch } from '../../../util/UndoManager';
+import { CollectionFreeFormView } from '../../collections/collectionFreeForm/CollectionFreeFormView';
+import { ViewBoxBaseComponent } from '../../DocComponent';
+import { FieldView, FieldViewProps } from '../FieldView';
+import { VideoBox } from '../VideoBox';
+import { RecordingView } from './RecordingView';
+import { DateField } from '../../../../fields/DateField';
 
 @observer
 export class RecordingBox extends ViewBoxBaseComponent<FieldViewProps>() {
@@ -69,8 +64,8 @@ export class RecordingBox extends ViewBoxBaseComponent<FieldViewProps>() {
 
     /**
      * This method toggles whether or not we are currently using the RecordingBox to record with the topbar button
-     * @param _readOnly_ 
-     * @returns 
+     * @param _readOnly_
+     * @returns
      */
     @undoBatch
     @action
@@ -78,33 +73,33 @@ export class RecordingBox extends ViewBoxBaseComponent<FieldViewProps>() {
         if (_readOnly_) return RecordingBox.screengrabber ? true : false;
         if (RecordingBox.screengrabber) {
             //if recordingbox is true; when we press the stop button. changed vals temporarily to see if changes happening
-            console.log('grabbing screen!')
+            console.log('grabbing screen!');
             RecordingBox.screengrabber.Pause?.();
             const remDoc = RecordingBox.screengrabber.rootDoc;
             setTimeout(() => {
                 RecordingBox.screengrabber?.Finish?.();
                 RecordingBox.screengrabber!.rootDoc.overlayX = 70; //was 100
                 RecordingBox.screengrabber!.rootDoc.overlayY = 590;
-                console.log(RecordingBox.screengrabber)
+                console.log(RecordingBox.screengrabber);
                 RecordingBox.screengrabber = undefined;
             }, 100);
             //could break if recording takes too long to turn into videobox. If so, either increase time on setTimeout below or find diff place to do this
             setTimeout(() => {
                 Doc.RemFromMyOverlay(remDoc);
-    
-            }, 1000)
+            }, 1000);
             Doc.UserDoc().isRecording = false;
-            Doc.AddDocToList(Doc.UserDoc(), "workspaceRecordings", RecordingBox.screengrabber.rootDoc);
+            Doc.AddDocToList(Doc.UserDoc(), 'workspaceRecordings', RecordingBox.screengrabber.rootDoc);
         } else {
             //when we first press mic
             const screengrabber = Docs.Create.WebCamDocument('', {
+                title: `${Doc.ActiveDashboard?.title ?? ''} ${new DateField()}`,
                 _width: 205,
                 _height: 115,
             });
             screengrabber.overlayX = 70; //was -400
             screengrabber.overlayY = 590; //was 0
             screengrabber[Doc.LayoutFieldKey(screengrabber) + '_trackScreen'] = true;
-            Doc.AddToMyOverlay(screengrabber);  //just adds doc to overlay
+            Doc.AddToMyOverlay(screengrabber); //just adds doc to overlay
             DocumentManager.Instance.AddViewRenderedCb(screengrabber, docView => {
                 RecordingBox.screengrabber = docView.ComponentView as RecordingBox;
                 RecordingBox.screengrabber.Record?.();
@@ -120,21 +115,21 @@ export class RecordingBox extends ViewBoxBaseComponent<FieldViewProps>() {
     @undoBatch
     @action
     public static toggleWorkspaceRecPlayback(value: Doc) {
-        let docval = undefined;
         Doc.UserDoc().currentRecording = value;
-        console.log(value)
-        value.overlayX =70;
+        console.log(value);
+        value.overlayX = 70;
         value.overlayY = 590;
         if (!Doc.UserDoc().isAddRecToDocMode) {
             Doc.UserDoc().isRecPlayback = true;
             Doc.UserDoc().isWorkspaceRecPlaying = true;
             Doc.AddToMyOverlay(value);
             DocumentManager.Instance.AddViewRenderedCb(value, docView => {
-                Doc.UserDoc().currentRecording = docView.ComponentView as RecordingBox;
-                SelectionManager.SelectSchemaViewDoc(value);    
-        })} else {
-            let recordingIndex = Array.from(Doc.UserDoc().workspaceRecordings).indexOf(value);
-            DragManager.StartDropdownDrag([document.createElement('div')],new DragManager.DocumentDragData([value]), 1, 1, recordingIndex);
+                Doc.UserDoc().currentRecording = docView.rootDoc;
+                SelectionManager.SelectSchemaViewDoc(value);
+            });
+        } else {
+            let recordingIndex = DocListCast(Doc.UserDoc().workspaceRecordings).indexOf(value);
+            DragManager.StartDropdownDrag([document.createElement('div')], new DragManager.DocumentDragData([value]), 1, 1, recordingIndex);
         }
     }
 
@@ -145,11 +140,11 @@ export class RecordingBox extends ViewBoxBaseComponent<FieldViewProps>() {
     @undoBatch
     @action
     public static addRecToWorkspace(value: RecordingBox) {
-        console.log("adding rec to doc");
+        console.log('adding rec to doc');
         console.log(value);
-         let ffView = Array.from(DocumentManager.Instance.DocumentViews).find(view => view.ComponentView instanceof CollectionFreeFormView);
+        let ffView = Array.from(DocumentManager.Instance.DocumentViews).find(view => view.ComponentView instanceof CollectionFreeFormView);
         (ffView?.ComponentView as CollectionFreeFormView).props.addDocument?.(value.rootDoc);
-        let recordingIndex = Array.from(Doc.UserDoc().workspaceRecordings).indexOf(value.rootDoc);
+        let recordingIndex = DocListCast(Doc.UserDoc().workspaceRecordings).indexOf(value.rootDoc);
         console.log(recordingIndex);
         Cast(Doc.UserDoc().workspaceRecordings, listSpec(Doc), null)?.splice(recordingIndex, 1);
         Doc.UserDoc().isAddRecToDocMode = false;
@@ -187,13 +182,12 @@ export class RecordingBox extends ViewBoxBaseComponent<FieldViewProps>() {
         Doc.UserDoc().isWorkspaceRecPlaying = false;
         Doc.UserDoc().isWorkspaceRecPaused = false;
         Doc.RemFromMyOverlay(value.rootDoc);
-
     }
 
     @undoBatch
     @action
     public static removeWorkspaceRec(value: VideoBox) {
-        let recordingIndex = Array.from(Doc.UserDoc().workspaceRecordings).indexOf(value.rootDoc);
+        let recordingIndex = DocListCast(Doc.UserDoc().workspaceRecordings).indexOf(value.rootDoc);
         Cast(Doc.UserDoc().workspaceRecordings, listSpec(Doc), null)?.splice(recordingIndex, 1);
         Doc.UserDoc().isAddRecToDocMode = false;
         Doc.RemFromMyOverlay(value.rootDoc);
@@ -202,11 +196,8 @@ export class RecordingBox extends ViewBoxBaseComponent<FieldViewProps>() {
         Doc.UserDoc().isAddRecToDocMode = false;
         Doc.UserDoc().isWorkspaceRecPlaying = false;
         Doc.UserDoc().isWorkspaceRecPaused = false;
-
     }
 
-    
-
     Record: undefined | (() => void);
     Pause: undefined | (() => void);
     Finish: undefined | (() => void);
@@ -234,26 +225,50 @@ export class RecordingBox extends ViewBoxBaseComponent<FieldViewProps>() {
     static screengrabber: RecordingBox | undefined;
 }
 
-ScriptingGlobals.add(function toggleRecording(_readOnly_: boolean) { RecordingBox.toggleWorkspaceRecording(_readOnly_); });
-ScriptingGlobals.add(function toggleRecPlayback(value: Doc) { RecordingBox.toggleWorkspaceRecPlayback(value); });
-ScriptingGlobals.add(function addRectoWorkspace(value: RecordingBox) { RecordingBox.addRecToWorkspace(value); });
+ScriptingGlobals.add(function toggleRecording(_readOnly_: boolean) {
+    RecordingBox.toggleWorkspaceRecording(_readOnly_);
+});
+ScriptingGlobals.add(function toggleRecPlayback(value: Doc) {
+    RecordingBox.toggleWorkspaceRecPlayback(value);
+});
+ScriptingGlobals.add(function addRectoWorkspace(value: RecordingBox) {
+    RecordingBox.addRecToWorkspace(value);
+});
 
-ScriptingGlobals.add(function playWorkspaceRec(value: VideoBox) { RecordingBox.playWorkspaceRec(value); });
-ScriptingGlobals.add(function pauseWorkspaceRec(value: VideoBox) { RecordingBox.pauseWorkspaceRec(value); });
-ScriptingGlobals.add(function closeWorkspaceRec(value: VideoBox) { RecordingBox.closeWorkspaceRec(value); });
-ScriptingGlobals.add(function removeWorkspaceRec(value: VideoBox) { RecordingBox.removeWorkspaceRec(value) });
+ScriptingGlobals.add(function playWorkspaceRec(value: VideoBox) {
+    RecordingBox.playWorkspaceRec(value);
+});
+ScriptingGlobals.add(function pauseWorkspaceRec(value: VideoBox) {
+    RecordingBox.pauseWorkspaceRec(value);
+});
+ScriptingGlobals.add(function closeWorkspaceRec(value: VideoBox) {
+    RecordingBox.closeWorkspaceRec(value);
+});
+ScriptingGlobals.add(function removeWorkspaceRec(value: VideoBox) {
+    RecordingBox.removeWorkspaceRec(value);
+});
 
-ScriptingGlobals.add(function getWorkspaceRecordings() { return Doc.UserDoc().workspaceRecordings });
-ScriptingGlobals.add(function getIsRecording() { return Doc.UserDoc().isRecording; })
-ScriptingGlobals.add(function getIsRecPlayback() { return Doc.UserDoc().isRecPlayback; })
-ScriptingGlobals.add(function getCurrentRecording() { return Doc.UserDoc().currentRecording; })
-ScriptingGlobals.add(function getIsWorkspaceRecPlaying() { return Doc.UserDoc().isWorkspaceRecPlaying; })
-ScriptingGlobals.add(function getIsWorkspaceRecPaused() { return Doc.UserDoc().isWorkspaceRecPaused; })
+ScriptingGlobals.add(function getWorkspaceRecordings() {
+    return Doc.UserDoc().workspaceRecordings;
+});
+ScriptingGlobals.add(function getIsRecording() {
+    return Doc.UserDoc().isRecording;
+});
+ScriptingGlobals.add(function getIsRecPlayback() {
+    return Doc.UserDoc().isRecPlayback;
+});
+ScriptingGlobals.add(function getCurrentRecording() {
+    return Doc.UserDoc().currentRecording;
+});
+ScriptingGlobals.add(function getIsWorkspaceRecPlaying() {
+    return Doc.UserDoc().isWorkspaceRecPlaying;
+});
+ScriptingGlobals.add(function getIsWorkspaceRecPaused() {
+    return Doc.UserDoc().isWorkspaceRecPaused;
+});
 ScriptingGlobals.add(function renderDropdown() {
-    if (!Doc.UserDoc().workspaceRecordings || Array.from(Doc.UserDoc().workspaceRecordings).length === 0) {
+    if (!Doc.UserDoc().workspaceRecordings || DocListCast(Doc.UserDoc().workspaceRecordings).length === 0) {
         return true;
     }
     return false;
-})
-
-
+});
-- 
cgit v1.2.3-70-g09d2


From 7c218639c75e22e1270d4198fb940b439175deee Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Thu, 31 Aug 2023 11:50:14 -0400
Subject: reworked recording workspace UI and switched to recording window, not
 webcam

---
 src/client/util/CurrentUserUtils.ts                |  58 +++---
 src/client/util/DragManager.ts                     |   7 +-
 src/client/views/DashboardView.tsx                 |   8 +-
 .../collectionLinear/CollectionLinearView.tsx      |   4 +-
 src/client/views/nodes/DocumentView.tsx            |   2 +-
 src/client/views/nodes/FontIconBox/FontIconBox.tsx |  90 ++++-----
 .../views/nodes/RecordingBox/RecordingBox.tsx      | 215 ++++++++++-----------
 src/client/views/nodes/ScreenshotBox.tsx           |   3 +
 src/client/views/topbar/TopBar.tsx                 |  63 ++++--
 src/fields/Doc.ts                                  |   3 +
 10 files changed, 234 insertions(+), 219 deletions(-)

(limited to 'src/client/views/nodes/FontIconBox/FontIconBox.tsx')

diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 51ef51508..04f1ff0d2 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -18,6 +18,7 @@ import { CollectionViewType, DocumentType } from "../documents/DocumentTypes";
 import { TreeViewType } from "../views/collections/CollectionTreeView";
 import { DashboardView } from "../views/DashboardView";
 import { Colors } from "../views/global/globalEnums";
+import { media_state } from "../views/nodes/AudioBox";
 import { OpenWhere } from "../views/nodes/DocumentView";
 import { ButtonType } from "../views/nodes/FontIconBox/FontIconBox";
 import { ImportElementBox } from "../views/nodes/importBox/ImportElementBox";
@@ -51,7 +52,7 @@ interface Button {
 
     // fields that do not correspond to DocumentOption fields
     scripts?: { script?: string; onClick?: string; onDoubleClick?: string }
-    funcs?: { [key:string]: string };
+    funcs?: { [key:string]: any};
     subMenu?: Button[];
 }
 
@@ -591,7 +592,7 @@ export class CurrentUserUtils {
     static createToolButton = (opts: DocumentOptions) => Docs.Create.FontIconDocument({
         btnType: ButtonType.ToolButton, _forceActive: true, _layout_hideContextMenu: true, 
         _dropPropertiesToRemove: new List<string>([ "_layout_hideContextMenu"]), 
-        _nativeWidth: 40, _nativeHeight: 40, _width: 40, _height: 40, isSystem: true, ...opts,
+        /*_nativeWidth: 40, _nativeHeight: 40, */ _width: 40, _height: 40, isSystem: true, ...opts,
     })
 
     /// initializes the required buttons in the expanding button menu at the bottom of the Dash window
@@ -693,7 +694,6 @@ export class CurrentUserUtils {
             { title: "URL",     toolTip: "URL", width: 250, btnType: ButtonType.EditableText, icon: "lock", ignoreClick: true, scripts: { script: '{ return webSetURL(value, _readOnly_); }'} },
         ];
     }
-
     static contextMenuTools():Button[] {
         return [
             { btnList: new List<string>([CollectionViewType.Freeform, CollectionViewType.Schema, CollectionViewType.Tree,
@@ -701,11 +701,11 @@ export class CurrentUserUtils {
                     CollectionViewType.Multirow, CollectionViewType.Time, CollectionViewType.Carousel,
                     CollectionViewType.Carousel3D, CollectionViewType.Linear, CollectionViewType.Map,
                     CollectionViewType.Grid, CollectionViewType.NoteTaking]),
-              title: "Perspective",                    toolTip: "View",                 btnType: ButtonType.DropdownList,                                                                                                                                    ignoreClick: true, width: 100, scripts: { script: 'setView(value, _readOnly_)'}},
+              title: "Perspective",                    toolTip: "View",                 btnType: ButtonType.DropdownList,                                                                                                                                    ignoreClick: true, width: 100, scripts: { script:  'setView(value, _readOnly_)'}},
             { title: "Pin",     icon: "map-pin",       toolTip: "Pin View to Trail",    btnType: ButtonType.ClickButton,         expertMode: false,                                                                                                                             width: 30,  scripts: { onClick: 'pinWithView(altKey)'}, funcs: {hidden: "IsNoneSelected()"}},
             { title: "Fill",    icon: "fill-drip",     toolTip: "Background Fill Color",btnType: ButtonType.ColorButton,         expertMode: false,                                                                                                          ignoreClick: true, width: 30,  scripts: { script:  'return setBackgroundColor(value, _readOnly_)'}, funcs: {hidden: "IsNoneSelected()"}}, // Only when a document is selected
             { title: "Header",  icon: "heading",       toolTip: "Header Color",         btnType: ButtonType.ColorButton,         expertMode: true,                                                                                                           ignoreClick: true,             scripts: { script:  'return setHeaderColor(value, _readOnly_)'}, funcs: {hidden: "IsNoneSelected()"}},
-            { title: "Overlay", icon: "layer-group",   toolTip: "Overlay",              btnType: ButtonType.ToggleButton,        expertMode: true,  toolType:CollectionViewType.Freeform, funcs: {hidden: '!SelectionManager_selectedDocType(self.toolType, self.expertMode, true)'},       scripts: { onClick:  '{ return toggleOverlay(_readOnly_); }'}}, // Only when floating document is selected in freeform
+            { title: "Overlay", icon: "layer-group",   toolTip: "Overlay",              btnType: ButtonType.ToggleButton,        expertMode: true,  toolType:CollectionViewType.Freeform, funcs: {hidden: '!SelectionManager_selectedDocType(self.toolType, self.expertMode, true)'},       scripts: { onClick: '{ return 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: "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_)'}},
@@ -714,16 +714,8 @@ export class CurrentUserUtils {
             { title: "Doc",     icon: "Doc",           toolTip: "Freeform Doc tools",   subMenu: CurrentUserUtils.freeTools(),   expertMode: false, toolType:CollectionViewType.Freeform, funcs: {hidden: `!SelectionManager_selectedDocType(self.toolType, self.expertMode, true)`, linearView_IsOpen: `SelectionManager_selectedDocType(self.toolType, self.expertMode)`} }, // Always available
             { title: "View",    icon: "View",          toolTip: "View tools",           subMenu: CurrentUserUtils.viewTools(),   expertMode: false, toolType:CollectionViewType.Freeform, funcs: {hidden: `!SelectionManager_selectedDocType(self.toolType, self.expertMode)`, linearView_IsOpen: `SelectionManager_selectedDocType(self.toolType, self.expertMode)`} }, // Always available
             { title: "Web",     icon: "Web",           toolTip: "Web functions",        subMenu: CurrentUserUtils.webTools(),    expertMode: false, toolType:DocumentType.WEB,            funcs: {hidden: `!SelectionManager_selectedDocType(self.toolType, self.expertMode)`, linearView_IsOpen: `SelectionManager_selectedDocType(self.toolType, self.expertMode)`} }, // Only when Web is selected
-            { title: "Schema",  icon: "Schema",linearBtnWidth:58,toolTip: "Schema functions",subMenu: CurrentUserUtils.schemaTools(), expertMode: false, toolType:CollectionViewType.Schema,   funcs: {hidden: `!SelectionManager_selectedDocType(self.toolType, self.expertMode)`, linearView_IsOpen: `SelectionManager_selectedDocType(self.toolType, self.expertMode)`} }, // Only when Schema is selected
-            { title: "Video",   icon: 'video',         toolTip: "Dictate",              btnType: ButtonType.ToggleButton,        expertMode: false,                                       funcs: {hidden: `getIsRecording()`},                               ignoreClick: true,             scripts: { onClick:  'return toggleRecording(_readOnly_)'}},
-            { title: "StopRec", icon: "stop",          toolTip: "Stop",                 btnType: ButtonType.ToggleButton,        expertMode: false,                                       funcs: {hidden: `!getIsRecording()`},                              ignoreClick: true,             scripts: { onClick: `return toggleRecording(_readOnly_)`}},
-            { title: "Dropdown",                       toolTip: "Workspace Recordings", btnType: ButtonType.DropdownList,        expertMode: false,                                       funcs: {hidden: `renderDropdown()`, btnList: `getWorkspaceRecordings()`},                      ignoreClick: true,             scripts: { script: `toggleRecPlayback(value)`}},
-            { title: "Play Rec",icon: "play",          toolTip: "Play recording",       btnType: ButtonType.ToggleButton,        expertMode: false,                                       funcs: {hidden: `!getIsWorkspaceRecPlaying()`},                            ignoreClick: true,             scripts: { onClick: `return playWorkspaceRec(getCurrentRecording())`}},
-            { title: "Pause Rec",icon: "pause",        toolTip: "Pause recording",      btnType: ButtonType.ToggleButton,        expertMode: false,                                       funcs: {hidden: `!getIsWorkspaceRecPaused()`},                            ignoreClick: true,             scripts: { onClick: `return pauseWorkspaceRec(getCurrentRecording())`}},
-            { title: "Stop Rec", icon: "stop",         toolTip: "Stop recording",       btnType: ButtonType.ToggleButton,        expertMode: false,                                       funcs: {hidden: `!getIsRecPlayback()`},                            ignoreClick: true,             scripts: { onClick: `return closeWorkspaceRec(getCurrentRecording())`}},
-            { title: "Add doc", icon: "down",          toolTip: "add to doc",           btnType: ButtonType.ToggleButton,        expertMode: false,                                       funcs: {hidden: `!getIsRecPlayback()`},                            ignoreClick: true,             scripts: { onClick: `addRectoWorkspace(getCurrentRecording())`}},
-            { title: "Delete Rec", icon: "trash",      toolTip: "delete selected recording", btnType: ButtonType.ToggleButton,   expertMode: false,                                       funcs: {hidden: `!getIsRecPlayback()`},                                                         ignoreClick: true,             scripts: { onClick: `removeWorkspaceRec(getCurrentRecording())`}}
-        ];
+            { title: "Schema",  icon: "Schema",linearBtnWidth:58,toolTip: "Schema functions",subMenu: CurrentUserUtils.schemaTools(),expertMode: false,toolType:CollectionViewType.Schema,funcs: {hidden: `!SelectionManager_selectedDocType(self.toolType, self.expertMode)`, linearView_IsOpen: `SelectionManager_selectedDocType(self.toolType, self.expertMode)`} }, // Only when Schema is selected
+           ];
     }
 
     /// initializes a context menu button for the top bar context menu
@@ -749,19 +741,17 @@ export class CurrentUserUtils {
         if (Doc.UserDoc().currentRecording) {
             Doc.RemFromMyOverlay(DocCast(Doc.UserDoc().currentRecording));
         }
-        Doc.UserDoc().isRecording = false;
-        Doc.UserDoc().isRecPlayback = false;
+        Doc.UserDoc().workspaceRecordingState = undefined;
+        Doc.UserDoc().workspaceReplayingState = undefined;
         Doc.UserDoc().currentRecording = undefined;
-        Doc.UserDoc().isPlaybackPlaying = false;
-        Doc.UserDoc().isWorkspaceRecPlaying = false;
-        Doc.UserDoc().isWorkspaceRecPaused = false;
+        Doc.UserDoc().workspaceRecordingState = undefined;
         if (!subMenu) { // button does not have a sub menu
             return this.setupContextMenuButton(params, menuBtnDoc);
         }  
         // linear view
         const reqdSubMenuOpts = { ...OmitKeys(params, ["scripts", "funcs", "subMenu"]).omit, undoIgnoreFields: new List<string>(['width', "linearView_IsOpen"]),
             childDontRegisterViews: true, flexGap: 0, _height: 30, ignoreClick: params.scripts?.onClick ? false : true,
-            linearView_SubMenu: true, linearView_Expandable: params.btnType !== ButtonType.MultiToggleButton};
+            linearView_SubMenu: true, linearView_Expandable: true};
         
         const items = (menuBtnDoc?:Doc) => !menuBtnDoc ? [] : subMenu.map(sub => this.setupContextMenuBtn(sub, menuBtnDoc) );
         const creator = params.btnType === ButtonType.MultiToggleButton ? this.multiToggleList : this.linearButtonList;
@@ -773,11 +763,34 @@ export class CurrentUserUtils {
 
     /// Initializes all the default buttons for the top bar context menu
     static setupContextMenuButtons(doc: Doc, field="myContextMenuBtns") {
-        const reqdCtxtOpts:DocumentOptions = { title: "context menu buttons", undoIgnoreFields:new List<string>(['width', "linearView_IsOpen"]), flexGap: 0, childDragAction: 'embed', childDontRegisterViews: true,  linearView_IsOpen: true, ignoreClick: true, linearView_Expandable: false, _height: 35 };
+        const reqdCtxtOpts:DocumentOptions = { title: "context menu buttons", undoIgnoreFields:new List<string>(['width', "linearView_IsOpen"]), flexGap: 0, childDragAction: 'embed', childDontRegisterViews: true,  linearView_IsOpen: true, ignoreClick: true, linearView_Expandable: true, _height: 35 };
         const ctxtMenuBtnsDoc = DocUtils.AssignDocField(doc, field, (opts, items) => this.linearButtonList(opts, items??[]), reqdCtxtOpts, undefined);
         const ctxtMenuBtns = CurrentUserUtils.contextMenuTools().map(params => this.setupContextMenuBtn(params, ctxtMenuBtnsDoc) );
         return DocUtils.AssignOpts(ctxtMenuBtnsDoc, reqdCtxtOpts, ctxtMenuBtns);
     }
+    /// Initializes all the default buttons for the top bar context menu
+    static setupTopbarButtons(doc: Doc, field="myTopBarBtns") {
+        const dockedBtns = DocCast(doc[field]);
+        const dockBtn = (opts: DocumentOptions, scripts: {[key:string]:string|undefined}, funcs?: {[key:string]:any}) =>
+            DocUtils.AssignScripts(DocUtils.AssignOpts(DocListCast(dockedBtns?.data)?.find(doc => doc.title === opts.title), opts) ?? 
+                            CurrentUserUtils.createToolButton(opts), scripts, funcs);
+        
+        const btnDescs = [// setup reactions to change the highlights on the undo/redo buttons -- would be better to encode this in the undo/redo buttons, but the undo/redo stacks are not wired up that way yet
+            { opts: { title: "Replicate",icon:"camera",toolTip: "Copy dashboard layout",btnType: ButtonType.ClickButton, expertMode: true},                                                                                               scripts: { onClick:  `snapshotDashboard()`}},
+            { opts: { title: "Recordings",            toolTip: "Workspace Recordings", btnType: ButtonType.DropdownList,expertMode: false, ignoreClick: true, width: 100}, funcs: {hidden: `false`, btnList:`getWorkspaceRecordings()`}, scripts: { script:  `{ return replayWorkspace(value, _readOnly_); }`}},
+            { opts: { title: "Stop Rec",icon: "stop", toolTip: "Stop recording",       btnType: ButtonType.ClickButton, expertMode: false}, funcs: {hidden: `!isWorkspaceRecording()`},                                                  scripts: { onClick: `stopWorkspaceRecording()`}},
+            { opts: { title: "Play",    icon: "play", toolTip: "Play recording",       btnType: ButtonType.ClickButton, expertMode: false}, funcs: {hidden: `isWorkspaceReplaying() !== "${media_state.Paused}"`},                       scripts: { onClick: `resumeWorkspaceReplaying(getCurrentRecording())`}},
+            { opts: { title: "Pause",   icon: "pause",toolTip: "Pause playback",       btnType: ButtonType.ClickButton, expertMode: false}, funcs: {hidden: `isWorkspaceReplaying() !== "${media_state.Playing}"`},                      scripts: { onClick: `pauseWorkspaceReplaying(getCurrentRecording())`}},
+            { opts: { title: "Stop",    icon: "stop", toolTip: "Stop playback",        btnType: ButtonType.ClickButton, expertMode: false}, funcs: {hidden: `isWorkspaceReplaying() !== "${media_state.Paused}"`},                       scripts: { onClick: `stopWorkspaceReplaying(getCurrentRecording())`}},
+            { opts: { title: "Delete",  icon: "trash",toolTip: "delete selected rec",  btnType: ButtonType.ClickButton, expertMode: false}, funcs: {hidden: `isWorkspaceReplaying() !== "${media_state.Paused}"`},                       scripts: { onClick: `removeWorkspaceReplaying(getCurrentRecording())`}}
+        ];
+        const btns = btnDescs.map(desc => dockBtn({_width: desc.opts.width??30, _height: 30, defaultDoubleClick: 'ignore', undoIgnoreFields: new List<string>(['opacity']), _dragOnlyWithinContainer: true, ...desc.opts}, desc.scripts, desc.funcs));
+        const dockBtnsReqdOpts:DocumentOptions = {
+            title: "docked buttons", _height: 40, flexGap: 0, layout_boxShadow: "standard", childDragAction: 'move',
+            childDontRegisterViews: true, linearView_IsOpen: true, linearView_Expandable: true, ignoreClick: true
+        };
+        return DocUtils.AssignDocField(doc, field, (opts, items) => this.linearButtonList(opts, items??[]), dockBtnsReqdOpts, btns);
+    }
 
     /// collection of documents rendered in the overlay layer above all tabs and other UI
     static setupOverlays(doc: Doc, field = "myOverlayDocs") {
@@ -891,6 +904,7 @@ export class CurrentUserUtils {
         this.setupOverlays(doc);  // sets up the overlay panel where documents and other widgets can be added to float over the rest of the dashboard
         this.setupPublished(doc);  // sets up the list doc of all docs that have been published (meaning that they can be auto-linked by typing their title into another text box)
         this.setupContextMenuButtons(doc); // set up the row of buttons at the top of the dashboard that change depending on what is selected
+        this.setupTopbarButtons(doc);
         this.setupDockedButtons(doc);  // the bottom bar of font icons
         this.setupLeftSidebarMenu(doc); // the left-side column of buttons that open their contents in a flyout panel on the left
         this.setupDocTemplates(doc); // sets up the template menu of templates
diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index 065f17139..6c0641943 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -243,13 +243,10 @@ export namespace DragManager {
             return dropDoc;
         };
         const finishDrag = async (e: DragCompleteEvent) => {
-            Doc.UserDoc().isAddRecToDocMode = false;
             Doc.RemFromMyOverlay(DocCast(Doc.UserDoc().currentRecording));
             Doc.UserDoc().currentRecording = undefined;
-            Doc.UserDoc().isRecPlayback = false;
-            Doc.UserDoc().isWorkspaceRecPlaying = false;
-            Doc.UserDoc().isWorkspaceRecPaused = false;
-            Doc.UserDoc().isAddRecToDocMode = false;
+            Doc.UserDoc().isWorkspaceReplaying = false;
+            Doc.UserDoc().workspaceRecordingState = undefined;
             Cast(Doc.UserDoc().workspaceRecordings, listSpec(Doc), null)?.splice(recordingIndex, 1);
             const docDragData = e.docDragData;
             dropEvent?.(); // glr: optional additional function to be called - in this case with presentation trails
diff --git a/src/client/views/DashboardView.tsx b/src/client/views/DashboardView.tsx
index 4387c6e96..3ef6c0814 100644
--- a/src/client/views/DashboardView.tsx
+++ b/src/client/views/DashboardView.tsx
@@ -18,7 +18,7 @@ import { CollectionViewType } from '../documents/DocumentTypes';
 import { HistoryUtil } from '../util/History';
 import { ScriptingGlobals } from '../util/ScriptingGlobals';
 import { SharingManager } from '../util/SharingManager';
-import { undoBatch } from '../util/UndoManager';
+import { undoBatch, UndoManager } from '../util/UndoManager';
 import { CollectionDockingView } from './collections/CollectionDockingView';
 import { CollectionView } from './collections/CollectionView';
 import { ContextMenu } from './ContextMenu';
@@ -493,6 +493,8 @@ ScriptingGlobals.add(function resetDashboard(dashboard: Doc) {
 ScriptingGlobals.add(function addToDashboards(dashboard: Doc) {
     DashboardView.openDashboard(Doc.MakeEmbedding(dashboard));
 }, 'adds Dashboard to set of Dashboards');
-ScriptingGlobals.add(function snapshotDashboard() {
-    DashboardView.snapshotDashboard();
+ScriptingGlobals.add(async function snapshotDashboard() {
+    const batch = UndoManager.StartBatch('snapshot');
+    await DashboardView.snapshotDashboard();
+    batch.end();
 }, 'creates a snapshot copy of a dashboard');
diff --git a/src/client/views/collections/collectionLinear/CollectionLinearView.tsx b/src/client/views/collections/collectionLinear/CollectionLinearView.tsx
index 3481d5130..0cf7d4411 100644
--- a/src/client/views/collections/collectionLinear/CollectionLinearView.tsx
+++ b/src/client/views/collections/collectionLinear/CollectionLinearView.tsx
@@ -229,8 +229,8 @@ export class CollectionLinearView extends CollectionSubView() {
                 <div className="collectionLinearView" ref={this.createDashEventsTarget} onContextMenu={this.myContextMenu} style={{ minHeight: this.dimension(), pointerEvents: 'all' }}>
                     {
                         <>
-                            {menuOpener}
-                            {!this.layoutDoc.linearView_IsOpen ? null : (
+                            {!this.layoutDoc.linearView_Expandable ? null :menuOpener}
+                            {!this.layoutDoc.linearView_IsOpen && !this.layoutDoc.linearView_alwaysOpen ? null : (
                                 <div
                                     className="collectionLinearView-content"
                                     style={{
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 8a0706c30..998024cea 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -798,7 +798,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
             !more && moreItems.length && cm.addItem({ description: 'More...', subitems: moreItems, icon: 'compass' });
         }
         const constantItems: ContextMenuProps[] = [];
-        if (!Doc.IsSystem(this.rootDoc)) {
+        if (!Doc.IsSystem(this.rootDoc) && this.rootDoc._type_collection !== CollectionViewType.Docking) {
             constantItems.push({ description: 'Zip Export', icon: 'download', event: async () => Doc.Zip(this.props.Document) });
             (this.rootDoc._type_collection !== CollectionViewType.Docking || !Doc.noviceMode) && constantItems.push({ description: 'Share', event: () => SharingManager.Instance.open(this.props.DocumentView()), icon: 'users' });
             if (this.props.removeDocument && Doc.ActiveDashboard !== this.props.Document) {
diff --git a/src/client/views/nodes/FontIconBox/FontIconBox.tsx b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
index bb2069cc9..8ef9cd792 100644
--- a/src/client/views/nodes/FontIconBox/FontIconBox.tsx
+++ b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
@@ -180,55 +180,45 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
      * Dropdown list
      */
     @computed get dropdownListButton() {
-        const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color);
         const script = ScriptCast(this.rootDoc.script);
 
         let noviceList: string[] = [];
         let text: string | undefined;
-        let dropdown = true;
         let getStyle: (val: string) => any = () => {};
         let icon: IconProp = 'caret-down';
-        let isViewDropdown: boolean = script?.script.originalScript.startsWith('setView');
-        try {
-            if (isViewDropdown) {
-                const selectedDocs: Doc[] = SelectionManager.Docs();
-                const selected = SelectionManager.Docs().lastElement();
-                if (selected) {
-                    if (StrCast(selected.type) === DocumentType.COL) {
-                        text = StrCast(selected._type_collection);
+        const isViewDropdown = script?.script.originalScript.startsWith('setView');
+        if (isViewDropdown) {
+            const selected = SelectionManager.Docs();
+            if (selected.lastElement()) {
+                if (StrCast(selected.lastElement().type) === DocumentType.COL) {
+                    text = StrCast(selected.lastElement()._type_collection);
+                } else {
+                    if (selected.length > 1) {
+                        text = selected.length + ' selected';
                     } else {
-                        dropdown = false;
-                        if (selectedDocs.length > 1) {
-                            text = selectedDocs.length + ' selected';
-                        } else {
-                            text = Utils.cleanDocumentType(StrCast(selected.type) as DocumentType);
-                            icon = Doc.toIcon(selected);
-                        }
-                        return (
-                            <Popup
-                                icon={<FontAwesomeIcon size={'1x'} icon={icon} />}
-                                text={text}
-                                type={Type.TERT}
-                                color={SettingsManager.userColor}
-                                background={SettingsManager.userVariantColor}
-                                popup={<SelectedDocView selectedDocs={selectedDocs} />}
-                                fillWidth
-                            />
-                        );
+                        text = Utils.cleanDocumentType(StrCast(selected.lastElement().type) as DocumentType);
+                        icon = Doc.toIcon(selected.lastElement());
                     }
-                } else {
-                    dropdown = false;
-                    return <Button text="None Selected" type={Type.TERT} color={SettingsManager.userColor} background={SettingsManager.userVariantColor} fillWidth inactive />;
+                    return (
+                        <Popup
+                            icon={<FontAwesomeIcon size={'1x'} icon={icon} />}
+                            text={text}
+                            type={Type.TERT}
+                            color={SettingsManager.userColor}
+                            background={SettingsManager.userVariantColor}
+                            popup={<SelectedDocView selectedDocs={selected} />}
+                            fillWidth
+                        />
+                    );
                 }
-                noviceList = [CollectionViewType.Freeform, CollectionViewType.Schema, CollectionViewType.Stacking, CollectionViewType.NoteTaking];
             } else {
-                text = StrCast((RichTextMenu.Instance?.TextView?.EditorView ? RichTextMenu.Instance : Doc.UserDoc()).fontFamily);
-                getStyle = (val: string) => {
-                    return { fontFamily: val };
-                };
+                return <Button text="None Selected" type={Type.TERT} color={SettingsManager.userColor} background={SettingsManager.userVariantColor} fillWidth inactive />;
             }
-        } catch (e) {
-            console.log(e);
+            noviceList = [CollectionViewType.Freeform, CollectionViewType.Schema, CollectionViewType.Stacking, CollectionViewType.NoteTaking];
+        } else {
+            text = script?.script.run({ this: this.layoutDoc, self: this.rootDoc, value: '', _readOnly_: true }).result;
+            // text = StrCast((RichTextMenu.Instance?.TextView?.EditorView ? RichTextMenu.Instance : Doc.UserDoc()).fontFamily);
+            getStyle = (val: string) => ({ fontFamily: val });
         }
 
         // Get items to place into the list
@@ -243,19 +233,17 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
             }));
 
         return (
-            <div style={{ color: SettingsManager.userColor, background: SettingsManager.userBackgroundColor }}>
-                <Dropdown
-                    selectedVal={text}
-                    setSelectedVal={undoable(val => script.script.run({ this: this.layoutDoc, self: this.rootDoc, val }), `dropdown select ${this.label}`)}
-                    color={SettingsManager.userColor}
-                    background={isViewDropdown ? SettingsManager.userVariantColor : SettingsManager.userBackgroundColor}
-                    type={Type.TERT}
-                    dropdownType={DropdownType.SELECT}
-                    items={list}
-                    tooltip={this.label}
-                    fillWidth
-                />
-            </div>
+            <Dropdown
+                selectedVal={text ?? 'Record Workspace'}
+                setSelectedVal={undoable(val => script.script.run({ this: this.layoutDoc, self: this.rootDoc, val }), `dropdown select ${this.label}`)}
+                color={SettingsManager.userColor}
+                background={SettingsManager.userVariantColor}
+                type={Type.TERT}
+                dropdownType={DropdownType.SELECT}
+                items={list}
+                tooltip={this.label}
+                fillWidth
+            />
         );
     }
 
diff --git a/src/client/views/nodes/RecordingBox/RecordingBox.tsx b/src/client/views/nodes/RecordingBox/RecordingBox.tsx
index 9dd673591..b1b044c25 100644
--- a/src/client/views/nodes/RecordingBox/RecordingBox.tsx
+++ b/src/client/views/nodes/RecordingBox/RecordingBox.tsx
@@ -1,11 +1,10 @@
 import { action, observable } from 'mobx';
 import { observer } from 'mobx-react';
 import * as React from 'react';
-import { formatTime } from '../../../../Utils';
 import { Doc, DocListCast } from '../../../../fields/Doc';
 import { Id } from '../../../../fields/FieldSymbols';
 import { listSpec } from '../../../../fields/Schema';
-import { BoolCast, Cast, DocCast } from '../../../../fields/Types';
+import { BoolCast, Cast, DocCast, StrCast } from '../../../../fields/Types';
 import { VideoField } from '../../../../fields/URLField';
 import { Upload } from '../../../../server/SharedMediaTypes';
 import { Docs } from '../../../documents/Documents';
@@ -22,6 +21,8 @@ import { FieldView, FieldViewProps } from '../FieldView';
 import { VideoBox } from '../VideoBox';
 import { RecordingView } from './RecordingView';
 import { DateField } from '../../../../fields/DateField';
+import { media_state } from '../AudioBox';
+import { List } from '../../../../fields/List';
 
 @observer
 export class RecordingBox extends ViewBoxBaseComponent<FieldViewProps>() {
@@ -41,9 +42,7 @@ export class RecordingBox extends ViewBoxBaseComponent<FieldViewProps>() {
     @observable videoDuration: number | undefined = undefined;
 
     @action
-    setVideoDuration = (duration: number) => {
-        this.videoDuration = duration;
-    };
+    setVideoDuration = (duration: number) => (this.videoDuration = duration);
 
     @action
     setResult = (info: Upload.AccessPathInfo, presentation?: Presentation) => {
@@ -61,76 +60,68 @@ export class RecordingBox extends ViewBoxBaseComponent<FieldViewProps>() {
             this.dataDoc[this.fieldKey + '_presentation'] = JSON.stringify(presCopy);
         }
     };
-
-    /**
-     * This method toggles whether or not we are currently using the RecordingBox to record with the topbar button
-     * @param _readOnly_
-     * @returns
-     */
     @undoBatch
     @action
-    public static toggleWorkspaceRecording(_readOnly_: boolean) {
-        if (_readOnly_) return RecordingBox.screengrabber ? true : false;
-        if (RecordingBox.screengrabber) {
+    public static WorkspaceStopRecording() {
+        const remDoc = RecordingBox.screengrabber?.rootDoc;
+        if (remDoc) {
             //if recordingbox is true; when we press the stop button. changed vals temporarily to see if changes happening
-            console.log('grabbing screen!');
-            RecordingBox.screengrabber.Pause?.();
-            const remDoc = RecordingBox.screengrabber.rootDoc;
+            RecordingBox.screengrabber?.Pause?.();
             setTimeout(() => {
                 RecordingBox.screengrabber?.Finish?.();
-                RecordingBox.screengrabber!.rootDoc.overlayX = 70; //was 100
-                RecordingBox.screengrabber!.rootDoc.overlayY = 590;
-                console.log(RecordingBox.screengrabber);
+                remDoc.overlayX = 70; //was 100
+                remDoc.overlayY = 590;
                 RecordingBox.screengrabber = undefined;
             }, 100);
             //could break if recording takes too long to turn into videobox. If so, either increase time on setTimeout below or find diff place to do this
-            setTimeout(() => {
-                Doc.RemFromMyOverlay(remDoc);
-            }, 1000);
-            Doc.UserDoc().isRecording = false;
-            Doc.AddDocToList(Doc.UserDoc(), 'workspaceRecordings', RecordingBox.screengrabber.rootDoc);
-        } else {
-            //when we first press mic
-            const screengrabber = Docs.Create.WebCamDocument('', {
-                title: `${Doc.ActiveDashboard?.title ?? ''} ${new DateField()}`,
-                _width: 205,
-                _height: 115,
-            });
-            screengrabber.overlayX = 70; //was -400
-            screengrabber.overlayY = 590; //was 0
-            screengrabber[Doc.LayoutFieldKey(screengrabber) + '_trackScreen'] = true;
-            Doc.AddToMyOverlay(screengrabber); //just adds doc to overlay
-            DocumentManager.Instance.AddViewRenderedCb(screengrabber, docView => {
-                RecordingBox.screengrabber = docView.ComponentView as RecordingBox;
-                RecordingBox.screengrabber.Record?.();
-            });
-            Doc.UserDoc().isRecording = true;
+            setTimeout(() => Doc.RemFromMyOverlay(remDoc), 1000);
+            Doc.UserDoc().workspaceRecordingState = media_state.Paused;
+            Doc.AddDocToList(Doc.UserDoc(), 'workspaceRecordings', remDoc);
         }
     }
 
+    /**
+     * This method toggles whether or not we are currently using the RecordingBox to record with the topbar button
+     * @param _readOnly_
+     * @returns
+     */
+    @undoBatch
+    @action
+    public static WorkspaceStartRecording() {
+        const screengrabber = Docs.Create.ScreenshotDocument({
+            title: `${Doc.ActiveDashboard?.title ?? ''} ${new DateField()}`,
+            _width: 205,
+            _height: 115,
+        });
+        screengrabber.overlayX = 70; //was -400
+        screengrabber.overlayY = 590; //was 0
+        screengrabber[Doc.LayoutFieldKey(screengrabber) + '_trackScreen'] = true;
+        Doc.AddToMyOverlay(screengrabber); //just adds doc to overlay
+        DocumentManager.Instance.AddViewRenderedCb(screengrabber, docView => {
+            RecordingBox.screengrabber = docView.ComponentView as RecordingBox;
+            RecordingBox.screengrabber.Record?.();
+        });
+        Doc.UserDoc().workspaceRecordingState = media_state.Recording;
+    }
+
     /**
      * This method changes the menu depending on whether or not we are in playback mode
      * @param value  RecordingBox rootdoc
      */
     @undoBatch
     @action
-    public static toggleWorkspaceRecPlayback(value: Doc) {
+    public static replayWorkspace(value: Doc) {
         Doc.UserDoc().currentRecording = value;
-        console.log(value);
         value.overlayX = 70;
         value.overlayY = 590;
-        if (!Doc.UserDoc().isAddRecToDocMode) {
-            Doc.UserDoc().isRecPlayback = true;
-            Doc.UserDoc().isWorkspaceRecPlaying = true;
-            Doc.AddToMyOverlay(value);
-            DocumentManager.Instance.AddViewRenderedCb(value, docView => {
-                Doc.UserDoc().currentRecording = docView.rootDoc;
-                SelectionManager.SelectSchemaViewDoc(value);
-            });
-        } else {
-            let recordingIndex = DocListCast(Doc.UserDoc().workspaceRecordings).indexOf(value);
-            DragManager.StartDropdownDrag([document.createElement('div')], new DragManager.DocumentDragData([value]), 1, 1, recordingIndex);
-        }
+        Doc.AddToMyOverlay(value);
+        DocumentManager.Instance.AddViewRenderedCb(value, docView => {
+            Doc.UserDoc().currentRecording = docView.rootDoc;
+            SelectionManager.SelectSchemaViewDoc(value);
+            RecordingBox.resumeWorkspaceReplaying(value);
+        });
+        // let recordingIndex = DocListCast(Doc.UserDoc().workspaceRecordings).indexOf(value);
+        // DragManager.StartDropdownDrag([document.createElement('div')], new DragManager.DocumentDragData([value]), 1, 1, recordingIndex);
     }
 
     /**
@@ -140,62 +131,55 @@ export class RecordingBox extends ViewBoxBaseComponent<FieldViewProps>() {
     @undoBatch
     @action
     public static addRecToWorkspace(value: RecordingBox) {
-        console.log('adding rec to doc');
-        console.log(value);
         let ffView = Array.from(DocumentManager.Instance.DocumentViews).find(view => view.ComponentView instanceof CollectionFreeFormView);
         (ffView?.ComponentView as CollectionFreeFormView).props.addDocument?.(value.rootDoc);
-        let recordingIndex = DocListCast(Doc.UserDoc().workspaceRecordings).indexOf(value.rootDoc);
-        console.log(recordingIndex);
-        Cast(Doc.UserDoc().workspaceRecordings, listSpec(Doc), null)?.splice(recordingIndex, 1);
-        Doc.UserDoc().isAddRecToDocMode = false;
+        Doc.RemoveDocFromList(Doc.UserDoc(), 'workspaceRecordings', value.rootDoc);
         Doc.RemFromMyOverlay(value.rootDoc);
         Doc.UserDoc().currentRecording = undefined;
-        Doc.UserDoc().isRecPlayback = false;
-        Doc.UserDoc().isAddRecToDocMode = false;
-        Doc.UserDoc().isWorkspaceRecPlaying = false;
-        Doc.UserDoc().isWorkspaceRecPaused = false;
+        Doc.UserDoc().workspaceReplayingState = undefined;
+        Doc.UserDoc().workspaceRecordingState = undefined;
     }
 
     @undoBatch
     @action
-    public static playWorkspaceRec(value: VideoBox) {
-        value.Play();
-        Doc.UserDoc().isWorkspaceRecPlaying = false;
-        Doc.UserDoc().isWorkspaceRecPaused = true;
+    public static resumeWorkspaceReplaying(doc: Doc) {
+        const docView = DocumentManager.Instance.getDocumentView(doc);
+        const videoBox = docView?.ComponentView as VideoBox;
+        if (videoBox) {
+            videoBox.Play();
+            Doc.UserDoc().workspaceReplayingState = media_state.Playing;
+        }
     }
 
     @undoBatch
     @action
-    public static pauseWorkspaceRec(value: VideoBox) {
-        value.Pause();
-        Doc.UserDoc().isWorkspaceRecPlaying = true;
-        Doc.UserDoc().isWorkspaceRecPaused = false;
+    public static pauseWorkspaceReplaying(doc: Doc) {
+        const docView = DocumentManager.Instance.getDocumentView(doc);
+        const videoBox = docView?.ComponentView as VideoBox;
+        if (videoBox) {
+            videoBox.Pause();
+        }
+        Doc.UserDoc().workspaceReplayingState = media_state.Paused;
     }
 
     @undoBatch
     @action
-    public static closeWorkspaceRec(value: VideoBox) {
-        value.Pause();
-        Doc.RemFromMyOverlay(value.rootDoc);
+    public static stopWorkspaceReplaying(value: Doc) {
+        Doc.RemFromMyOverlay(value);
         Doc.UserDoc().currentRecording = undefined;
-        Doc.UserDoc().isRecPlayback = false;
-        Doc.UserDoc().isWorkspaceRecPlaying = false;
-        Doc.UserDoc().isWorkspaceRecPaused = false;
-        Doc.RemFromMyOverlay(value.rootDoc);
+        Doc.UserDoc().workspaceReplayingState = undefined;
+        Doc.UserDoc().workspaceRecordingState = undefined;
+        Doc.RemFromMyOverlay(value);
     }
 
     @undoBatch
     @action
-    public static removeWorkspaceRec(value: VideoBox) {
-        let recordingIndex = DocListCast(Doc.UserDoc().workspaceRecordings).indexOf(value.rootDoc);
-        Cast(Doc.UserDoc().workspaceRecordings, listSpec(Doc), null)?.splice(recordingIndex, 1);
-        Doc.UserDoc().isAddRecToDocMode = false;
-        Doc.RemFromMyOverlay(value.rootDoc);
+    public static removeWorkspaceReplaying(value: Doc) {
+        Doc.RemoveDocFromList(Doc.UserDoc(), 'workspaceRecordings', value);
+        Doc.RemFromMyOverlay(value);
         Doc.UserDoc().currentRecording = undefined;
-        Doc.UserDoc().isRecPlayback = false;
-        Doc.UserDoc().isAddRecToDocMode = false;
-        Doc.UserDoc().isWorkspaceRecPlaying = false;
-        Doc.UserDoc().isWorkspaceRecPaused = false;
+        Doc.UserDoc().workspaceReplayingState = undefined;
+        Doc.UserDoc().workspaceRecordingState = undefined;
     }
 
     Record: undefined | (() => void);
@@ -225,47 +209,44 @@ export class RecordingBox extends ViewBoxBaseComponent<FieldViewProps>() {
     static screengrabber: RecordingBox | undefined;
 }
 
-ScriptingGlobals.add(function toggleRecording(_readOnly_: boolean) {
-    RecordingBox.toggleWorkspaceRecording(_readOnly_);
-});
-ScriptingGlobals.add(function toggleRecPlayback(value: Doc) {
-    RecordingBox.toggleWorkspaceRecPlayback(value);
+ScriptingGlobals.add(function startWorkspaceRecording() {
+    RecordingBox.WorkspaceStartRecording();
 });
-ScriptingGlobals.add(function addRectoWorkspace(value: RecordingBox) {
-    RecordingBox.addRecToWorkspace(value);
+ScriptingGlobals.add(function stopWorkspaceRecording() {
+    RecordingBox.WorkspaceStopRecording();
 });
 
-ScriptingGlobals.add(function playWorkspaceRec(value: VideoBox) {
-    RecordingBox.playWorkspaceRec(value);
+ScriptingGlobals.add(function stopWorkspaceReplaying(value: Doc) {
+    RecordingBox.stopWorkspaceReplaying(value);
 });
-ScriptingGlobals.add(function pauseWorkspaceRec(value: VideoBox) {
-    RecordingBox.pauseWorkspaceRec(value);
-});
-ScriptingGlobals.add(function closeWorkspaceRec(value: VideoBox) {
-    RecordingBox.closeWorkspaceRec(value);
-});
-ScriptingGlobals.add(function removeWorkspaceRec(value: VideoBox) {
-    RecordingBox.removeWorkspaceRec(value);
+ScriptingGlobals.add(function removeWorkspaceReplaying(value: Doc) {
+    RecordingBox.removeWorkspaceReplaying(value);
 });
 
+ScriptingGlobals.add(function getCurrentRecording() {
+    return Doc.UserDoc().currentRecording;
+});
 ScriptingGlobals.add(function getWorkspaceRecordings() {
-    return Doc.UserDoc().workspaceRecordings;
+    return new List<any>(['Record Workspace', ...DocListCast(Doc.UserDoc().workspaceRecordings)]);
 });
-ScriptingGlobals.add(function getIsRecording() {
-    return Doc.UserDoc().isRecording;
+ScriptingGlobals.add(function isWorkspaceRecording() {
+    return Doc.UserDoc().workspaceRecordingState === media_state.Recording;
 });
-ScriptingGlobals.add(function getIsRecPlayback() {
-    return Doc.UserDoc().isRecPlayback;
+ScriptingGlobals.add(function isWorkspaceReplaying() {
+    return Doc.UserDoc().workspaceReplayingState;
 });
-ScriptingGlobals.add(function getCurrentRecording() {
-    return Doc.UserDoc().currentRecording;
+ScriptingGlobals.add(function replayWorkspace(value: Doc | string, _readOnly_: boolean) {
+    if (_readOnly_) return DocCast(Doc.UserDoc().currentRecording) ?? 'Record Workspace';
+    if (typeof value === 'string') RecordingBox.WorkspaceStartRecording();
+    else RecordingBox.replayWorkspace(value);
 });
-ScriptingGlobals.add(function getIsWorkspaceRecPlaying() {
-    return Doc.UserDoc().isWorkspaceRecPlaying;
+ScriptingGlobals.add(function pauseWorkspaceReplaying(value: Doc, _readOnly_: boolean) {
+    RecordingBox.pauseWorkspaceReplaying(value);
 });
-ScriptingGlobals.add(function getIsWorkspaceRecPaused() {
-    return Doc.UserDoc().isWorkspaceRecPaused;
+ScriptingGlobals.add(function resumeWorkspaceReplaying(value: Doc, _readOnly_: boolean) {
+    RecordingBox.resumeWorkspaceReplaying(value);
 });
+
 ScriptingGlobals.add(function renderDropdown() {
     if (!Doc.UserDoc().workspaceRecordings || DocListCast(Doc.UserDoc().workspaceRecordings).length === 0) {
         return true;
diff --git a/src/client/views/nodes/ScreenshotBox.tsx b/src/client/views/nodes/ScreenshotBox.tsx
index fa19caae1..4ebc93165 100644
--- a/src/client/views/nodes/ScreenshotBox.tsx
+++ b/src/client/views/nodes/ScreenshotBox.tsx
@@ -219,6 +219,9 @@ export class ScreenshotBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatabl
         // }
         return null;
     }
+    Record = () => !this._screenCapture && this.toggleRecording();
+    Pause = () => this._screenCapture && this.toggleRecording();
+
     toggleRecording = async () => {
         if (!this._screenCapture) {
             this._audioRec = new MediaRecorder(await navigator.mediaDevices.getUserMedia({ audio: true }));
diff --git a/src/client/views/topbar/TopBar.tsx b/src/client/views/topbar/TopBar.tsx
index 5b097e639..55d94406a 100644
--- a/src/client/views/topbar/TopBar.tsx
+++ b/src/client/views/topbar/TopBar.tsx
@@ -1,13 +1,14 @@
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { Button, IconButton, isDark, Size, Toggle, Type } from 'browndash-components';
+import { Button, IconButton, isDark, Size, Type } from 'browndash-components';
 import { action, computed, observable, reaction } from 'mobx';
 import { observer } from 'mobx-react';
 import * as React from 'react';
-import { FaBug, FaCamera } from 'react-icons/fa';
+import { FaBug } from 'react-icons/fa';
 import { Doc, DocListCast } from '../../../fields/Doc';
 import { AclAdmin, DashVersion } from '../../../fields/DocSymbols';
 import { StrCast } from '../../../fields/Types';
 import { GetEffectiveAcl } from '../../../fields/util';
+import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue } from '../../../Utils';
 import { CurrentUserUtils } from '../../util/CurrentUserUtils';
 import { DocumentManager } from '../../util/DocumentManager';
 import { PingManager } from '../../util/PingManager';
@@ -15,12 +16,14 @@ import { ReportManager } from '../../util/reportManager/ReportManager';
 import { ServerStats } from '../../util/ServerStats';
 import { SettingsManager } from '../../util/SettingsManager';
 import { SharingManager } from '../../util/SharingManager';
-import { UndoManager } from '../../util/UndoManager';
+import { Transform } from '../../util/Transform';
 import { CollectionDockingView } from '../collections/CollectionDockingView';
+import { CollectionLinearView } from '../collections/collectionLinear';
 import { ContextMenu } from '../ContextMenu';
 import { DashboardView } from '../DashboardView';
 import { Colors } from '../global/globalEnums';
-import { DocumentView } from '../nodes/DocumentView';
+import { DocumentView, DocumentViewInternal } from '../nodes/DocumentView';
+import { DefaultStyleProvider } from '../StyleProvider';
 import './TopBar.scss';
 
 /**
@@ -91,6 +94,43 @@ export class TopBar extends React.Component {
         );
     }
 
+    @computed get dashMenuButtons() {
+        const selDoc = Doc.MyTopBarBtns;
+        return !(selDoc instanceof Doc) ? null : (
+            <div className="collectionMenu-contMenuButtons" style={{ height: '100%' }}>
+                <CollectionLinearView
+                    Document={selDoc}
+                    DataDoc={undefined}
+                    fieldKey="data"
+                    dropAction="embed"
+                    setHeight={returnFalse}
+                    styleProvider={DefaultStyleProvider}
+                    rootSelected={returnTrue}
+                    bringToFront={emptyFunction}
+                    select={emptyFunction}
+                    isContentActive={returnTrue}
+                    isAnyChildContentActive={returnFalse}
+                    isSelected={returnFalse}
+                    docViewPath={returnEmptyDoclist}
+                    moveDocument={returnFalse}
+                    addDocument={returnFalse}
+                    addDocTab={DocumentViewInternal.addDocTabFunc}
+                    pinToPres={emptyFunction}
+                    removeDocument={returnFalse}
+                    ScreenToLocalTransform={Transform.Identity}
+                    PanelWidth={() => 200}
+                    PanelHeight={() => 30}
+                    renderDepth={0}
+                    focus={emptyFunction}
+                    whenChildContentsActiveChanged={emptyFunction}
+                    childFilters={returnEmptyFilter}
+                    childFiltersByRanges={returnEmptyFilter}
+                    searchFilterDocs={returnEmptyDoclist}
+                />
+            </div>
+        );
+    }
+
     /**
      * Returns the center of the topbar
      * This part of the topbar contains everything related to the current dashboard including:
@@ -118,23 +158,10 @@ export class TopBar extends React.Component {
                     style={{ fontWeight: 700, fontSize: '1rem' }}
                     onClick={(e: React.MouseEvent) => {
                         const dashView = Doc.ActiveDashboard && DocumentManager.Instance.getDocumentView(Doc.ActiveDashboard);
-                        ContextMenu.Instance.addItem({ description: 'Open Dashboard View', event: this.navigateToHome, icon: 'edit' });
                         dashView?.showContextMenu(e.clientX + 20, e.clientY + 30);
                     }}
                 />
-                {!Doc.noviceMode && (
-                    <IconButton
-                        tooltip="Work on a copy of the dashboard layout"
-                        size={Size.SMALL}
-                        color={this.color}
-                        onClick={async () => {
-                            const batch = UndoManager.StartBatch('snapshot');
-                            await DashboardView.snapshotDashboard();
-                            batch.end();
-                        }}
-                        icon={<FaCamera />}
-                    />
-                )}
+                {!Doc.noviceMode && this.dashMenuButtons}
             </div>
         ) : null;
     }
diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts
index ad0e548ed..2a1dfbfc7 100644
--- a/src/fields/Doc.ts
+++ b/src/fields/Doc.ts
@@ -220,6 +220,9 @@ export class Doc extends RefField {
     public static get MyContextMenuBtns() {
         return DocCast(Doc.UserDoc().myContextMenuBtns);
     }
+    public static get MyTopBarBtns() {
+        return DocCast(Doc.UserDoc().myTopBarBtns);
+    }
     public static get MyRecentlyClosed() {
         return DocCast(Doc.UserDoc().myRecentlyClosed);
     }
-- 
cgit v1.2.3-70-g09d2


From b7295d4747d8eb01d8213c97442cc4916aec77c4 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Thu, 31 Aug 2023 12:16:09 -0400
Subject: from last again

---
 src/client/util/DragManager.ts                     |  4 +---
 .../collectionLinear/CollectionLinearView.tsx      |  4 ++--
 src/client/views/nodes/FontIconBox/FontIconBox.tsx |  2 +-
 .../views/nodes/RecordingBox/RecordingBox.tsx      |  3 ---
 src/client/views/nodes/trails/PresBox.tsx          |  2 --
 src/client/views/nodes/trails/PresElementBox.tsx   | 24 +++++++---------------
 6 files changed, 11 insertions(+), 28 deletions(-)

(limited to 'src/client/views/nodes/FontIconBox/FontIconBox.tsx')

diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index 4ab033555..6d6eaebec 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -4,17 +4,15 @@ import { Doc, Field, Opt, StrListCast } from '../../fields/Doc';
 import { List } from '../../fields/List';
 import { PrefetchProxy } from '../../fields/Proxy';
 import { ScriptField } from '../../fields/ScriptField';
-import { BoolCast, Cast, DocCast, ScriptCast, StrCast } from '../../fields/Types';
+import { ScriptCast, StrCast } from '../../fields/Types';
 import { emptyFunction, Utils } from '../../Utils';
 import { Docs, DocUtils } from '../documents/Documents';
 import * as globalCssVariables from '../views/global/globalCssVariables.scss';
-import { Colors } from '../views/global/globalEnums';
 import { DocumentView } from '../views/nodes/DocumentView';
 import { ScriptingGlobals } from './ScriptingGlobals';
 import { SelectionManager } from './SelectionManager';
 import { SnappingManager } from './SnappingManager';
 import { UndoManager } from './UndoManager';
-import { listSpec } from '../../fields/Schema';
 
 export type dropActionType = 'embed' | 'copy' | 'move' | 'add' | 'same' | 'proto' | 'none' | undefined; // undefined = move, "same" = move but don't call dropPropertiesToRemove
 
diff --git a/src/client/views/collections/collectionLinear/CollectionLinearView.tsx b/src/client/views/collections/collectionLinear/CollectionLinearView.tsx
index 0cf7d4411..47a98bdd1 100644
--- a/src/client/views/collections/collectionLinear/CollectionLinearView.tsx
+++ b/src/client/views/collections/collectionLinear/CollectionLinearView.tsx
@@ -229,8 +229,8 @@ export class CollectionLinearView extends CollectionSubView() {
                 <div className="collectionLinearView" ref={this.createDashEventsTarget} onContextMenu={this.myContextMenu} style={{ minHeight: this.dimension(), pointerEvents: 'all' }}>
                     {
                         <>
-                            {!this.layoutDoc.linearView_Expandable ? null :menuOpener}
-                            {!this.layoutDoc.linearView_IsOpen && !this.layoutDoc.linearView_alwaysOpen ? null : (
+                            {!this.layoutDoc.linearView_Expandable ? null : menuOpener}
+                            {!this.layoutDoc.linearView_IsOpen ? null : (
                                 <div
                                     className="collectionLinearView-content"
                                     style={{
diff --git a/src/client/views/nodes/FontIconBox/FontIconBox.tsx b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
index 8ef9cd792..9bc9f2b52 100644
--- a/src/client/views/nodes/FontIconBox/FontIconBox.tsx
+++ b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
@@ -234,7 +234,7 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
 
         return (
             <Dropdown
-                selectedVal={text ?? 'Record Workspace'}
+                selectedVal={text}
                 setSelectedVal={undoable(val => script.script.run({ this: this.layoutDoc, self: this.rootDoc, val }), `dropdown select ${this.label}`)}
                 color={SettingsManager.userColor}
                 background={SettingsManager.userVariantColor}
diff --git a/src/client/views/nodes/RecordingBox/RecordingBox.tsx b/src/client/views/nodes/RecordingBox/RecordingBox.tsx
index 1b2f63fa2..e9060a605 100644
--- a/src/client/views/nodes/RecordingBox/RecordingBox.tsx
+++ b/src/client/views/nodes/RecordingBox/RecordingBox.tsx
@@ -138,7 +138,6 @@ export class RecordingBox extends ViewBoxBaseComponent<FieldViewProps>() {
         Doc.UserDoc().workspaceRecordingState = undefined;
     }
 
-    @undoBatch
     @action
     public static resumeWorkspaceReplaying(doc: Doc) {
         const docView = DocumentManager.Instance.getDocumentView(doc);
@@ -149,7 +148,6 @@ export class RecordingBox extends ViewBoxBaseComponent<FieldViewProps>() {
         }
     }
 
-    @undoBatch
     @action
     public static pauseWorkspaceReplaying(doc: Doc) {
         const docView = DocumentManager.Instance.getDocumentView(doc);
@@ -160,7 +158,6 @@ export class RecordingBox extends ViewBoxBaseComponent<FieldViewProps>() {
         Doc.UserDoc().workspaceReplayingState = media_state.Paused;
     }
 
-    @undoBatch
     @action
     public static stopWorkspaceReplaying(value: Doc) {
         Doc.RemFromMyOverlay(value);
diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx
index 02132b7b3..7bb1b80a3 100644
--- a/src/client/views/nodes/trails/PresBox.tsx
+++ b/src/client/views/nodes/trails/PresBox.tsx
@@ -303,7 +303,6 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
     // Called when the user activates 'next' - to move to the next part of the pres. trail
     @action
     next = () => {
-        console.log('next');
         const progressiveReveal = (first: boolean) => {
             const presIndexed = Cast(this.activeItem?.presentation_indexed, 'number', null);
             if (presIndexed !== undefined) {
@@ -386,7 +385,6 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
     //it'll also execute the necessary actions if presentation is playing.
     @undoBatch
     public gotoDocument = action((index: number, from?: Doc, group?: boolean, finished?: () => void) => {
-        console.log('going to document');
         Doc.UnBrushAllDocs();
         if (index >= 0 && index < this.childDocs.length) {
             this.rootDoc._itemIndex = index;
diff --git a/src/client/views/nodes/trails/PresElementBox.tsx b/src/client/views/nodes/trails/PresElementBox.tsx
index 121eb87d5..82ed9e8d5 100644
--- a/src/client/views/nodes/trails/PresElementBox.tsx
+++ b/src/client/views/nodes/trails/PresElementBox.tsx
@@ -6,7 +6,7 @@ import { Doc, DocListCast, Opt } from '../../../../fields/Doc';
 import { Height, Width } from '../../../../fields/DocSymbols';
 import { Id } from '../../../../fields/FieldSymbols';
 import { List } from '../../../../fields/List';
-import { Cast, DocCast, NumCast, StrCast } from '../../../../fields/Types';
+import { BoolCast, Cast, DocCast, NumCast, StrCast } from '../../../../fields/Types';
 import { emptyFunction, returnEmptyDoclist, returnFalse, returnTrue, setupMoveUpEvents } from '../../../../Utils';
 import { Docs } from '../../../documents/Documents';
 import { CollectionViewType } from '../../../documents/DocumentTypes';
@@ -313,17 +313,8 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() {
     @undoBatch
     @action
     revertToPreviouslySaved = (presTargetDoc: Doc, activeItem: Doc) => {
-        console.log('reverting');
-        // console.log("reverting to previosly saved\n");
-        // console.log(this.prevTarget);
-        console.log('Content continuously updating');
         const target = DocCast(activeItem.annotationOn) ?? activeItem;
-        console.log(presTargetDoc.pinData);
         PresBox.reversePin(activeItem, target);
-        // console.log("new target\n");
-        // console.log(target);
-        // PresBox.pinDocView(activeItem, { pinData: PresBox.pinDataTypes(this.prevTarget) }, this.prevTarget ? this.prevTarget : target);
-        //figure out how to make it go back to the previously saved one
     };
 
     /**
@@ -426,7 +417,6 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() {
     @action
     lfg = (e: React.MouseEvent) => {
         e.stopPropagation();
-        console.log('lfg called');
         // TODO: fix this bug
         const { toggleChildrenRun } = this.rootDoc;
         TreeView.ToggleChildrenRun.get(this.rootDoc)?.();
@@ -445,12 +435,12 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() {
     }
 
     @computed get presButtons() {
-        const presBox = this.presBox; //presBox
-        const presBoxColor: string = StrCast(presBox?._backgroundColor);
-        const presColorBool: boolean = presBoxColor ? presBoxColor !== Colors.WHITE && presBoxColor !== 'transparent' : false;
-        const targetDoc: Doc = this.targetDoc;
-        const activeItem: Doc = this.rootDoc;
-        const hasChildren: boolean = Cast(this.rootDoc?.hasChildren, 'boolean') || false;
+        const presBox = this.presBox;
+        const presBoxColor = StrCast(presBox?._backgroundColor);
+        const presColorBool = presBoxColor ? presBoxColor !== Colors.WHITE && presBoxColor !== 'transparent' : false;
+        const targetDoc = this.targetDoc;
+        const activeItem = this.rootDoc;
+        const hasChildren = BoolCast(this.rootDoc?.hasChildren);
 
         const items: JSX.Element[] = [];
 
-- 
cgit v1.2.3-70-g09d2


From a60edcbd8fd724ef9c228262370a7ad98f7aadd1 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Thu, 31 Aug 2023 15:44:46 -0400
Subject: added dragging off of recordings and option for webcam vs screen

---
 package-lock.json                                  | 304 +++++++++------------
 package.json                                       |   2 +-
 src/client/util/CurrentUserUtils.ts                |   4 +-
 src/client/views/nodes/FontIconBox/FontIconBox.tsx |  15 +-
 .../views/nodes/RecordingBox/RecordingBox.tsx      |  44 +--
 src/client/views/nodes/ScreenshotBox.tsx           |  13 +-
 6 files changed, 185 insertions(+), 197 deletions(-)

(limited to 'src/client/views/nodes/FontIconBox/FontIconBox.tsx')

diff --git a/package-lock.json b/package-lock.json
index c3190ddb4..aae7c022c 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -164,11 +164,11 @@
             },
             "dependencies": {
                 "@babel/code-frame": {
-                    "version": "7.22.10",
-                    "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.10.tgz",
-                    "integrity": "sha512-/KKIMG4UEL35WmI9OlvMhurwtytjvXoFcGNrOvyG9zIzA8YmPjVtIZUf7b05+TPO7G7/GEmLHDaoCgACHl9hhA==",
+                    "version": "7.22.13",
+                    "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz",
+                    "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==",
                     "requires": {
-                        "@babel/highlight": "^7.22.10",
+                        "@babel/highlight": "^7.22.13",
                         "chalk": "^2.4.2"
                     }
                 },
@@ -184,9 +184,9 @@
                     }
                 },
                 "@babel/highlight": {
-                    "version": "7.22.10",
-                    "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.10.tgz",
-                    "integrity": "sha512-78aUtVcT7MUscr0K5mIEnkwxPE0MaxkR5RxRwuHaQ+JuU5AmTPhY+do2mdzVTnIJJpyBglql2pehuBIWHug+WQ==",
+                    "version": "7.22.13",
+                    "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.13.tgz",
+                    "integrity": "sha512-C/BaXcnnvBCmHTpz/VGZ8jgtE2aYlW4hxDhseJAWZb7gqGM/qtCK6iZUb0TyKFf7BOUsBH7Q7fkRsDRhg1XklQ==",
                     "requires": {
                         "@babel/helper-validator-identifier": "^7.22.5",
                         "chalk": "^2.4.2",
@@ -194,9 +194,9 @@
                     }
                 },
                 "@babel/parser": {
-                    "version": "7.22.11",
-                    "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.11.tgz",
-                    "integrity": "sha512-R5zb8eJIBPJriQtbH/htEQy4k7E2dHWlD2Y2VT07JCzwYZHBxV5ZYtM0UhXSNMT74LyxuM+b1jdL7pSesXbC/g=="
+                    "version": "7.22.14",
+                    "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.14.tgz",
+                    "integrity": "sha512-1KucTHgOvaw/LzCVrEOAyXkr9rQlp0A1HiHRYnSUE9dmb8PvPW7o5sscg+5169r54n3vGlbx6GevTE/Iw/P3AQ=="
                 },
                 "@babel/traverse": {
                     "version": "7.22.11",
@@ -579,11 +579,11 @@
             },
             "dependencies": {
                 "@babel/code-frame": {
-                    "version": "7.22.10",
-                    "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.10.tgz",
-                    "integrity": "sha512-/KKIMG4UEL35WmI9OlvMhurwtytjvXoFcGNrOvyG9zIzA8YmPjVtIZUf7b05+TPO7G7/GEmLHDaoCgACHl9hhA==",
+                    "version": "7.22.13",
+                    "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz",
+                    "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==",
                     "requires": {
-                        "@babel/highlight": "^7.22.10",
+                        "@babel/highlight": "^7.22.13",
                         "chalk": "^2.4.2"
                     }
                 },
@@ -599,9 +599,9 @@
                     }
                 },
                 "@babel/highlight": {
-                    "version": "7.22.10",
-                    "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.10.tgz",
-                    "integrity": "sha512-78aUtVcT7MUscr0K5mIEnkwxPE0MaxkR5RxRwuHaQ+JuU5AmTPhY+do2mdzVTnIJJpyBglql2pehuBIWHug+WQ==",
+                    "version": "7.22.13",
+                    "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.13.tgz",
+                    "integrity": "sha512-C/BaXcnnvBCmHTpz/VGZ8jgtE2aYlW4hxDhseJAWZb7gqGM/qtCK6iZUb0TyKFf7BOUsBH7Q7fkRsDRhg1XklQ==",
                     "requires": {
                         "@babel/helper-validator-identifier": "^7.22.5",
                         "chalk": "^2.4.2",
@@ -609,9 +609,9 @@
                     }
                 },
                 "@babel/parser": {
-                    "version": "7.22.11",
-                    "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.11.tgz",
-                    "integrity": "sha512-R5zb8eJIBPJriQtbH/htEQy4k7E2dHWlD2Y2VT07JCzwYZHBxV5ZYtM0UhXSNMT74LyxuM+b1jdL7pSesXbC/g=="
+                    "version": "7.22.14",
+                    "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.14.tgz",
+                    "integrity": "sha512-1KucTHgOvaw/LzCVrEOAyXkr9rQlp0A1HiHRYnSUE9dmb8PvPW7o5sscg+5169r54n3vGlbx6GevTE/Iw/P3AQ=="
                 },
                 "@babel/traverse": {
                     "version": "7.22.11",
@@ -1822,9 +1822,9 @@
             }
         },
         "@babel/preset-env": {
-            "version": "7.22.10",
-            "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.22.10.tgz",
-            "integrity": "sha512-riHpLb1drNkpLlocmSyEg4oYJIQFeXAK/d7rI6mbD0XsvoTOOweXDmQPG/ErxsEhWk3rl3Q/3F6RFQlVFS8m0A==",
+            "version": "7.22.14",
+            "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.22.14.tgz",
+            "integrity": "sha512-daodMIoVo+ol/g+//c/AH+szBkFj4STQUikvBijRGL72Ph+w+AMTSh55DUETe8KJlPlDT1k/mp7NBfOuiWmoig==",
             "requires": {
                 "@babel/compat-data": "^7.22.9",
                 "@babel/helper-compilation-targets": "^7.22.10",
@@ -1852,41 +1852,41 @@
                 "@babel/plugin-syntax-top-level-await": "^7.14.5",
                 "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6",
                 "@babel/plugin-transform-arrow-functions": "^7.22.5",
-                "@babel/plugin-transform-async-generator-functions": "^7.22.10",
+                "@babel/plugin-transform-async-generator-functions": "^7.22.11",
                 "@babel/plugin-transform-async-to-generator": "^7.22.5",
                 "@babel/plugin-transform-block-scoped-functions": "^7.22.5",
                 "@babel/plugin-transform-block-scoping": "^7.22.10",
                 "@babel/plugin-transform-class-properties": "^7.22.5",
-                "@babel/plugin-transform-class-static-block": "^7.22.5",
+                "@babel/plugin-transform-class-static-block": "^7.22.11",
                 "@babel/plugin-transform-classes": "^7.22.6",
                 "@babel/plugin-transform-computed-properties": "^7.22.5",
                 "@babel/plugin-transform-destructuring": "^7.22.10",
                 "@babel/plugin-transform-dotall-regex": "^7.22.5",
                 "@babel/plugin-transform-duplicate-keys": "^7.22.5",
-                "@babel/plugin-transform-dynamic-import": "^7.22.5",
+                "@babel/plugin-transform-dynamic-import": "^7.22.11",
                 "@babel/plugin-transform-exponentiation-operator": "^7.22.5",
-                "@babel/plugin-transform-export-namespace-from": "^7.22.5",
+                "@babel/plugin-transform-export-namespace-from": "^7.22.11",
                 "@babel/plugin-transform-for-of": "^7.22.5",
                 "@babel/plugin-transform-function-name": "^7.22.5",
-                "@babel/plugin-transform-json-strings": "^7.22.5",
+                "@babel/plugin-transform-json-strings": "^7.22.11",
                 "@babel/plugin-transform-literals": "^7.22.5",
-                "@babel/plugin-transform-logical-assignment-operators": "^7.22.5",
+                "@babel/plugin-transform-logical-assignment-operators": "^7.22.11",
                 "@babel/plugin-transform-member-expression-literals": "^7.22.5",
                 "@babel/plugin-transform-modules-amd": "^7.22.5",
-                "@babel/plugin-transform-modules-commonjs": "^7.22.5",
-                "@babel/plugin-transform-modules-systemjs": "^7.22.5",
+                "@babel/plugin-transform-modules-commonjs": "^7.22.11",
+                "@babel/plugin-transform-modules-systemjs": "^7.22.11",
                 "@babel/plugin-transform-modules-umd": "^7.22.5",
                 "@babel/plugin-transform-named-capturing-groups-regex": "^7.22.5",
                 "@babel/plugin-transform-new-target": "^7.22.5",
-                "@babel/plugin-transform-nullish-coalescing-operator": "^7.22.5",
-                "@babel/plugin-transform-numeric-separator": "^7.22.5",
-                "@babel/plugin-transform-object-rest-spread": "^7.22.5",
+                "@babel/plugin-transform-nullish-coalescing-operator": "^7.22.11",
+                "@babel/plugin-transform-numeric-separator": "^7.22.11",
+                "@babel/plugin-transform-object-rest-spread": "^7.22.11",
                 "@babel/plugin-transform-object-super": "^7.22.5",
-                "@babel/plugin-transform-optional-catch-binding": "^7.22.5",
-                "@babel/plugin-transform-optional-chaining": "^7.22.10",
+                "@babel/plugin-transform-optional-catch-binding": "^7.22.11",
+                "@babel/plugin-transform-optional-chaining": "^7.22.12",
                 "@babel/plugin-transform-parameters": "^7.22.5",
                 "@babel/plugin-transform-private-methods": "^7.22.5",
-                "@babel/plugin-transform-private-property-in-object": "^7.22.5",
+                "@babel/plugin-transform-private-property-in-object": "^7.22.11",
                 "@babel/plugin-transform-property-literals": "^7.22.5",
                 "@babel/plugin-transform-regenerator": "^7.22.10",
                 "@babel/plugin-transform-reserved-words": "^7.22.5",
@@ -1900,7 +1900,7 @@
                 "@babel/plugin-transform-unicode-regex": "^7.22.5",
                 "@babel/plugin-transform-unicode-sets-regex": "^7.22.5",
                 "@babel/preset-modules": "0.1.6-no-external-plugins",
-                "@babel/types": "^7.22.10",
+                "@babel/types": "^7.22.11",
                 "babel-plugin-polyfill-corejs2": "^0.4.5",
                 "babel-plugin-polyfill-corejs3": "^0.8.3",
                 "babel-plugin-polyfill-regenerator": "^0.5.2",
@@ -2711,11 +2711,11 @@
             }
         },
         "@floating-ui/react-dom": {
-            "version": "2.0.1",
-            "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.0.1.tgz",
-            "integrity": "sha512-rZtAmSht4Lry6gdhAJDrCp/6rKN7++JnL1/Anbr/DdeyYXQPxvg/ivrbYvJulbRf4vL8b212suwMM2lxbv+RQA==",
+            "version": "2.0.2",
+            "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.0.2.tgz",
+            "integrity": "sha512-5qhlDvjaLmAst/rKb3VdlCinwTF4EYMiVxuuc/HVUjs46W0zgtbMmAZ1UTsDrRTxRmUEzl92mOtWbeeXL26lSQ==",
             "requires": {
-                "@floating-ui/dom": "^1.3.0"
+                "@floating-ui/dom": "^1.5.1"
             }
         },
         "@floating-ui/utils": {
@@ -3232,9 +3232,9 @@
             }
         },
         "@mui/styled-engine-sc": {
-            "version": "5.14.6",
-            "resolved": "https://registry.npmjs.org/@mui/styled-engine-sc/-/styled-engine-sc-5.14.6.tgz",
-            "integrity": "sha512-7/KXXdDLjpQAmbmIhUs1x7nzqooEiHkidQOXCIH04NiVa4KRxP4v/bOWV/5GpgZi1Aky5ruf9IVyH3jxYIW3JA==",
+            "version": "5.14.7",
+            "resolved": "https://registry.npmjs.org/@mui/styled-engine-sc/-/styled-engine-sc-5.14.7.tgz",
+            "integrity": "sha512-so3X2N0SxpXjc61+d6s0aG11OVF9XTDrKusaXd8YE1d9fzEuIGEpvOXizaMJZThqkTqGzNKQuXFEpC55Vb0gdw==",
             "requires": {
                 "@babel/runtime": "^7.22.10",
                 "prop-types": "^15.8.1"
@@ -6537,9 +6537,9 @@
             }
         },
         "browndash-components": {
-            "version": "0.1.2",
-            "resolved": "https://registry.npmjs.org/browndash-components/-/browndash-components-0.1.2.tgz",
-            "integrity": "sha512-5ONrqd6qYYMjWuayhhdwU4tlrtr+7c0n9MAMXg4jccdd9OxnmdlWpjPzOBYl3slE+mSpKcycwKarwYND+eM0NA==",
+            "version": "0.1.21",
+            "resolved": "https://registry.npmjs.org/browndash-components/-/browndash-components-0.1.21.tgz",
+            "integrity": "sha512-xPHuliete1jNXCGYZrVxuKUDmlanleFLWjZm8dC3vII0BT7jNPxMRZyYTxgc/PjYMRgM/BY0FCUPFTrsiYRawQ==",
             "requires": {
                 "@emotion/react": "^11.11.1",
                 "@emotion/styled": "^11.11.0",
@@ -6657,15 +6657,15 @@
                     "integrity": "sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww=="
                 },
                 "@mui/base": {
-                    "version": "5.0.0-beta.12",
-                    "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-beta.12.tgz",
-                    "integrity": "sha512-tZjjXNAyUpwSDT1uRliZMhRQkWYzELJ8Qi61EuOMRpi36HIwnK2T7Nr4RI423Sv8G2EEikDAZj7je33eNd73NQ==",
+                    "version": "5.0.0-beta.13",
+                    "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-beta.13.tgz",
+                    "integrity": "sha512-uC0l97pBspfDAp+iz2cJq8YZ8Sd9i73V77+WzUiOAckIVEyCm5dyVDZCCO2/phmzckVEeZCGcytybkjMQuhPQw==",
                     "requires": {
                         "@babel/runtime": "^7.22.10",
                         "@emotion/is-prop-valid": "^1.2.1",
                         "@floating-ui/react-dom": "^2.0.1",
                         "@mui/types": "^7.2.4",
-                        "@mui/utils": "^5.14.6",
+                        "@mui/utils": "^5.14.7",
                         "@popperjs/core": "^2.11.8",
                         "clsx": "^2.0.0",
                         "prop-types": "^15.8.1",
@@ -6683,21 +6683,21 @@
                     }
                 },
                 "@mui/core-downloads-tracker": {
-                    "version": "5.14.6",
-                    "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.14.6.tgz",
-                    "integrity": "sha512-QZEU3pyGWLuaHbxvOlShol7U1FVgzWBR0OH9H8D7L8w4/vto5N5jJVvlqFQS3T0zbR6YGHxFaiL6Ky87jQg7aw=="
+                    "version": "5.14.7",
+                    "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.14.7.tgz",
+                    "integrity": "sha512-sCWTUNElBPgB30iLvWe3PU7SIlTKZNf6/E/sko85iHVeHCM6WPkDw+y89CrZYjhFNmPqt2fIQM/pZu+rP2lFLA=="
                 },
                 "@mui/material": {
-                    "version": "5.14.6",
-                    "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.14.6.tgz",
-                    "integrity": "sha512-C3UgGrmtvcGkQkm0ONBU7bTdapTjQc2Se3b2354xMmU7lgSgW7VM6EP9wIH5XqqoJ60m9l/s9kbTWX0Y+EaWvA==",
+                    "version": "5.14.7",
+                    "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.14.7.tgz",
+                    "integrity": "sha512-jIZj9F7zMv6IlyaYDVv5M2Kp20jIX8c0kzuwteySHS/A0IvPVyomQEPtWc51MCbpDNCqzwoZUp3rQtA2lI8k7A==",
                     "requires": {
                         "@babel/runtime": "^7.22.10",
-                        "@mui/base": "5.0.0-beta.12",
-                        "@mui/core-downloads-tracker": "^5.14.6",
-                        "@mui/system": "^5.14.6",
+                        "@mui/base": "5.0.0-beta.13",
+                        "@mui/core-downloads-tracker": "^5.14.7",
+                        "@mui/system": "^5.14.7",
                         "@mui/types": "^7.2.4",
-                        "@mui/utils": "^5.14.6",
+                        "@mui/utils": "^5.14.7",
                         "@types/react-transition-group": "^4.4.6",
                         "clsx": "^2.0.0",
                         "csstype": "^3.1.2",
@@ -6717,12 +6717,12 @@
                     }
                 },
                 "@mui/private-theming": {
-                    "version": "5.14.6",
-                    "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.14.6.tgz",
-                    "integrity": "sha512-3VBLFGizBXfofyk33bwRg6t9L648aKnLmOKPfY1wFuiXq3AEYwobK65iDci/tHKxm/VKbZ6A7PFjLejvB3EvRQ==",
+                    "version": "5.14.7",
+                    "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.14.7.tgz",
+                    "integrity": "sha512-Y86+hmDnJab2Ka42PgxKpK3oL7EiacbeeX3X/lG9LGO0wSc45wZjHeTfIlVSkkUCkexiMKEJp5NlSjZhr27NRQ==",
                     "requires": {
                         "@babel/runtime": "^7.22.10",
-                        "@mui/utils": "^5.14.6",
+                        "@mui/utils": "^5.14.7",
                         "prop-types": "^15.8.1"
                     },
                     "dependencies": {
@@ -6737,9 +6737,9 @@
                     }
                 },
                 "@mui/styled-engine": {
-                    "version": "5.14.6",
-                    "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.14.6.tgz",
-                    "integrity": "sha512-I6zeu/OP1Hk4NsX1Oj85TiYl1dER0JMsLJVn76J1Ihl24A5EbiZQKJp3Mn+ufA79ypkdAvM9aQCAQyiVBFcUHg==",
+                    "version": "5.14.7",
+                    "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.14.7.tgz",
+                    "integrity": "sha512-hKBETEDsIAkL8/mBwPiQj/vw28OeIhMXC3Tvj4J2bb9snxAKpiZioR1PwqP+6P41twsC/GKBd0Vr9oaWYaHuMg==",
                     "requires": {
                         "@babel/runtime": "^7.22.10",
                         "@emotion/cache": "^11.11.0",
@@ -6758,15 +6758,15 @@
                     }
                 },
                 "@mui/system": {
-                    "version": "5.14.6",
-                    "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.14.6.tgz",
-                    "integrity": "sha512-/n0ae1MegWjiV1BpRU8jgg4E0zBjeB2VYsT/68ag/xaDuq3/TaDKJeT9REIvyBvwlG3CI3S2O+tRELktxCD1kg==",
+                    "version": "5.14.7",
+                    "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.14.7.tgz",
+                    "integrity": "sha512-jeZtHglc+Pi6qjGoopT6O4RqYXVBMqHVOsjMGP0hxGSSPm1T4gsAu7jU8eqGx9YwwjvvJ0eotTjFqw7iJ6qE2Q==",
                     "requires": {
                         "@babel/runtime": "^7.22.10",
-                        "@mui/private-theming": "^5.14.6",
-                        "@mui/styled-engine": "^5.14.6",
+                        "@mui/private-theming": "^5.14.7",
+                        "@mui/styled-engine": "^5.14.7",
                         "@mui/types": "^7.2.4",
-                        "@mui/utils": "^5.14.6",
+                        "@mui/utils": "^5.14.7",
                         "clsx": "^2.0.0",
                         "csstype": "^3.1.2",
                         "prop-types": "^15.8.1"
@@ -6783,9 +6783,9 @@
                     }
                 },
                 "@mui/utils": {
-                    "version": "5.14.6",
-                    "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.14.6.tgz",
-                    "integrity": "sha512-AznpqLu6hrFnpHgcvsSSMCG+cDbkcCYfo+daUwBVReNYv4l+NQ8+wvBAF4aUMi155N7xWbbgh0cyKs6Wdsm3aA==",
+                    "version": "5.14.7",
+                    "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.14.7.tgz",
+                    "integrity": "sha512-RtheP/aBoPogVdi8vj8Vo2IFnRa4mZVmnD0RGlVZ49yF60rZs+xP4/KbpIrTr83xVs34QmHQ2aQ+IX7I0a0dDw==",
                     "requires": {
                         "@babel/runtime": "^7.22.10",
                         "@types/prop-types": "^15.7.5",
@@ -7094,97 +7094,12 @@
                                         "strip-ansi": "^7.0.1"
                                     }
                                 },
-                                "string-width-cjs": {
-                                    "version": "npm:string-width@4.2.3",
-                                    "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
-                                    "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
-                                    "requires": {
-                                        "emoji-regex": "^8.0.0",
-                                        "is-fullwidth-code-point": "^3.0.0",
-                                        "strip-ansi": "^6.0.1"
-                                    },
-                                    "dependencies": {
-                                        "ansi-regex": {
-                                            "version": "5.0.1",
-                                            "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
-                                            "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="
-                                        },
-                                        "emoji-regex": {
-                                            "version": "8.0.0",
-                                            "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
-                                            "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
-                                        },
-                                        "strip-ansi": {
-                                            "version": "6.0.1",
-                                            "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
-                                            "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
-                                            "requires": {
-                                                "ansi-regex": "^5.0.1"
-                                            }
-                                        }
-                                    }
-                                },
                                 "strip-ansi": {
                                     "version": "7.1.0",
                                     "bundled": true,
                                     "requires": {
                                         "ansi-regex": "^6.0.1"
                                     }
-                                },
-                                "strip-ansi-cjs": {
-                                    "version": "npm:strip-ansi@6.0.1",
-                                    "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
-                                    "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
-                                    "requires": {
-                                        "ansi-regex": "^5.0.1"
-                                    },
-                                    "dependencies": {
-                                        "ansi-regex": {
-                                            "version": "5.0.1",
-                                            "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
-                                            "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="
-                                        }
-                                    }
-                                },
-                                "wrap-ansi-cjs": {
-                                    "version": "npm:wrap-ansi@7.0.0",
-                                    "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
-                                    "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
-                                    "requires": {
-                                        "ansi-styles": "^4.0.0",
-                                        "string-width": "^4.1.0",
-                                        "strip-ansi": "^6.0.0"
-                                    },
-                                    "dependencies": {
-                                        "ansi-regex": {
-                                            "version": "5.0.1",
-                                            "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
-                                            "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="
-                                        },
-                                        "emoji-regex": {
-                                            "version": "8.0.0",
-                                            "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
-                                            "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
-                                        },
-                                        "string-width": {
-                                            "version": "4.2.3",
-                                            "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
-                                            "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
-                                            "requires": {
-                                                "emoji-regex": "^8.0.0",
-                                                "is-fullwidth-code-point": "^3.0.0",
-                                                "strip-ansi": "^6.0.1"
-                                            }
-                                        },
-                                        "strip-ansi": {
-                                            "version": "6.0.1",
-                                            "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
-                                            "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
-                                            "requires": {
-                                                "ansi-regex": "^5.0.1"
-                                            }
-                                        }
-                                    }
                                 }
                             }
                         },
@@ -8689,7 +8604,7 @@
                             }
                         },
                         "string-width-cjs": {
-                            "version": "npm:string-width-cjs@4.2.3",
+                            "version": "npm:string-width@4.2.3",
                             "bundled": true,
                             "requires": {
                                 "emoji-regex": "^8.0.0",
@@ -8712,7 +8627,7 @@
                             }
                         },
                         "strip-ansi-cjs": {
-                            "version": "npm:strip-ansi-cjs@6.0.1",
+                            "version": "npm:strip-ansi@6.0.1",
                             "bundled": true,
                             "requires": {
                                 "ansi-regex": "^5.0.1"
@@ -8871,7 +8786,7 @@
                             }
                         },
                         "wrap-ansi-cjs": {
-                            "version": "npm:wrap-ansi-cjs@7.0.0",
+                            "version": "npm:wrap-ansi@7.0.0",
                             "bundled": true,
                             "requires": {
                                 "ansi-styles": "^4.0.0",
@@ -8903,9 +8818,9 @@
                     "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g=="
                 },
                 "postcss": {
-                    "version": "8.4.28",
-                    "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.28.tgz",
-                    "integrity": "sha512-Z7V5j0cq8oEKyejIKfpD8b4eBy9cwW2JWPk0+fB1HOAMsfHbnAXLLS+PfVWlzMSLQaWttKDt607I0XHmpE67Vw==",
+                    "version": "8.4.29",
+                    "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.29.tgz",
+                    "integrity": "sha512-cbI+jaqIeu/VGqXEarWkRCCffhjgXc0qjBtXpqJhTBohMUjUQnbBr0xqX3vEKudc4iviTewcJo5ajcec5+wdJw==",
                     "requires": {
                         "nanoid": "^3.3.6",
                         "picocolors": "^1.0.0",
@@ -10081,14 +9996,14 @@
                     }
                 },
                 "caniuse-lite": {
-                    "version": "1.0.30001524",
-                    "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001524.tgz",
-                    "integrity": "sha512-Jj917pJtYg9HSJBF95HVX3Cdr89JUyLT4IZ8SvM5aDRni95swKgYi3TgYLH5hnGfPE/U1dg6IfZ50UsIlLkwSA=="
+                    "version": "1.0.30001525",
+                    "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001525.tgz",
+                    "integrity": "sha512-/3z+wB4icFt3r0USMwxujAqRvaD/B7rvGTsKhbhSQErVrJvkZCLhgNLJxU8MevahQVH6hCU9FsHdNUFbiwmE7Q=="
                 },
                 "electron-to-chromium": {
-                    "version": "1.4.503",
-                    "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.503.tgz",
-                    "integrity": "sha512-LF2IQit4B0VrUHFeQkWhZm97KuJSGF2WJqq1InpY+ECpFRkXd8yTIaTtJxsO0OKDmiBYwWqcrNaXOurn2T2wiA=="
+                    "version": "1.4.506",
+                    "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.506.tgz",
+                    "integrity": "sha512-xxGct4GPAKSRlrLBtJxJFYy74W11zX6PO9GyHgl/U+2s3Dp0ZEwAklDfNHXOWcvH7zWMpsmgbR0ggEuaYAVvHA=="
                 }
             }
         },
@@ -10445,6 +10360,16 @@
             "integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=",
             "dev": true
         },
+        "d": {
+            "version": "1.0.1",
+            "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz",
+            "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==",
+            "dev": true,
+            "requires": {
+                "es5-ext": "^0.10.50",
+                "type": "^1.0.1"
+            }
+        },
         "d3": {
             "version": "7.8.4",
             "resolved": "https://registry.npmjs.org/d3/-/d3-7.8.4.tgz",
@@ -11825,6 +11750,28 @@
                 "is-symbol": "^1.0.2"
             }
         },
+        "es5-ext": {
+            "version": "0.10.62",
+            "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.62.tgz",
+            "integrity": "sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA==",
+            "dev": true,
+            "requires": {
+                "es6-iterator": "^2.0.3",
+                "es6-symbol": "^3.1.3",
+                "next-tick": "^1.1.0"
+            }
+        },
+        "es6-iterator": {
+            "version": "2.0.3",
+            "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz",
+            "integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==",
+            "dev": true,
+            "requires": {
+                "d": "1",
+                "es5-ext": "^0.10.35",
+                "es6-symbol": "^3.1.1"
+            }
+        },
         "es6-promise": {
             "version": "3.2.1",
             "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.2.1.tgz",
@@ -11836,6 +11783,7 @@
             "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==",
             "dev": true,
             "requires": {
+                "d": "^1.0.1",
                 "ext": "^1.1.2"
             }
         },
@@ -27648,6 +27596,12 @@
             "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
             "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q="
         },
+        "type": {
+            "version": "1.2.0",
+            "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz",
+            "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==",
+            "dev": true
+        },
         "type-check": {
             "version": "0.4.0",
             "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
diff --git a/package.json b/package.json
index 5f7289719..de44b31f3 100644
--- a/package.json
+++ b/package.json
@@ -178,7 +178,7 @@
         "body-parser": "^1.19.2",
         "bootstrap": "^4.6.1",
         "brotli": "^1.3.3",
-        "browndash-components": "^0.1.02",
+        "browndash-components": "^0.1.21",
         "browser-assert": "^1.2.1",
         "bson": "^4.6.1",
         "canvas": "^2.9.3",
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 539c62833..9f83f105e 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -773,8 +773,8 @@ export class CurrentUserUtils {
                             CurrentUserUtils.createToolButton(opts), scripts, funcs);
         
         const btnDescs = [// setup reactions to change the highlights on the undo/redo buttons -- would be better to encode this in the undo/redo buttons, but the undo/redo stacks are not wired up that way yet
-            { opts: { title: "Replicate",icon:"camera",toolTip: "Copy dashboard layout",btnType: ButtonType.ClickButton, expertMode: true},                                                                                               scripts: { onClick:  `snapshotDashboard()`}},
-            { opts: { title: "Recordings",            toolTip: "Workspace Recordings", btnType: ButtonType.DropdownList,expertMode: false, ignoreClick: true, width: 100}, funcs: {hidden: `false`, btnList:`getWorkspaceRecordings()`}, scripts: { script:  `{ return replayWorkspace(value, _readOnly_); }`}},
+            { opts: { title: "Replicate",icon:"camera",toolTip: "Copy dashboard layout",btnType: ButtonType.ClickButton, expertMode: true},                                                                                              scripts: { onClick:  `snapshotDashboard()`}},
+            { opts: { title: "Recordings",            toolTip: "Workspace Recordings", btnType: ButtonType.DropdownList,expertMode: false, ignoreClick: true, width: 100}, funcs: {hidden: `false`, btnList:`getWorkspaceRecordings()`}, scripts: { script:  `{ return replayWorkspace(value, _readOnly_); }`, onDragScript: `{ return startRecordingDrag(value); }`}},
             { opts: { title: "Stop Rec",icon: "stop", toolTip: "Stop recording",       btnType: ButtonType.ClickButton, expertMode: false}, funcs: {hidden: `!isWorkspaceRecording()`},                                                  scripts: { onClick: `stopWorkspaceRecording()`}},
             { opts: { title: "Play",    icon: "play", toolTip: "Play recording",       btnType: ButtonType.ClickButton, expertMode: false}, funcs: {hidden: `isWorkspaceReplaying() !== "${media_state.Paused}"`},                       scripts: { onClick: `resumeWorkspaceReplaying(getCurrentRecording())`}},
             { opts: { title: "Pause",   icon: "pause",toolTip: "Pause playback",       btnType: ButtonType.ClickButton, expertMode: false}, funcs: {hidden: `isWorkspaceReplaying() !== "${media_state.Playing}"`},                      scripts: { onClick: `pauseWorkspaceReplaying(getCurrentRecording())`}},
diff --git a/src/client/views/nodes/FontIconBox/FontIconBox.tsx b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
index 9bc9f2b52..ea7c2de82 100644
--- a/src/client/views/nodes/FontIconBox/FontIconBox.tsx
+++ b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
@@ -7,7 +7,7 @@ import * as React from 'react';
 import { Doc, DocListCast, StrListCast } from '../../../../fields/Doc';
 import { ScriptField } from '../../../../fields/ScriptField';
 import { BoolCast, Cast, DocCast, NumCast, ScriptCast, StrCast } from '../../../../fields/Types';
-import { Utils } from '../../../../Utils';
+import { emptyFunction, setupMoveUpEvents, Utils } from '../../../../Utils';
 import { CollectionViewType, DocumentType } from '../../../documents/DocumentTypes';
 import { SelectionManager } from '../../../util/SelectionManager';
 import { SettingsManager } from '../../../util/SettingsManager';
@@ -176,6 +176,18 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
         );
     }
 
+    dropdownItemDown = (e: React.PointerEvent, value: string | number) => {
+        setupMoveUpEvents(
+            this,
+            e,
+            (e: PointerEvent) => {
+                return ScriptCast(this.rootDoc.onDragScript)?.script.run({ this: this.layoutDoc, self: this.rootDoc, value: { doc: value, e } }).result;
+            },
+            emptyFunction,
+            emptyFunction
+        );
+    };
+
     /**
      * Dropdown list
      */
@@ -240,6 +252,7 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
                 background={SettingsManager.userVariantColor}
                 type={Type.TERT}
                 dropdownType={DropdownType.SELECT}
+                onItemDown={this.dropdownItemDown}
                 items={list}
                 tooltip={this.label}
                 fillWidth
diff --git a/src/client/views/nodes/RecordingBox/RecordingBox.tsx b/src/client/views/nodes/RecordingBox/RecordingBox.tsx
index 3412b2dd2..1f113110b 100644
--- a/src/client/views/nodes/RecordingBox/RecordingBox.tsx
+++ b/src/client/views/nodes/RecordingBox/RecordingBox.tsx
@@ -1,10 +1,11 @@
 import { action, observable } from 'mobx';
 import { observer } from 'mobx-react';
 import * as React from 'react';
+import { DateField } from '../../../../fields/DateField';
 import { Doc, DocListCast } from '../../../../fields/Doc';
 import { Id } from '../../../../fields/FieldSymbols';
-import { listSpec } from '../../../../fields/Schema';
-import { BoolCast, Cast, DocCast, StrCast } from '../../../../fields/Types';
+import { List } from '../../../../fields/List';
+import { BoolCast, DocCast } from '../../../../fields/Types';
 import { VideoField } from '../../../../fields/URLField';
 import { Upload } from '../../../../server/SharedMediaTypes';
 import { Docs } from '../../../documents/Documents';
@@ -17,12 +18,10 @@ import { Presentation } from '../../../util/TrackMovements';
 import { undoBatch } from '../../../util/UndoManager';
 import { CollectionFreeFormView } from '../../collections/collectionFreeForm/CollectionFreeFormView';
 import { ViewBoxBaseComponent } from '../../DocComponent';
+import { media_state } from '../AudioBox';
 import { FieldView, FieldViewProps } from '../FieldView';
 import { VideoBox } from '../VideoBox';
 import { RecordingView } from './RecordingView';
-import { DateField } from '../../../../fields/DateField';
-import { media_state } from '../AudioBox';
-import { List } from '../../../../fields/List';
 
 @observer
 export class RecordingBox extends ViewBoxBaseComponent<FieldViewProps>() {
@@ -87,15 +86,22 @@ export class RecordingBox extends ViewBoxBaseComponent<FieldViewProps>() {
      */
     @undoBatch
     @action
-    public static WorkspaceStartRecording() {
-        const screengrabber = Docs.Create.ScreenshotDocument({
-            title: `${new DateField()}-${Doc.ActiveDashboard?.title ?? ''}`,
-            _width: 205,
-            _height: 115,
-        });
+    public static WorkspaceStartRecording(value: string) {
+        const screengrabber =
+            value === 'Record Workspace'
+                ? Docs.Create.ScreenshotDocument({
+                      title: `${new DateField()}-${Doc.ActiveDashboard?.title ?? ''}`,
+                      _width: 205,
+                      _height: 115,
+                  })
+                : Docs.Create.WebCamDocument(`${new DateField()}-${Doc.ActiveDashboard?.title ?? ''}`, {
+                      title: `${new DateField()}-${Doc.ActiveDashboard?.title ?? ''}`,
+                      _width: 205,
+                      _height: 115,
+                  });
         screengrabber.overlayX = 70; //was -400
         screengrabber.overlayY = 590; //was 0
-        screengrabber[Doc.LayoutFieldKey(screengrabber) + '_trackScreen'] = true;
+        Doc.GetProto(screengrabber)[Doc.LayoutFieldKey(screengrabber) + '_trackScreen'] = true;
         Doc.AddToMyOverlay(screengrabber); //just adds doc to overlay
         DocumentManager.Instance.AddViewRenderedCb(screengrabber, docView => {
             RecordingBox.screengrabber = docView.ComponentView as RecordingBox;
@@ -204,9 +210,6 @@ export class RecordingBox extends ViewBoxBaseComponent<FieldViewProps>() {
     static screengrabber: RecordingBox | undefined;
 }
 
-ScriptingGlobals.add(function startWorkspaceRecording() {
-    RecordingBox.WorkspaceStartRecording();
-});
 ScriptingGlobals.add(function stopWorkspaceRecording() {
     RecordingBox.WorkspaceStopRecording();
 });
@@ -222,7 +225,7 @@ ScriptingGlobals.add(function getCurrentRecording() {
     return Doc.UserDoc().currentRecording;
 });
 ScriptingGlobals.add(function getWorkspaceRecordings() {
-    return new List<any>(['Record Workspace', ...DocListCast(Doc.UserDoc().workspaceRecordings)]);
+    return new List<any>(['Record Workspace', `Record Webcam`, ...DocListCast(Doc.UserDoc().workspaceRecordings)]);
 });
 ScriptingGlobals.add(function isWorkspaceRecording() {
     return Doc.UserDoc().workspaceRecordingState === media_state.Recording;
@@ -232,7 +235,7 @@ ScriptingGlobals.add(function isWorkspaceReplaying() {
 });
 ScriptingGlobals.add(function replayWorkspace(value: Doc | string, _readOnly_: boolean) {
     if (_readOnly_) return DocCast(Doc.UserDoc().currentRecording) ?? 'Record Workspace';
-    if (typeof value === 'string') RecordingBox.WorkspaceStartRecording();
+    if (typeof value === 'string') RecordingBox.WorkspaceStartRecording(value);
     else RecordingBox.replayWorkspace(value);
 });
 ScriptingGlobals.add(function pauseWorkspaceReplaying(value: Doc, _readOnly_: boolean) {
@@ -242,6 +245,13 @@ ScriptingGlobals.add(function resumeWorkspaceReplaying(value: Doc, _readOnly_: b
     RecordingBox.resumeWorkspaceReplaying(value);
 });
 
+ScriptingGlobals.add(function startRecordingDrag(value: { doc: Doc | string; e: React.PointerEvent }) {
+    if (DocCast(value.doc)) {
+        DragManager.StartDocumentDrag([value.e.target as HTMLElement], new DragManager.DocumentDragData([DocCast(value.doc)], 'embed'), value.e.clientX, value.e.clientY);
+        value.e.preventDefault();
+        return true;
+    }
+});
 ScriptingGlobals.add(function renderDropdown() {
     if (!Doc.UserDoc().workspaceRecordings || DocListCast(Doc.UserDoc().workspaceRecordings).length === 0) {
         return true;
diff --git a/src/client/views/nodes/ScreenshotBox.tsx b/src/client/views/nodes/ScreenshotBox.tsx
index 4ebc93165..26ad8b7bb 100644
--- a/src/client/views/nodes/ScreenshotBox.tsx
+++ b/src/client/views/nodes/ScreenshotBox.tsx
@@ -26,6 +26,7 @@ import { FieldView, FieldViewProps } from './FieldView';
 import { FormattedTextBox } from './formattedText/FormattedTextBox';
 import './ScreenshotBox.scss';
 import { VideoBox } from './VideoBox';
+import { TrackMovements } from '../../util/TrackMovements';
 
 declare class MediaRecorder {
     constructor(e: any, options?: any); // whatever MediaRecorder has
@@ -236,9 +237,19 @@ export class ScreenshotBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatabl
             this._videoRef!.srcObject = await (navigator.mediaDevices as any).getDisplayMedia({ video: true });
             this._videoRec = new MediaRecorder(this._videoRef!.srcObject);
             const vid_chunks: any = [];
-            this._videoRec.onstart = () => (this.dataDoc[this.props.fieldKey + '_recordingStart'] = new DateField(new Date()));
+            this._videoRec.onstart = () => {
+                if (this.dataDoc[this.props.fieldKey + '_trackScreen']) TrackMovements.Instance.start();
+                this.dataDoc[this.props.fieldKey + '_recordingStart'] = new DateField(new Date());
+            };
             this._videoRec.ondataavailable = (e: any) => vid_chunks.push(e.data);
             this._videoRec.onstop = async (e: any) => {
+                const presentation = TrackMovements.Instance.yieldPresentation();
+                if (presentation?.movements) {
+                    const presCopy = { ...presentation };
+                    presCopy.movements = presentation.movements.map(movement => ({ ...movement, doc: movement.doc[Id] })) as any;
+                    this.dataDoc[this.fieldKey + '_presentation'] = JSON.stringify(presCopy);
+                }
+                TrackMovements.Instance.finish();
                 const file = new File(vid_chunks, `${this.rootDoc[Id]}.mkv`, { type: vid_chunks[0].type, lastModified: Date.now() });
                 const [{ result }] = await Networking.UploadFilesToServer({ file });
                 this.dataDoc[this.fieldKey + '_duration'] = (new Date().getTime() - this.recordingStart!) / 1000;
-- 
cgit v1.2.3-70-g09d2


From a63ab5802551887f62265d420b7c5e925b5cd7d6 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Tue, 5 Sep 2023 01:26:54 -0400
Subject: added ui for specifying wehther to play a/v when following links, and
 cleaned up ui/etc for pres trails.  fixed a bunch of colors in pres
 properties.  fixed a/v anchors to be configs when not adding them to the doc,
 otherwise labels.

---
 src/client/util/DocumentManager.ts                 |   5 +-
 src/client/util/LinkFollower.ts                    |   1 +
 src/client/views/MainView.tsx                      |   2 +-
 src/client/views/PropertiesView.tsx                |  14 +-
 src/client/views/UndoStack.tsx                     |  69 ++++----
 .../collections/CollectionStackedTimeline.tsx      |   6 +-
 src/client/views/collections/TabDocView.tsx        |   6 +-
 src/client/views/nodes/AudioBox.tsx                |  28 +--
 src/client/views/nodes/DocumentView.tsx            |   1 +
 src/client/views/nodes/FontIconBox/FontIconBox.tsx |   1 -
 src/client/views/nodes/VideoBox.tsx                |  13 +-
 src/client/views/nodes/trails/PresBox.scss         |   6 -
 src/client/views/nodes/trails/PresBox.tsx          | 192 ++++++++++++++-------
 src/client/views/selectedDoc/SelectedDocView.tsx   |  61 +++----
 14 files changed, 244 insertions(+), 161 deletions(-)

(limited to 'src/client/views/nodes/FontIconBox/FontIconBox.tsx')

diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts
index 28ca37611..bfe0e1b48 100644
--- a/src/client/util/DocumentManager.ts
+++ b/src/client/util/DocumentManager.ts
@@ -1,9 +1,9 @@
-import { action, computed, observable, ObservableSet, observe, reaction } from 'mobx';
+import { action, computed, observable, ObservableSet, observe } from 'mobx';
 import { Doc, DocListCast, Opt } from '../../fields/Doc';
 import { AclAdmin, AclEdit, Animation } from '../../fields/DocSymbols';
 import { Id } from '../../fields/FieldSymbols';
 import { listSpec } from '../../fields/Schema';
-import { Cast, DocCast, StrCast } from '../../fields/Types';
+import { Cast, DocCast, NumCast, StrCast } from '../../fields/Types';
 import { AudioField } from '../../fields/URLField';
 import { GetEffectiveAcl } from '../../fields/util';
 import { CollectionViewType } from '../documents/DocumentTypes';
@@ -323,6 +323,7 @@ export class DocumentManager {
             if (docView.ComponentView instanceof FormattedTextBox) docView.ComponentView?.focus(viewSpec, options);
             PresBox.restoreTargetDocView(docView, viewSpec, options.zoomTime ?? 500);
             Doc.linkFollowHighlight(viewSpec ? [docView.rootDoc, viewSpec] : docView.rootDoc, undefined, options.effect);
+            if (options.playMedia) docView.ComponentView?.playFrom?.(NumCast(docView.rootDoc._layout_currentTimecode));
             if (options.playAudio) DocumentManager.playAudioAnno(docView.rootDoc);
             if (options.toggleTarget && (!options.didMove || docView.rootDoc.hidden)) docView.rootDoc.hidden = !docView.rootDoc.hidden;
             if (options.effect) docView.rootDoc[Animation] = options.effect;
diff --git a/src/client/util/LinkFollower.ts b/src/client/util/LinkFollower.ts
index b8fea340f..2fc811b09 100644
--- a/src/client/util/LinkFollower.ts
+++ b/src/client/util/LinkFollower.ts
@@ -73,6 +73,7 @@ export class LinkFollower {
                     const toggleTarget = canToggle && BoolCast(sourceDoc.followLinkToggle);
                     const options: DocFocusOptions = {
                         playAudio: BoolCast(sourceDoc.followLinkAudio),
+                        playMedia: BoolCast(sourceDoc.followLinkVideo),
                         toggleTarget,
                         noSelect: true,
                         willPan: true,
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 7ae9a374d..c8b89c1d5 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -805,7 +805,7 @@ export class MainView extends React.Component {
                         {this.dockingContent}
 
                         {this._hideUI ? null : (
-                            <div className="mainView-propertiesDragger" key="props" onPointerDown={this.onPropertiesPointerDown} style={{ background: SettingsManager.userBackgroundColor, right: this.propertiesWidth() - 1 }}>
+                            <div className="mainView-propertiesDragger" key="props" onPointerDown={this.onPropertiesPointerDown} style={{ background: SettingsManager.userVariantColor, right: this.propertiesWidth() - 1 }}>
                                 <FontAwesomeIcon icon={this.propertiesWidth() < 10 ? 'chevron-left' : 'chevron-right'} color={SettingsManager.userColor} size="sm" />
                             </div>
                         )}
diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx
index 5f9439cbc..01329b482 100644
--- a/src/client/views/PropertiesView.tsx
+++ b/src/client/views/PropertiesView.tsx
@@ -1538,6 +1538,16 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                                 <FontAwesomeIcon className="fa-icon" icon={faAnchor as IconLookup} size="lg" />
                             </button>
                         </div>
+                        <div className="propertiesView-input inline">
+                            <p>Play Target Video</p>
+                            <button
+                                style={{ background: !this.sourceAnchor?.followLinkVideo ? '' : '#4476f7', borderRadius: 3 }}
+                                onPointerDown={e => this.toggleAnchorProp(e, 'followLinkVideo', this.sourceAnchor)}
+                                onClick={e => e.stopPropagation()}
+                                className="propertiesButton">
+                                <FontAwesomeIcon className="fa-icon" icon={faAnchor as IconLookup} size="lg" />
+                            </button>
+                        </div>
                         <div className="propertiesView-input inline">
                             <p>Zoom Text Selections</p>
                             <button
@@ -1742,12 +1752,12 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                                         color: SettingsManager.userColor,
                                         backgroundColor: this.openPresVisibilityAndDuration ? SettingsManager.userVariantColor : SettingsManager.userBackgroundColor,
                                     }}>
-                                    &nbsp; <FontAwesomeIcon style={{ alignSelf: 'center' }} icon={'rocket'} /> &nbsp; Visibilty
+                                    &nbsp; <FontAwesomeIcon style={{ alignSelf: 'center' }} icon={'rocket'} /> &nbsp; Visibility
                                     <div className="propertiesView-presentationTrails-title-icon">
                                         <FontAwesomeIcon icon={this.openPresVisibilityAndDuration ? 'caret-down' : 'caret-right'} size="lg" />
                                     </div>
                                 </div>
-                                {this.openPresVisibilityAndDuration ? <div className="propertiesView-presentationTrails-content">{PresBox.Instance.visibiltyDurationDropdown}</div> : null}
+                                {this.openPresVisibilityAndDuration ? <div className="propertiesView-presentationTrails-content">{PresBox.Instance.visibilityDurationDropdown}</div> : null}
                             </div>
                         )}
                         {!selectedItem ? null : (
diff --git a/src/client/views/UndoStack.tsx b/src/client/views/UndoStack.tsx
index 47853b5e4..1afd5ad22 100644
--- a/src/client/views/UndoStack.tsx
+++ b/src/client/views/UndoStack.tsx
@@ -8,6 +8,7 @@ import { Doc } from '../../fields/Doc';
 import { Popup, Type, isDark } from 'browndash-components';
 import { Colors } from './global/globalEnums';
 import { SettingsManager } from '../util/SettingsManager';
+import { Tooltip } from '@mui/material';
 
 interface UndoStackProps {
     width?: number;
@@ -22,39 +23,43 @@ export class UndoStack extends React.Component<UndoStackProps> {
         const background = UndoManager.batchCounter.get() ? 'yellow' : SettingsManager.userVariantColor;
         const color = UndoManager.batchCounter.get() ? 'black' : SettingsManager.userColor;
         return this.props.inline && UndoStack.HideInline ? null : (
-            <div className="undoStack-outerContainer">
-                <Popup
-                    text="stack"
-                    color={color}
-                    background={background}
-                    placement={`top-start`}
-                    type={Type.TERT}
-                    popup={
-                        <div
-                            className="undoStack-commandsContainer"
-                            ref={r => r?.scroll({ behavior: 'auto', top: r?.scrollHeight + 20 })}
-                            style={{
-                                background,
-                                color,
-                            }}>
-                            {UndoManager.undoStackNames.map((name, i) => (
-                                <div className="undoStack-resultContainer" key={i}>
-                                    <div className="undoStack-commandString">{StrCast(name).replace(/[^\.]*\./, '')}</div>
-                                </div>
-                            ))}
-                            {Array.from(UndoManager.redoStackNames)
-                                .reverse()
-                                .map((name, i) => (
-                                    <div className="undoStack-resultContainer" key={i}>
-                                        <div className="undoStack-commandString" style={{ fontWeight: 'bold', color: SettingsManager.userBackgroundColor }}>
-                                            {StrCast(name).replace(/[^\.]*\./, '')}
+            <Tooltip title={'undo stack (if it stays yellow, undo is broken - you should reload Dash)'}>
+                <div>
+                    <div className="undoStack-outerContainer">
+                        <Popup
+                            text="stack"
+                            color={color}
+                            background={background}
+                            placement={`top-start`}
+                            type={Type.TERT}
+                            popup={
+                                <div
+                                    className="undoStack-commandsContainer"
+                                    ref={r => r?.scroll({ behavior: 'auto', top: r?.scrollHeight + 20 })}
+                                    style={{
+                                        background,
+                                        color,
+                                    }}>
+                                    {UndoManager.undoStackNames.map((name, i) => (
+                                        <div className="undoStack-resultContainer" key={i}>
+                                            <div className="undoStack-commandString">{StrCast(name).replace(/[^\.]*\./, '')}</div>
                                         </div>
-                                    </div>
-                                ))}
-                        </div>
-                    }
-                />
-            </div>
+                                    ))}
+                                    {Array.from(UndoManager.redoStackNames)
+                                        .reverse()
+                                        .map((name, i) => (
+                                            <div className="undoStack-resultContainer" key={i}>
+                                                <div className="undoStack-commandString" style={{ fontWeight: 'bold', color: SettingsManager.userBackgroundColor }}>
+                                                    {StrCast(name).replace(/[^\.]*\./, '')}
+                                                </div>
+                                            </div>
+                                        ))}
+                                </div>
+                            }
+                        />
+                    </div>
+                </div>
+            </Tooltip>
         );
     }
 }
diff --git a/src/client/views/collections/CollectionStackedTimeline.tsx b/src/client/views/collections/CollectionStackedTimeline.tsx
index d2be70577..0a5a80936 100644
--- a/src/client/views/collections/CollectionStackedTimeline.tsx
+++ b/src/client/views/collections/CollectionStackedTimeline.tsx
@@ -32,7 +32,7 @@ import './CollectionStackedTimeline.scss';
 export type CollectionStackedTimelineProps = {
     Play: () => void;
     Pause: () => void;
-    playLink: (linkDoc: Doc) => void;
+    playLink: (linkDoc: Doc, options: DocFocusOptions) => void;
     playFrom: (seekTimeInSeconds: number, endTime?: number) => void;
     playing: () => boolean;
     setTime: (time: number) => void;
@@ -677,7 +677,7 @@ interface StackedTimelineAnchorProps {
     height: number;
     toTimeline: (screen_delta: number, width: number) => number;
     styleProvider?: (doc: Opt<Doc>, props: Opt<DocumentViewProps>, property: string) => any;
-    playLink: (linkDoc: Doc) => void;
+    playLink: (linkDoc: Doc, options: DocFocusOptions) => void;
     setTime: (time: number) => void;
     startTag: string;
     endTag: string;
@@ -793,7 +793,7 @@ class StackedTimelineAnchor extends React.Component<StackedTimelineAnchorProps>
     renderInner = computedFn(function (this: StackedTimelineAnchor, mark: Doc, script: undefined | (() => ScriptField), doublescript: undefined | (() => ScriptField), screenXf: () => Transform, width: () => number, height: () => number) {
         const anchor = observable({ view: undefined as any });
         const focusFunc = (doc: Doc, options: DocFocusOptions): number | undefined => {
-            this.props.playLink(mark);
+            this.props.playLink(mark, options);
             return undefined;
         };
         return {
diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
index f6acafa95..6cdb84dea 100644
--- a/src/client/views/collections/TabDocView.tsx
+++ b/src/client/views/collections/TabDocView.tsx
@@ -278,10 +278,8 @@ export class TabDocView extends React.Component<TabDocViewProps> {
 
             if (pinProps.pinViewport) PresBox.pinDocView(pinDoc, pinProps, anchorDoc ?? doc);
             if (!pinProps?.audioRange && duration !== undefined) {
-                pinDoc.mediaStart = 'manual';
-                pinDoc.mediaStop = 'manual';
-                pinDoc.config_clipStart = NumCast(doc.clipStart);
-                pinDoc.config_clipEnd = NumCast(doc.clipEnd, duration);
+                pinDoc.presentation_mediaStart = 'manual';
+                pinDoc.presentation_mediaStop = 'manual';
             }
             if (pinProps?.activeFrame !== undefined) {
                 pinDoc.config_activeFrame = pinProps?.activeFrame;
diff --git a/src/client/views/nodes/AudioBox.tsx b/src/client/views/nodes/AudioBox.tsx
index 7c409c38c..50b2432d2 100644
--- a/src/client/views/nodes/AudioBox.tsx
+++ b/src/client/views/nodes/AudioBox.tsx
@@ -8,7 +8,7 @@ import { ComputedField } from '../../../fields/ScriptField';
 import { Cast, DateCast, NumCast } from '../../../fields/Types';
 import { AudioField, nullAudio } from '../../../fields/URLField';
 import { emptyFunction, formatTime, returnFalse, setupMoveUpEvents } from '../../../Utils';
-import { DocUtils } from '../../documents/Documents';
+import { Docs, DocUtils } from '../../documents/Documents';
 import { Networking } from '../../Network';
 import { DragManager } from '../../util/DragManager';
 import { LinkManager } from '../../util/LinkManager';
@@ -20,6 +20,7 @@ import { ViewBoxAnnotatableComponent, ViewBoxAnnotatableProps } from '../DocComp
 import './AudioBox.scss';
 import { FieldView, FieldViewProps } from './FieldView';
 import { PinProps, PresBox } from './trails';
+import { DocFocusOptions } from './DocumentView';
 
 /**
  * AudioBox
@@ -134,16 +135,19 @@ export class AudioBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
     }
 
     getAnchor = (addAsAnnotation: boolean, pinProps?: PinProps) => {
-        const anchor =
-            CollectionStackedTimeline.createAnchor(
-                this.rootDoc,
-                this.dataDoc,
-                this.annotationKey,
-                this._ele?.currentTime || Cast(this.props.Document._layout_currentTimecode, 'number', null) || (this.mediaState === media_state.Recording ? (Date.now() - (this.recordingStart || 0)) / 1000 : undefined),
-                undefined,
-                undefined,
-                addAsAnnotation
-            ) || this.rootDoc;
+        const timecode = Cast(this.layoutDoc._layout_currentTimecode, 'number', null);
+        const anchor = addAsAnnotation
+            ? CollectionStackedTimeline.createAnchor(
+                  this.rootDoc,
+                  this.dataDoc,
+                  this.annotationKey,
+                  this._ele?.currentTime || Cast(this.props.Document._layout_currentTimecode, 'number', null) || (this.mediaState === media_state.Recording ? (Date.now() - (this.recordingStart || 0)) / 1000 : undefined),
+                  undefined,
+                  undefined,
+                  addAsAnnotation
+              ) || this.rootDoc
+            : Docs.Create.ConfigDocument({ title: '#' + timecode, _timecodeToShow: timecode, annotationOn: this.rootDoc });
+
         PresBox.pinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: { ...(pinProps?.pinData ?? {}), temporal: true } }, this.rootDoc);
         return anchor;
     };
@@ -418,7 +422,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
     };
 
     // plays link
-    playLink = (link: Doc) => {
+    playLink = (link: Doc, options: DocFocusOptions) => {
         if (link.annotationOn === this.rootDoc) {
             if (!this.layoutDoc.dontAutoPlayFollowedLinks) {
                 this.playFrom(this.timeline?.anchorStart(link) || 0, this.timeline?.anchorEnd(link));
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 998024cea..f7773ff18 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -100,6 +100,7 @@ export interface DocFocusOptions {
     effect?: Doc; // animation effect for focus
     noSelect?: boolean; // whether target should be selected after focusing
     playAudio?: boolean; // whether to play audio annotation on focus
+    playMedia?: boolean; // whether to play start target videos
     openLocation?: OpenWhere; // where to open a missing document
     zoomTextSelections?: boolean; // whether to display a zoomed overlay of anchor text selections
     toggleTarget?: boolean; // whether to toggle target on and off
diff --git a/src/client/views/nodes/FontIconBox/FontIconBox.tsx b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
index ea7c2de82..1eb6fd51c 100644
--- a/src/client/views/nodes/FontIconBox/FontIconBox.tsx
+++ b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
@@ -19,7 +19,6 @@ import { SelectedDocView } from '../../selectedDoc';
 import { StyleProp } from '../../StyleProvider';
 import { OpenWhere } from '../DocumentView';
 import { FieldView, FieldViewProps } from '../FieldView';
-import { RichTextMenu } from '../formattedText/RichTextMenu';
 import './FontIconBox.scss';
 import TrailsIcon from './TrailsIcon';
 
diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx
index 56508abf6..9d9aa8a4b 100644
--- a/src/client/views/nodes/VideoBox.tsx
+++ b/src/client/views/nodes/VideoBox.tsx
@@ -29,7 +29,7 @@ import { ViewBoxAnnotatableComponent, ViewBoxAnnotatableProps } from '../DocComp
 import { MarqueeAnnotator } from '../MarqueeAnnotator';
 import { AnchorMenu } from '../pdf/AnchorMenu';
 import { StyleProp } from '../StyleProvider';
-import { DocumentView, OpenWhere } from './DocumentView';
+import { DocFocusOptions, DocumentView, OpenWhere } from './DocumentView';
 import { FieldView, FieldViewProps } from './FieldView';
 import { RecordingBox } from './RecordingBox';
 import { PinProps, PresBox } from './trails';
@@ -385,7 +385,9 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
         const timecode = Cast(this.layoutDoc._layout_currentTimecode, 'number', null);
         const marquee = AnchorMenu.Instance.GetAnchor?.(undefined, addAsAnnotation);
         if (!addAsAnnotation && marquee) marquee.backgroundColor = 'transparent';
-        const anchor = CollectionStackedTimeline.createAnchor(this.rootDoc, this.dataDoc, this.annotationKey, timecode ? timecode : undefined, undefined, marquee, addAsAnnotation) || this.rootDoc;
+        const anchor = addAsAnnotation
+            ? CollectionStackedTimeline.createAnchor(this.rootDoc, this.dataDoc, this.annotationKey, timecode ? timecode : undefined, undefined, marquee, addAsAnnotation) || this.rootDoc
+            : Docs.Create.ConfigDocument({ title: '#' + timecode, _timecodeToShow: timecode, annotationOn: this.rootDoc });
         PresBox.pinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: { ...(pinProps?.pinData ?? {}), temporal: true } }, this.rootDoc);
         return anchor;
     };
@@ -846,11 +848,11 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
     zoom = (zoom: number) => this.timeline?.setZoom(zoom);
 
     // plays link
-    playLink = (doc: Doc) => {
-        const startTime = Math.max(0, this._stackedTimeline?.anchorStart(doc) || 0);
+    playLink = (doc: Doc, options: DocFocusOptions) => {
+        const startTime = Math.max(0, NumCast(doc.config_clipStart, this._stackedTimeline?.anchorStart(doc) || 0));
         const endTime = this.timeline?.anchorEnd(doc);
         if (startTime !== undefined) {
-            if (!this.layoutDoc.dontAutoPlayFollowedLinks) endTime ? this.playFrom(startTime, endTime) : this.playFrom(startTime);
+            if (options.playMedia) endTime ? this.playFrom(startTime, endTime) : this.playFrom(startTime);
             else this.Seek(startTime);
         }
     };
@@ -1038,7 +1040,6 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
         this.props.bringToFront(cropping);
         return cropping;
     };
-
     savedAnnotations = () => this._savedAnnotations;
     render() {
         const borderRad = this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.BorderRounding);
diff --git a/src/client/views/nodes/trails/PresBox.scss b/src/client/views/nodes/trails/PresBox.scss
index bf56b4d9e..31a003144 100644
--- a/src/client/views/nodes/trails/PresBox.scss
+++ b/src/client/views/nodes/trails/PresBox.scss
@@ -187,9 +187,6 @@
         font-size: 11;
         font-weight: 200;
         height: 20;
-        background-color: $white;
-        color: $black;
-        border: solid 1px $black;
         display: flex;
         margin-left: 5px;
         margin-top: 5px;
@@ -210,13 +207,11 @@
 
         .ribbon-propertyUpDownItem {
             cursor: pointer;
-            color: white;
             display: flex;
             justify-content: center;
             align-items: center;
             height: 100%;
             width: 100%;
-            background: $black;
         }
 
         .ribbon-propertyUpDownItem:hover {
@@ -609,7 +604,6 @@
         font-weight: 200;
         height: 20;
         background-color: $white;
-        border: solid 1px rgba(0, 0, 0, 0.5);
         display: flex;
         color: $black;
         margin-top: 5px;
diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx
index 92c130ea1..48f376075 100644
--- a/src/client/views/nodes/trails/PresBox.tsx
+++ b/src/client/views/nodes/trails/PresBox.tsx
@@ -391,11 +391,11 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
             if (from?.mediaStopTriggerList && this.layoutDoc.presentation_status !== PresStatus.Edit) {
                 DocListCast(from.mediaStopTriggerList).forEach(this.stopTempMedia);
             }
-            if (from?.mediaStop === 'auto' && this.layoutDoc.presentation_status !== PresStatus.Edit) {
+            if (from?.presentation_mediaStop === 'auto' && this.layoutDoc.presentation_status !== PresStatus.Edit) {
                 this.stopTempMedia(from.presentation_targetDoc);
             }
             // If next slide is audio / video 'Play automatically' then the next slide should be played
-            if (this.layoutDoc.presentation_status !== PresStatus.Edit && (this.targetDoc.type === DocumentType.AUDIO || this.targetDoc.type === DocumentType.VID) && this.activeItem.mediaStart === 'auto') {
+            if (this.layoutDoc.presentation_status !== PresStatus.Edit && (this.targetDoc.type === DocumentType.AUDIO || this.targetDoc.type === DocumentType.VID) && this.activeItem.presentation_mediaStart === 'auto') {
                 this.startTempMedia(this.targetDoc, this.activeItem);
             }
             if (!group) this.clearSelectedArray();
@@ -798,8 +798,9 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
             easeFunc: StrCast(activeItem.presEaseFunc, 'ease') as any,
             zoomTextSelections: BoolCast(activeItem.presentation_zoomText),
             playAudio: BoolCast(activeItem.presPlayAudio),
+            playMedia: activeItem.presentation_mediaStart === 'auto',
         };
-        if (activeItem.presOpenInLightbox) {
+        if (activeItem.presentation_openInLightbox) {
             const context = DocCast(targetDoc.annotationOn) ?? targetDoc;
             if (!DocumentManager.Instance.getLightboxDocumentView(context)) {
                 LightboxView.SetLightboxDoc(context);
@@ -1075,8 +1076,6 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
             if (doc.type === DocumentType.LABEL) {
                 const audio = Cast(doc.annotationOn, Doc, null);
                 if (audio) {
-                    audio.mediaStart = 'manual';
-                    audio.mediaStop = 'manual';
                     audio.config_clipStart = NumCast(doc._timecodeToShow /* audioStart */, NumCast(doc._timecodeToShow /* videoStart */));
                     audio.config_clipEnd = NumCast(doc._timecodeToHide /* audioEnd */, NumCast(doc._timecodeToHide /* videoEnd */));
                     audio.presentation_duration = audio.config_clipStart - audio.config_clipEnd;
@@ -1472,8 +1471,8 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
     @undoBatch
     @action
     updateOpenDoc = (activeItem: Doc) => {
-        activeItem.presOpenInLightbox = !activeItem.presOpenInLightbox;
-        this.selectedArray.forEach(doc => (doc.presOpenInLightbox = activeItem.presOpenInLightbox));
+        activeItem.presentation_openInLightbox = !activeItem.presentation_openInLightbox;
+        this.selectedArray.forEach(doc => (doc.presentation_openInLightbox = activeItem.presentation_openInLightbox));
     };
 
     @undoBatch
@@ -1501,7 +1500,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                 max={max}
                 value={value}
                 readOnly={true}
-                style={{ marginLeft: hmargin, marginRight: hmargin, width: `calc(100% - ${2 * (hmargin ?? 0)}px)` }}
+                style={{ marginLeft: hmargin, marginRight: hmargin, width: `calc(100% - ${2 * (hmargin ?? 0)}px)`, background: SettingsManager.userColor, color: SettingsManager.userVariantColor }}
                 className={`toolbar-slider ${active ? '' : 'none'}`}
                 onPointerDown={e => {
                     PresBox._sliderBatch = UndoManager.StartBatch('pres slider');
@@ -1532,7 +1531,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
         });
     };
 
-    @computed get visibiltyDurationDropdown() {
+    @computed get visibilityDurationDropdown() {
         const activeItem = this.activeItem;
         if (activeItem && this.targetDoc) {
             const targetType = this.targetDoc.type;
@@ -1541,30 +1540,49 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
             return (
                 <div className="presBox-ribbon">
                     <div className="ribbon-doubleButton">
-                        <Tooltip title={<div className="dash-tooltip">{'Hide before presented'}</div>}>
-                            <div className={`ribbon-toggle ${activeItem.presentation_hideBefore ? 'active' : ''}`} onClick={() => this.updateHideBefore(activeItem)}>
+                        <Tooltip title={<div className="dash-tooltip">Hide before presented</div>}>
+                            <div
+                                className={`ribbon-toggle ${activeItem.presentation_hideBefore ? 'active' : ''}`}
+                                style={{ border: `solid 1px ${SettingsManager.userColor}`, color: SettingsManager.userColor, background: activeItem.presentation_hideBefore ? SettingsManager.userVariantColor : SettingsManager.userBackgroundColor }}
+                                onClick={() => this.updateHideBefore(activeItem)}>
                                 Hide before
                             </div>
                         </Tooltip>
                         <Tooltip title={<div className="dash-tooltip">{'Hide while presented'}</div>}>
-                            <div className={`ribbon-toggle ${activeItem.presentation_hide ? 'active' : ''}`} onClick={() => this.updateHide(activeItem)}>
+                            <div
+                                className={`ribbon-toggle ${activeItem.presentation_hide ? 'active' : ''}`}
+                                style={{ border: `solid 1px ${SettingsManager.userColor}`, color: SettingsManager.userColor, background: activeItem.presentation_hide ? SettingsManager.userVariantColor : SettingsManager.userBackgroundColor }}
+                                onClick={() => this.updateHide(activeItem)}>
                                 Hide
                             </div>
                         </Tooltip>
 
                         <Tooltip title={<div className="dash-tooltip">{'Hide after presented'}</div>}>
-                            <div className={`ribbon-toggle ${activeItem.presentation_hideAfter ? 'active' : ''}`} onClick={() => this.updateHideAfter(activeItem)}>
+                            <div
+                                className={`ribbon-toggle ${activeItem.presentation_hideAfter ? 'active' : ''}`}
+                                style={{ border: `solid 1px ${SettingsManager.userColor}`, color: SettingsManager.userColor, background: activeItem.presentation_hideAfter ? SettingsManager.userVariantColor : SettingsManager.userBackgroundColor }}
+                                onClick={() => this.updateHideAfter(activeItem)}>
                                 Hide after
                             </div>
                         </Tooltip>
 
                         <Tooltip title={<div className="dash-tooltip">{'Open in lightbox view'}</div>}>
-                            <div className="ribbon-toggle" style={{ backgroundColor: activeItem.presOpenInLightbox ? Colors.LIGHT_BLUE : '' }} onClick={() => this.updateOpenDoc(activeItem)}>
+                            <div
+                                className="ribbon-toggle"
+                                style={{
+                                    border: `solid 1px ${SettingsManager.userColor}`,
+                                    color: SettingsManager.userColor,
+                                    background: activeItem.presentation_openInLightbox ? SettingsManager.userVariantColor : SettingsManager.userBackgroundColor,
+                                }}
+                                onClick={() => this.updateOpenDoc(activeItem)}>
                                 Lightbox
                             </div>
                         </Tooltip>
-                        <Tooltip title={<div className="dash-tooltip">{'Transition movement style'}</div>}>
-                            <div className="ribbon-toggle" onClick={() => this.updateEaseFunc(activeItem)}>
+                        <Tooltip title={<div className="dash-tooltip">Transition movement style</div>}>
+                            <div
+                                className="ribbon-toggle"
+                                style={{ border: `solid 1px ${SettingsManager.userColor}`, color: SettingsManager.userColor, background: activeItem.presEaseFunc === 'ease' ? SettingsManager.userVariantColor : SettingsManager.userBackgroundColor }}
+                                onClick={() => this.updateEaseFunc(activeItem)}>
                                 {`${StrCast(activeItem.presEaseFunc, 'ease')}`}
                             </div>
                         </Tooltip>
@@ -1573,10 +1591,10 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                         <>
                             <div className="ribbon-doubleButton">
                                 <div className="presBox-subheading">Slide Duration</div>
-                                <div className="ribbon-property">
+                                <div className="ribbon-property" style={{ border: `solid 1px ${SettingsManager.userColor}` }}>
                                     <input className="presBox-input" type="number" readOnly={true} value={duration} onKeyDown={e => e.stopPropagation()} onChange={e => this.updateDurationTime(e.target.value)} /> s
                                 </div>
-                                <div className="ribbon-propertyUpDown">
+                                <div className="ribbon-propertyUpDown" style={{ color: SettingsManager.userBackgroundColor, background: SettingsManager.userColor }}>
                                     <div className="ribbon-propertyUpDownItem" onClick={() => this.updateDurationTime(String(duration), 1000)}>
                                         <FontAwesomeIcon icon={'caret-up'} />
                                     </div>
@@ -1615,7 +1633,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                         <div className="presBox-subheading">Progressivize Collection</div>
                         <input
                             className="presBox-checkbox"
-                            style={{ margin: 10 }}
+                            style={{ margin: 10, border: `solid 1px ${SettingsManager.userColor}` }}
                             type="checkbox"
                             onChange={() => {
                                 activeItem.presentation_indexed = activeItem.presentation_indexed === undefined ? 0 : undefined;
@@ -1638,7 +1656,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                         <div className="presBox-subheading">Progressivize First Bullet</div>
                         <input
                             className="presBox-checkbox"
-                            style={{ margin: 10 }}
+                            style={{ margin: 10, border: `solid 1px ${SettingsManager.userColor}` }}
                             type="checkbox"
                             onChange={() => (activeItem.presentation_indexedStart = activeItem.presentation_indexedStart ? 0 : 1)}
                             checked={!NumCast(activeItem.presentation_indexedStart)}
@@ -1646,7 +1664,13 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                     </div>
                     <div className="ribbon-doubleButton" style={{ display: 'inline-flex' }}>
                         <div className="presBox-subheading">Expand Current Bullet</div>
-                        <input className="presBox-checkbox" style={{ margin: 10 }} type="checkbox" onChange={() => (activeItem.presBulletExpand = !activeItem.presBulletExpand)} checked={BoolCast(activeItem.presBulletExpand)} />
+                        <input
+                            className="presBox-checkbox"
+                            style={{ margin: 10, border: `solid 1px ${SettingsManager.userColor}` }}
+                            type="checkbox"
+                            onChange={() => (activeItem.presBulletExpand = !activeItem.presBulletExpand)}
+                            checked={BoolCast(activeItem.presBulletExpand)}
+                        />
                     </div>
 
                     <div className="ribbon-box">
@@ -1657,10 +1681,18 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                                 e.stopPropagation();
                                 this._openBulletEffectDropdown = !this._openBulletEffectDropdown;
                             })}
-                            style={{ borderBottomLeftRadius: this._openBulletEffectDropdown ? 0 : 5, border: this._openBulletEffectDropdown ? `solid 2px ${Colors.MEDIUM_BLUE}` : 'solid 1px black' }}>
+                            style={{
+                                color: SettingsManager.userColor,
+                                background: SettingsManager.userVariantColor,
+                                borderBottomLeftRadius: this._openBulletEffectDropdown ? 0 : 5,
+                                border: this._openBulletEffectDropdown ? `solid 2px ${SettingsManager.userVariantColor}` : `solid 1px ${SettingsManager.userColor}`,
+                            }}>
                             {effect?.toString()}
                             <FontAwesomeIcon className="presBox-dropdownIcon" style={{ gridColumn: 2, color: this._openBulletEffectDropdown ? Colors.MEDIUM_BLUE : 'black' }} icon={'angle-down'} />
-                            <div className={'presBox-dropdownOptions'} style={{ display: this._openBulletEffectDropdown ? 'grid' : 'none' }} onPointerDown={e => e.stopPropagation()}>
+                            <div
+                                className={'presBox-dropdownOptions'}
+                                style={{ display: this._openBulletEffectDropdown ? 'grid' : 'none', color: SettingsManager.userColor, background: SettingsManager.userBackgroundColor }}
+                                onPointerDown={e => e.stopPropagation()}>
                                 {bulletEffect(PresEffect.None)}
                                 {bulletEffect(PresEffect.Fade)}
                                 {bulletEffect(PresEffect.Flip)}
@@ -1725,7 +1757,12 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                                 e.stopPropagation();
                                 this._openMovementDropdown = !this._openMovementDropdown;
                             })}
-                            style={{ borderBottomLeftRadius: this._openMovementDropdown ? 0 : 5, border: this._openMovementDropdown ? `solid 2px ${Colors.MEDIUM_BLUE}` : 'solid 1px black' }}>
+                            style={{
+                                color: SettingsManager.userColor,
+                                background: SettingsManager.userVariantColor,
+                                borderBottomLeftRadius: this._openMovementDropdown ? 0 : 5,
+                                border: this._openMovementDropdown ? `solid 2px ${SettingsManager.userVariantColor}` : `solid 1px ${SettingsManager.userColor}`,
+                            }}>
                             {this.movementName(activeItem)}
                             <FontAwesomeIcon className="presBox-dropdownIcon" style={{ gridColumn: 2, color: this._openMovementDropdown ? Colors.MEDIUM_BLUE : 'black' }} icon={'angle-down'} />
                             <div className={'presBox-dropdownOptions'} id={'presBoxMovementDropdown'} onPointerDown={StopEvent} style={{ display: this._openMovementDropdown ? 'grid' : 'none' }}>
@@ -1738,10 +1775,10 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                         </div>
                         <div className="ribbon-doubleButton" style={{ display: activeItem.presentation_movement === PresMovement.Zoom ? 'inline-flex' : 'none' }}>
                             <div className="presBox-subheading">Zoom (% screen filled)</div>
-                            <div className="ribbon-property">
+                            <div className="ribbon-property" style={{ border: `solid 1px ${SettingsManager.userColor}` }}>
                                 <input className="presBox-input" type="number" readOnly={true} value={zoom} onChange={e => this.updateZoom(e.target.value)} />%
                             </div>
-                            <div className="ribbon-propertyUpDown">
+                            <div className="ribbon-propertyUpDown" style={{ color: SettingsManager.userBackgroundColor, background: SettingsManager.userColor }}>
                                 <div className="ribbon-propertyUpDownItem" onClick={() => this.updateZoom(String(zoom), 0.1)}>
                                     <FontAwesomeIcon icon={'caret-up'} />
                                 </div>
@@ -1753,10 +1790,10 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                         {PresBox.inputter('0', '1', '100', zoom, activeItem.presentation_movement === PresMovement.Zoom, this.updateZoom)}
                         <div className="ribbon-doubleButton" style={{ display: 'inline-flex' }}>
                             <div className="presBox-subheading">Transition Time</div>
-                            <div className="ribbon-property">
+                            <div className="ribbon-property" style={{ border: `solid 1px ${SettingsManager.userColor}` }}>
                                 <input className="presBox-input" type="number" readOnly={true} value={transitionSpeed} onKeyDown={e => e.stopPropagation()} onChange={action(e => this.updateTransitionTime(e.target.value))} /> s
                             </div>
-                            <div className="ribbon-propertyUpDown">
+                            <div className="ribbon-propertyUpDown" style={{ color: SettingsManager.userBackgroundColor, background: SettingsManager.userColor }}>
                                 <div className="ribbon-propertyUpDownItem" onClick={() => this.updateTransitionTime(String(transitionSpeed), 1000)}>
                                     <FontAwesomeIcon icon={'caret-up'} />
                                 </div>
@@ -1776,13 +1813,19 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                         Effects
                         <div className="ribbon-doubleButton" style={{ display: 'inline-flex' }}>
                             <div className="presBox-subheading">Play Audio Annotation</div>
-                            <input className="presBox-checkbox" style={{ margin: 10 }} type="checkbox" onChange={() => (activeItem.presPlayAudio = !BoolCast(activeItem.presPlayAudio))} checked={BoolCast(activeItem.presPlayAudio)} />
+                            <input
+                                className="presBox-checkbox"
+                                style={{ margin: 10, border: `solid 1px ${SettingsManager.userColor}` }}
+                                type="checkbox"
+                                onChange={() => (activeItem.presPlayAudio = !BoolCast(activeItem.presPlayAudio))}
+                                checked={BoolCast(activeItem.presPlayAudio)}
+                            />
                         </div>
                         <div className="ribbon-doubleButton" style={{ display: 'inline-flex' }}>
                             <div className="presBox-subheading">Zoom Text Selections</div>
                             <input
                                 className="presBox-checkbox"
-                                style={{ margin: 10 }}
+                                style={{ margin: 10, border: `solid 1px ${SettingsManager.userColor}` }}
                                 type="checkbox"
                                 onChange={() => (activeItem.presentation_zoomText = !BoolCast(activeItem.presentation_zoomText))}
                                 checked={BoolCast(activeItem.presentation_zoomText)}
@@ -1794,7 +1837,12 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                                 e.stopPropagation();
                                 this._openEffectDropdown = !this._openEffectDropdown;
                             })}
-                            style={{ borderBottomLeftRadius: this._openEffectDropdown ? 0 : 5, border: this._openEffectDropdown ? `solid 2px ${Colors.MEDIUM_BLUE}` : 'solid 1px black' }}>
+                            style={{
+                                color: SettingsManager.userColor,
+                                background: SettingsManager.userVariantColor,
+                                borderBottomLeftRadius: this._openEffectDropdown ? 0 : 5,
+                                border: this._openEffectDropdown ? `solid 2px ${SettingsManager.userVariantColor}` : `solid 1px ${SettingsManager.userColor}`,
+                            }}>
                             {effect?.toString()}
                             <FontAwesomeIcon className="presBox-dropdownIcon" style={{ gridColumn: 2, color: this._openEffectDropdown ? Colors.MEDIUM_BLUE : 'black' }} icon={'angle-down'} />
                             <div className={'presBox-dropdownOptions'} id={'presBoxMovementDropdown'} style={{ display: this._openEffectDropdown ? 'grid' : 'none' }} onPointerDown={e => e.stopPropagation()}>
@@ -1808,7 +1856,9 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                         </div>
                         <div className="ribbon-doubleButton" style={{ display: effect === PresEffectDirection.None ? 'none' : 'inline-flex' }}>
                             <div className="presBox-subheading">Effect direction</div>
-                            <div className="ribbon-property">{StrCast(this.activeItem.presentation_effectDirection)}</div>
+                            <div className="ribbon-property" style={{ border: `solid 1px ${SettingsManager.userColor}` }}>
+                                {StrCast(this.activeItem.presentation_effectDirection)}
+                            </div>
                         </div>
                         <div className="effectDirection" style={{ display: effect === PresEffectDirection.None ? 'none' : 'grid', width: 40 }}>
                             {presDirection(PresEffectDirection.Left, 'angle-right', 1, 2, {})}
@@ -1830,8 +1880,10 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
     @computed get mediaOptionsDropdown() {
         const activeItem = this.activeItem;
         if (activeItem && this.targetDoc) {
-            const clipStart = NumCast(activeItem.clipStart);
-            const clipEnd = NumCast(activeItem.clipEnd, NumCast(activeItem[Doc.LayoutFieldKey(activeItem) + '_duration']));
+            const renderTarget = PresBox.targetRenderedDoc(this.activeItem);
+            const clipStart = NumCast(renderTarget.clipStart);
+            const clipEnd = NumCast(renderTarget.clipEnd, clipStart + NumCast(renderTarget[Doc.LayoutFieldKey(renderTarget) + '_duration']));
+            const config_clipEnd = NumCast(activeItem.config_clipEnd) < NumCast(activeItem.config_clipStart) ? clipEnd - clipStart : NumCast(activeItem.config_clipEnd);
             return (
                 <div className={'presBox-ribbon'} onClick={e => e.stopPropagation()} onPointerUp={e => e.stopPropagation()} onPointerDown={e => e.stopPropagation()}>
                     <div>
@@ -1842,7 +1894,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                                     <div className="slider-text" style={{ fontWeight: 500 }}>
                                         Start time (s)
                                     </div>
-                                    <div id={'startTime'} className="slider-number" style={{ backgroundColor: Colors.LIGHT_GRAY }}>
+                                    <div id="startTime" className="slider-number" style={{ color: SettingsManager.userColor, backgroundColor: SettingsManager.userBackgroundColor }}>
                                         <input
                                             className="presBox-input"
                                             style={{ textAlign: 'center', width: '100%', height: 15, fontSize: 10 }}
@@ -1850,9 +1902,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                                             readOnly={true}
                                             value={NumCast(activeItem.config_clipStart).toFixed(2)}
                                             onKeyDown={e => e.stopPropagation()}
-                                            onChange={action((e: React.ChangeEvent<HTMLInputElement>) => {
-                                                activeItem.config_clipStart = Number(e.target.value);
-                                            })}
+                                            onChange={action(e => (activeItem.config_clipStart = Number(e.target.value)))}
                                         />
                                     </div>
                                 </div>
@@ -1860,25 +1910,23 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                                     <div className="slider-text" style={{ fontWeight: 500 }}>
                                         Duration (s)
                                     </div>
-                                    <div className="slider-number" style={{ backgroundColor: Colors.LIGHT_BLUE }}>
-                                        {Math.round((NumCast(activeItem.config_clipEnd) - NumCast(activeItem.config_clipStart)) * 10) / 10}
+                                    <div className="slider-number" style={{ color: SettingsManager.userColor, backgroundColor: SettingsManager.userBackgroundColor }}>
+                                        {Math.round((config_clipEnd - NumCast(activeItem.config_clipStart)) * 10) / 10}
                                     </div>
                                 </div>
                                 <div className="slider-block">
                                     <div className="slider-text" style={{ fontWeight: 500 }}>
                                         End time (s)
                                     </div>
-                                    <div id={'endTime'} className="slider-number" style={{ backgroundColor: Colors.LIGHT_GRAY }}>
+                                    <div id="endTime" className="slider-number" style={{ color: SettingsManager.userColor, backgroundColor: SettingsManager.userBackgroundColor }}>
                                         <input
                                             className="presBox-input"
                                             onKeyDown={e => e.stopPropagation()}
                                             style={{ textAlign: 'center', width: '100%', height: 15, fontSize: 10 }}
                                             type="number"
                                             readOnly={true}
-                                            value={NumCast(activeItem.config_clipEnd).toFixed(2)}
-                                            onChange={action((e: React.ChangeEvent<HTMLInputElement>) => {
-                                                activeItem.config_clipEnd = Number(e.target.value);
-                                            })}
+                                            value={config_clipEnd.toFixed(2)}
+                                            onChange={action(e => (activeItem.config_clipEnd = Number(e.target.value)))}
                                         />
                                     </div>
                                 </div>
@@ -1889,16 +1937,15 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                                     step="0.1"
                                     min={clipStart}
                                     max={clipEnd}
-                                    value={NumCast(activeItem.config_clipEnd)}
-                                    style={{ gridColumn: 1, gridRow: 1 }}
+                                    value={config_clipEnd}
+                                    style={{ gridColumn: 1, gridRow: 1, background: SettingsManager.userColor, color: SettingsManager.userVariantColor }}
                                     className={`toolbar-slider ${'end'}`}
                                     id="toolbar-slider"
                                     onPointerDown={e => {
                                         this._batch = UndoManager.StartBatch('config_clipEnd');
                                         const endBlock = document.getElementById('endTime');
                                         if (endBlock) {
-                                            endBlock.style.color = Colors.LIGHT_GRAY;
-                                            endBlock.style.backgroundColor = Colors.MEDIUM_BLUE;
+                                            endBlock.style.backgroundColor = SettingsManager.userVariantColor;
                                         }
                                         e.stopPropagation();
                                     }}
@@ -1906,8 +1953,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                                         this._batch?.end();
                                         const endBlock = document.getElementById('endTime');
                                         if (endBlock) {
-                                            endBlock.style.color = Colors.BLACK;
-                                            endBlock.style.backgroundColor = Colors.LIGHT_GRAY;
+                                            endBlock.style.backgroundColor = SettingsManager.userBackgroundColor;
                                         }
                                     }}
                                     onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
@@ -1928,8 +1974,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                                         this._batch = UndoManager.StartBatch('config_clipStart');
                                         const startBlock = document.getElementById('startTime');
                                         if (startBlock) {
-                                            startBlock.style.color = Colors.LIGHT_GRAY;
-                                            startBlock.style.backgroundColor = Colors.MEDIUM_BLUE;
+                                            startBlock.style.backgroundColor = SettingsManager.userVariantColor;
                                         }
                                         e.stopPropagation();
                                     }}
@@ -1937,8 +1982,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                                         this._batch?.end();
                                         const startBlock = document.getElementById('startTime');
                                         if (startBlock) {
-                                            startBlock.style.color = Colors.BLACK;
-                                            startBlock.style.backgroundColor = Colors.LIGHT_GRAY;
+                                            startBlock.style.backgroundColor = SettingsManager.userBackgroundColor;
                                         }
                                     }}
                                     onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
@@ -1958,22 +2002,46 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                             <div className="presBox-subheading">Start playing:</div>
                             <div className="presBox-radioButtons">
                                 <div className="checkbox-container">
-                                    <input className="presBox-checkbox" type="checkbox" onChange={() => (activeItem.mediaStart = 'manual')} checked={activeItem.mediaStart === 'manual'} />
+                                    <input
+                                        className="presBox-checkbox"
+                                        type="checkbox"
+                                        style={{ border: `solid 1px ${SettingsManager.userColor}` }}
+                                        onChange={() => (activeItem.presentation_mediaStart = 'manual')}
+                                        checked={activeItem.presentation_mediaStart === 'manual'}
+                                    />
                                     <div>On click</div>
                                 </div>
                                 <div className="checkbox-container">
-                                    <input className="presBox-checkbox" type="checkbox" onChange={() => (activeItem.mediaStart = 'auto')} checked={activeItem.mediaStart === 'auto'} />
+                                    <input
+                                        className="presBox-checkbox"
+                                        style={{ border: `solid 1px ${SettingsManager.userColor}` }}
+                                        type="checkbox"
+                                        onChange={() => (activeItem.presentation_mediaStart = 'auto')}
+                                        checked={activeItem.presentation_mediaStart === 'auto'}
+                                    />
                                     <div>Automatically</div>
                                 </div>
                             </div>
                             <div className="presBox-subheading">Stop playing:</div>
                             <div className="presBox-radioButtons">
                                 <div className="checkbox-container">
-                                    <input className="presBox-checkbox" type="checkbox" onChange={() => (activeItem.mediaStop = 'manual')} checked={activeItem.mediaStop === 'manual'} />
-                                    <div>At audio end time</div>
+                                    <input
+                                        className="presBox-checkbox"
+                                        type="checkbox"
+                                        style={{ border: `solid 1px ${SettingsManager.userColor}` }}
+                                        onChange={() => (activeItem.presentation_mediaStop = 'manual')}
+                                        checked={activeItem.presentation_mediaStop === 'manual'}
+                                    />
+                                    <div>At media end time</div>
                                 </div>
                                 <div className="checkbox-container">
-                                    <input className="presBox-checkbox" type="checkbox" onChange={() => (activeItem.mediaStop = 'auto')} checked={activeItem.mediaStop === 'auto'} />
+                                    <input
+                                        className="presBox-checkbox"
+                                        type="checkbox"
+                                        style={{ border: `solid 1px ${SettingsManager.userColor}` }}
+                                        onChange={() => (activeItem.presentation_mediaStop = 'auto')}
+                                        checked={activeItem.presentation_mediaStop === 'auto'}
+                                    />
                                     <div>On slide change</div>
                                 </div>
                                 {/* <div className="checkbox-container">
@@ -2221,8 +2289,8 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
         const propTitle = SettingsManager.propertiesWidth > 0 ? 'Close Presentation Panel' : 'Open Presentation Panel';
         const mode = StrCast(this.rootDoc._type_collection) as CollectionViewType;
         const isMini: boolean = this.toolbarWidth <= 100;
-        const activeColor = Colors.LIGHT_BLUE;
-        const inactiveColor = Colors.WHITE;
+        const activeColor = SettingsManager.userVariantColor;
+        const inactiveColor = SettingsManager.userColor;
         return mode === CollectionViewType.Carousel3D || Doc.IsInMyOverlay(this.rootDoc) ? null : (
             <div id="toolbarContainer" className={'presBox-toolbar'}>
                 {/* <Tooltip title={<><div className="dash-tooltip">{"Add new slide"}</div></>}><div className={`toolbar-button ${this.newDocumentTools ? "active" : ""}`} onClick={action(() => this.newDocumentTools = !this.newDocumentTools)}>
diff --git a/src/client/views/selectedDoc/SelectedDocView.tsx b/src/client/views/selectedDoc/SelectedDocView.tsx
index 955a4a174..2139919e0 100644
--- a/src/client/views/selectedDoc/SelectedDocView.tsx
+++ b/src/client/views/selectedDoc/SelectedDocView.tsx
@@ -1,12 +1,14 @@
 import React = require('react');
-import { Doc } from "../../../fields/Doc";
-import { observer } from "mobx-react";
-import { computed } from "mobx";
-import { StrCast } from "../../../fields/Types";
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { Colors, ListBox } from 'browndash-components';
+import { ListBox } from 'browndash-components';
+import { computed } from 'mobx';
+import { observer } from 'mobx-react';
+import { Doc } from '../../../fields/Doc';
+import { StrCast } from '../../../fields/Types';
 import { DocumentManager } from '../../util/DocumentManager';
 import { DocFocusOptions } from '../nodes/DocumentView';
+import { emptyFunction } from '../../../Utils';
+import { SettingsManager } from '../../util/SettingsManager';
 
 export interface SelectedDocViewProps {
     selectedDocs: Doc[];
@@ -14,34 +16,33 @@ export interface SelectedDocViewProps {
 
 @observer
 export class SelectedDocView extends React.Component<SelectedDocViewProps> {
-
     @computed get selectedDocs() {
         return this.props.selectedDocs;
     }
-    
 
     render() {
-        return <div className={`selectedDocView-container`}>
-            <ListBox
-                items={this.selectedDocs.map((doc) => {
-                    const icon = Doc.toIcon(doc);
-                    const iconEle = <FontAwesomeIcon size={'1x'} icon={icon} />;
-                    const text = StrCast(doc.title)
-                    const finished = () => {
-                        
-                    };
-                    const options: DocFocusOptions = {
-                        playAudio: false,
-                    };
-                    return {
-                        text: text,
-                        val: StrCast(doc._id),
-                        icon: iconEle,
-                        onClick: () => {DocumentManager.Instance.showDocument(doc, options, finished);}
-                    }
-                })}
-                color={StrCast(Doc.UserDoc().userColor)}
-            />
-        </div>
+        return (
+            <div className="selectedDocView-container">
+                <ListBox
+                    items={this.selectedDocs.map(doc => {
+                        const options: DocFocusOptions = {
+                            playAudio: false,
+                            playMedia: false,
+                            willPan: true,
+                        };
+                        return {
+                            text: StrCast(doc.title),
+                            val: StrCast(doc._id),
+                            color: SettingsManager.userColor,
+                            background: SettingsManager.userBackgroundColor,
+                            icon: <FontAwesomeIcon size={'1x'} icon={Doc.toIcon(doc)} />,
+                            onClick: () => DocumentManager.Instance.showDocument(doc, options, emptyFunction),
+                        };
+                    })}
+                    color={SettingsManager.userColor}
+                    background={SettingsManager.userBackgroundColor}
+                />
+            </div>
+        );
     }
-}
\ No newline at end of file
+}
-- 
cgit v1.2.3-70-g09d2


From 888ddd78737781f8a2d045b5f1e41788c512c94d Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Fri, 8 Sep 2023 17:02:49 -0400
Subject: don't remove current recording from overlay, added closeOnSelect
 option  for dropdown.   place recording box on screen.  fixe overlayView to
 keep views on screen. fixed schema view checkboxes. don't cause tab to
 rerender when colelctoin type changes.  add dropdown to filter indicator to
 find filters.

---
 package-lock.json                                  | 166 +++++++++++++--------
 package.json                                       |   2 +-
 src/client/util/CurrentUserUtils.ts                |   1 -
 src/client/util/SettingsManager.tsx                |   6 +-
 src/client/util/reportManager/ReportManager.tsx    |   2 +
 src/client/views/DashboardView.tsx                 |   1 +
 src/client/views/MainView.tsx                      |   6 +-
 src/client/views/OverlayView.tsx                   |  15 ++
 src/client/views/PropertiesButtons.tsx             |   1 +
 src/client/views/PropertiesView.tsx                |  39 +++--
 src/client/views/StyleProvider.scss                |   9 +-
 src/client/views/StyleProvider.tsx                 |  41 ++++-
 src/client/views/UndoStack.tsx                     |  12 +-
 src/client/views/collections/TabDocView.tsx        |  10 +-
 .../collectionSchema/CollectionSchemaView.tsx      |   8 +-
 src/client/views/nodes/FontIconBox/FontIconBox.tsx |   3 +-
 .../views/nodes/RecordingBox/RecordingBox.tsx      |   9 +-
 17 files changed, 213 insertions(+), 118 deletions(-)

(limited to 'src/client/views/nodes/FontIconBox/FontIconBox.tsx')

diff --git a/package-lock.json b/package-lock.json
index b6c03c6ba..6055e9d1e 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -142,20 +142,20 @@
             "integrity": "sha512-5UamI7xkUcJ3i9qVDS+KFDEK8/7oJ55/sJMB1Ge7IEapr7KfdfV/HErR+koZwOfd+SgtFKOKRhRakdg++DcJpQ=="
         },
         "@babel/core": {
-            "version": "7.22.15",
-            "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.15.tgz",
-            "integrity": "sha512-PtZqMmgRrvj8ruoEOIwVA3yoF91O+Hgw9o7DAUTNBA6Mo2jpu31clx9a7Nz/9JznqetTR6zwfC4L3LAjKQXUwA==",
+            "version": "7.22.17",
+            "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.17.tgz",
+            "integrity": "sha512-2EENLmhpwplDux5PSsZnSbnSkB3tZ6QTksgO25xwEL7pIDcNOMhF5v/s6RzwjMZzZzw9Ofc30gHv5ChCC8pifQ==",
             "requires": {
                 "@ampproject/remapping": "^2.2.0",
                 "@babel/code-frame": "^7.22.13",
                 "@babel/generator": "^7.22.15",
                 "@babel/helper-compilation-targets": "^7.22.15",
-                "@babel/helper-module-transforms": "^7.22.15",
+                "@babel/helper-module-transforms": "^7.22.17",
                 "@babel/helpers": "^7.22.15",
-                "@babel/parser": "^7.22.15",
+                "@babel/parser": "^7.22.16",
                 "@babel/template": "^7.22.15",
-                "@babel/traverse": "^7.22.15",
-                "@babel/types": "^7.22.15",
+                "@babel/traverse": "^7.22.17",
+                "@babel/types": "^7.22.17",
                 "convert-source-map": "^1.7.0",
                 "debug": "^4.1.0",
                 "gensync": "^1.0.0-beta.2",
@@ -209,9 +209,9 @@
                     }
                 },
                 "@babel/traverse": {
-                    "version": "7.22.15",
-                    "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.15.tgz",
-                    "integrity": "sha512-DdHPwvJY0sEeN4xJU5uRLmZjgMMDIvMPniLuYzUVXj/GGzysPl0/fwt44JBkyUIzGJPV8QgHMcQdQ34XFuKTYQ==",
+                    "version": "7.22.17",
+                    "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.17.tgz",
+                    "integrity": "sha512-xK4Uwm0JnAMvxYZxOVecss85WxTEIbTa7bnGyf/+EgCL5Zt3U7htUpEOWv9detPlamGKuRzCqw74xVglDWpPdg==",
                     "requires": {
                         "@babel/code-frame": "^7.22.13",
                         "@babel/generator": "^7.22.15",
@@ -219,16 +219,16 @@
                         "@babel/helper-function-name": "^7.22.5",
                         "@babel/helper-hoist-variables": "^7.22.5",
                         "@babel/helper-split-export-declaration": "^7.22.6",
-                        "@babel/parser": "^7.22.15",
-                        "@babel/types": "^7.22.15",
+                        "@babel/parser": "^7.22.16",
+                        "@babel/types": "^7.22.17",
                         "debug": "^4.1.0",
                         "globals": "^11.1.0"
                     }
                 },
                 "@babel/types": {
-                    "version": "7.22.15",
-                    "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.15.tgz",
-                    "integrity": "sha512-X+NLXr0N8XXmN5ZsaQdm9U2SSC3UbIYq/doL++sueHOTisgZHoKaQtZxGuV2cUPQHMfjKEfg/g6oy7Hm6SKFtA==",
+                    "version": "7.22.17",
+                    "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.17.tgz",
+                    "integrity": "sha512-YSQPHLFtQNE5xN9tHuZnzu8vPr61wVTBZdfv1meex1NBosa4iT05k/Jw06ddJugi4bk7The/oSwQGFcksmEJQg==",
                     "requires": {
                         "@babel/helper-string-parser": "^7.22.5",
                         "@babel/helper-validator-identifier": "^7.22.15",
@@ -300,9 +300,9 @@
                     "integrity": "sha512-4E/F9IIEi8WR94324mbDUMo074YTheJmd7eZF5vITTeYchqAi6sYXRLHUVsmkdmY4QjfKTcB2jB7dVP3NaBElQ=="
                 },
                 "@babel/types": {
-                    "version": "7.22.15",
-                    "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.15.tgz",
-                    "integrity": "sha512-X+NLXr0N8XXmN5ZsaQdm9U2SSC3UbIYq/doL++sueHOTisgZHoKaQtZxGuV2cUPQHMfjKEfg/g6oy7Hm6SKFtA==",
+                    "version": "7.22.17",
+                    "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.17.tgz",
+                    "integrity": "sha512-YSQPHLFtQNE5xN9tHuZnzu8vPr61wVTBZdfv1meex1NBosa4iT05k/Jw06ddJugi4bk7The/oSwQGFcksmEJQg==",
                     "requires": {
                         "@babel/helper-string-parser": "^7.22.5",
                         "@babel/helper-validator-identifier": "^7.22.15",
@@ -472,9 +472,9 @@
                     "integrity": "sha512-4E/F9IIEi8WR94324mbDUMo074YTheJmd7eZF5vITTeYchqAi6sYXRLHUVsmkdmY4QjfKTcB2jB7dVP3NaBElQ=="
                 },
                 "@babel/types": {
-                    "version": "7.22.15",
-                    "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.15.tgz",
-                    "integrity": "sha512-X+NLXr0N8XXmN5ZsaQdm9U2SSC3UbIYq/doL++sueHOTisgZHoKaQtZxGuV2cUPQHMfjKEfg/g6oy7Hm6SKFtA==",
+                    "version": "7.22.17",
+                    "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.17.tgz",
+                    "integrity": "sha512-YSQPHLFtQNE5xN9tHuZnzu8vPr61wVTBZdfv1meex1NBosa4iT05k/Jw06ddJugi4bk7The/oSwQGFcksmEJQg==",
                     "requires": {
                         "@babel/helper-string-parser": "^7.22.5",
                         "@babel/helper-validator-identifier": "^7.22.15",
@@ -492,9 +492,9 @@
             }
         },
         "@babel/helper-module-transforms": {
-            "version": "7.22.15",
-            "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.22.15.tgz",
-            "integrity": "sha512-l1UiX4UyHSFsYt17iQ3Se5pQQZZHa22zyIXURmvkmLCD4t/aU+dvNWHatKac/D9Vm9UES7nvIqHs4jZqKviUmQ==",
+            "version": "7.22.17",
+            "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.22.17.tgz",
+            "integrity": "sha512-XouDDhQESrLHTpnBtCKExJdyY4gJCdrvH2Pyv8r8kovX2U8G0dRUOT45T9XlbLtuu9CLXP15eusnkprhoPV5iQ==",
             "requires": {
                 "@babel/helper-environment-visitor": "^7.22.5",
                 "@babel/helper-module-imports": "^7.22.15",
@@ -517,9 +517,9 @@
                     "integrity": "sha512-4E/F9IIEi8WR94324mbDUMo074YTheJmd7eZF5vITTeYchqAi6sYXRLHUVsmkdmY4QjfKTcB2jB7dVP3NaBElQ=="
                 },
                 "@babel/types": {
-                    "version": "7.22.15",
-                    "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.15.tgz",
-                    "integrity": "sha512-X+NLXr0N8XXmN5ZsaQdm9U2SSC3UbIYq/doL++sueHOTisgZHoKaQtZxGuV2cUPQHMfjKEfg/g6oy7Hm6SKFtA==",
+                    "version": "7.22.17",
+                    "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.17.tgz",
+                    "integrity": "sha512-YSQPHLFtQNE5xN9tHuZnzu8vPr61wVTBZdfv1meex1NBosa4iT05k/Jw06ddJugi4bk7The/oSwQGFcksmEJQg==",
                     "requires": {
                         "@babel/helper-string-parser": "^7.22.5",
                         "@babel/helper-validator-identifier": "^7.22.15",
@@ -542,13 +542,13 @@
             "integrity": "sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ=="
         },
         "@babel/helper-remap-async-to-generator": {
-            "version": "7.22.9",
-            "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.9.tgz",
-            "integrity": "sha512-8WWC4oR4Px+tr+Fp0X3RHDVfINGpF3ad1HIbrc8A77epiR6eMMc6jsgozkzT2uDiOOdoS9cLIQ+XD2XvI2WSmQ==",
+            "version": "7.22.17",
+            "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.17.tgz",
+            "integrity": "sha512-bxH77R5gjH3Nkde6/LuncQoLaP16THYPscurp1S8z7S9ZgezCyV3G8Hc+TZiCmY8pz4fp8CvKSgtJMW0FkLAxA==",
             "requires": {
                 "@babel/helper-annotate-as-pure": "^7.22.5",
                 "@babel/helper-environment-visitor": "^7.22.5",
-                "@babel/helper-wrap-function": "^7.22.9"
+                "@babel/helper-wrap-function": "^7.22.17"
             },
             "dependencies": {
                 "@babel/helper-annotate-as-pure": {
@@ -611,28 +611,64 @@
             "integrity": "sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA=="
         },
         "@babel/helper-wrap-function": {
-            "version": "7.22.10",
-            "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.22.10.tgz",
-            "integrity": "sha512-OnMhjWjuGYtdoO3FmsEFWvBStBAe2QOgwOLsLNDjN+aaiMD8InJk1/O3HSD8lkqTjCgg5YI34Tz15KNNA3p+nQ==",
+            "version": "7.22.17",
+            "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.22.17.tgz",
+            "integrity": "sha512-nAhoheCMlrqU41tAojw9GpVEKDlTS8r3lzFmF0lP52LwblCPbuFSO7nGIZoIcoU5NIm1ABrna0cJExE4Ay6l2Q==",
             "requires": {
                 "@babel/helper-function-name": "^7.22.5",
-                "@babel/template": "^7.22.5",
-                "@babel/types": "^7.22.10"
+                "@babel/template": "^7.22.15",
+                "@babel/types": "^7.22.17"
             },
             "dependencies": {
-                "@babel/helper-validator-identifier": {
+                "@babel/code-frame": {
+                    "version": "7.22.13",
+                    "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz",
+                    "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==",
+                    "requires": {
+                        "@babel/highlight": "^7.22.13",
+                        "chalk": "^2.4.2"
+                    }
+                },
+                "@babel/highlight": {
+                    "version": "7.22.13",
+                    "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.13.tgz",
+                    "integrity": "sha512-C/BaXcnnvBCmHTpz/VGZ8jgtE2aYlW4hxDhseJAWZb7gqGM/qtCK6iZUb0TyKFf7BOUsBH7Q7fkRsDRhg1XklQ==",
+                    "requires": {
+                        "@babel/helper-validator-identifier": "^7.22.5",
+                        "chalk": "^2.4.2",
+                        "js-tokens": "^4.0.0"
+                    }
+                },
+                "@babel/parser": {
+                    "version": "7.22.16",
+                    "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.16.tgz",
+                    "integrity": "sha512-+gPfKv8UWeKKeJTUxe59+OobVcrYHETCsORl61EmSkmgymguYk/X5bp7GuUIXaFsc6y++v8ZxPsLSSuujqDphA=="
+                },
+                "@babel/template": {
                     "version": "7.22.15",
-                    "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.15.tgz",
-                    "integrity": "sha512-4E/F9IIEi8WR94324mbDUMo074YTheJmd7eZF5vITTeYchqAi6sYXRLHUVsmkdmY4QjfKTcB2jB7dVP3NaBElQ=="
+                    "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz",
+                    "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==",
+                    "requires": {
+                        "@babel/code-frame": "^7.22.13",
+                        "@babel/parser": "^7.22.15",
+                        "@babel/types": "^7.22.15"
+                    }
                 },
                 "@babel/types": {
-                    "version": "7.22.15",
-                    "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.15.tgz",
-                    "integrity": "sha512-X+NLXr0N8XXmN5ZsaQdm9U2SSC3UbIYq/doL++sueHOTisgZHoKaQtZxGuV2cUPQHMfjKEfg/g6oy7Hm6SKFtA==",
+                    "version": "7.22.17",
+                    "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.17.tgz",
+                    "integrity": "sha512-YSQPHLFtQNE5xN9tHuZnzu8vPr61wVTBZdfv1meex1NBosa4iT05k/Jw06ddJugi4bk7The/oSwQGFcksmEJQg==",
                     "requires": {
                         "@babel/helper-string-parser": "^7.22.5",
                         "@babel/helper-validator-identifier": "^7.22.15",
                         "to-fast-properties": "^2.0.0"
+                    },
+                    "dependencies": {
+                        "@babel/helper-validator-identifier": {
+                            "version": "7.22.15",
+                            "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.15.tgz",
+                            "integrity": "sha512-4E/F9IIEi8WR94324mbDUMo074YTheJmd7eZF5vITTeYchqAi6sYXRLHUVsmkdmY4QjfKTcB2jB7dVP3NaBElQ=="
+                        }
                     }
                 }
             }
@@ -693,9 +729,9 @@
                     }
                 },
                 "@babel/traverse": {
-                    "version": "7.22.15",
-                    "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.15.tgz",
-                    "integrity": "sha512-DdHPwvJY0sEeN4xJU5uRLmZjgMMDIvMPniLuYzUVXj/GGzysPl0/fwt44JBkyUIzGJPV8QgHMcQdQ34XFuKTYQ==",
+                    "version": "7.22.17",
+                    "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.17.tgz",
+                    "integrity": "sha512-xK4Uwm0JnAMvxYZxOVecss85WxTEIbTa7bnGyf/+EgCL5Zt3U7htUpEOWv9detPlamGKuRzCqw74xVglDWpPdg==",
                     "requires": {
                         "@babel/code-frame": "^7.22.13",
                         "@babel/generator": "^7.22.15",
@@ -703,16 +739,16 @@
                         "@babel/helper-function-name": "^7.22.5",
                         "@babel/helper-hoist-variables": "^7.22.5",
                         "@babel/helper-split-export-declaration": "^7.22.6",
-                        "@babel/parser": "^7.22.15",
-                        "@babel/types": "^7.22.15",
+                        "@babel/parser": "^7.22.16",
+                        "@babel/types": "^7.22.17",
                         "debug": "^4.1.0",
                         "globals": "^11.1.0"
                     }
                 },
                 "@babel/types": {
-                    "version": "7.22.15",
-                    "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.15.tgz",
-                    "integrity": "sha512-X+NLXr0N8XXmN5ZsaQdm9U2SSC3UbIYq/doL++sueHOTisgZHoKaQtZxGuV2cUPQHMfjKEfg/g6oy7Hm6SKFtA==",
+                    "version": "7.22.17",
+                    "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.17.tgz",
+                    "integrity": "sha512-YSQPHLFtQNE5xN9tHuZnzu8vPr61wVTBZdfv1meex1NBosa4iT05k/Jw06ddJugi4bk7The/oSwQGFcksmEJQg==",
                     "requires": {
                         "@babel/helper-string-parser": "^7.22.5",
                         "@babel/helper-validator-identifier": "^7.22.15",
@@ -1691,9 +1727,9 @@
                     }
                 },
                 "@babel/types": {
-                    "version": "7.22.15",
-                    "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.15.tgz",
-                    "integrity": "sha512-X+NLXr0N8XXmN5ZsaQdm9U2SSC3UbIYq/doL++sueHOTisgZHoKaQtZxGuV2cUPQHMfjKEfg/g6oy7Hm6SKFtA==",
+                    "version": "7.22.17",
+                    "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.17.tgz",
+                    "integrity": "sha512-YSQPHLFtQNE5xN9tHuZnzu8vPr61wVTBZdfv1meex1NBosa4iT05k/Jw06ddJugi4bk7The/oSwQGFcksmEJQg==",
                     "requires": {
                         "@babel/helper-string-parser": "^7.22.5",
                         "@babel/helper-validator-identifier": "^7.22.15",
@@ -2028,9 +2064,9 @@
                     "integrity": "sha512-4E/F9IIEi8WR94324mbDUMo074YTheJmd7eZF5vITTeYchqAi6sYXRLHUVsmkdmY4QjfKTcB2jB7dVP3NaBElQ=="
                 },
                 "@babel/types": {
-                    "version": "7.22.15",
-                    "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.15.tgz",
-                    "integrity": "sha512-X+NLXr0N8XXmN5ZsaQdm9U2SSC3UbIYq/doL++sueHOTisgZHoKaQtZxGuV2cUPQHMfjKEfg/g6oy7Hm6SKFtA==",
+                    "version": "7.22.17",
+                    "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.17.tgz",
+                    "integrity": "sha512-YSQPHLFtQNE5xN9tHuZnzu8vPr61wVTBZdfv1meex1NBosa4iT05k/Jw06ddJugi4bk7The/oSwQGFcksmEJQg==",
                     "requires": {
                         "@babel/helper-string-parser": "^7.22.5",
                         "@babel/helper-validator-identifier": "^7.22.15",
@@ -6651,9 +6687,9 @@
             }
         },
         "browndash-components": {
-            "version": "0.1.23",
-            "resolved": "https://registry.npmjs.org/browndash-components/-/browndash-components-0.1.23.tgz",
-            "integrity": "sha512-yZPnSUBXdToufaq4mTYHMgDwrijQWsuVKK8j+NilRKMqmOrkZeqyRhncTDz077DcMLcjeIj+SobT3GPK04TXmQ==",
+            "version": "0.1.25",
+            "resolved": "https://registry.npmjs.org/browndash-components/-/browndash-components-0.1.25.tgz",
+            "integrity": "sha512-YgzUsfeUKwtaOLRYNDcxybZG2Ip7KSQV38VbUrgC+ycwOX/tzq9IWlfw2z4h/EVuVcq+ERCaBS4pb3mMU6pKGQ==",
             "requires": {
                 "@emotion/react": "^11.11.1",
                 "@emotion/styled": "^11.11.0",
@@ -10110,14 +10146,14 @@
                     }
                 },
                 "caniuse-lite": {
-                    "version": "1.0.30001528",
-                    "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001528.tgz",
-                    "integrity": "sha512-0Db4yyjR9QMNlsxh+kKWzQtkyflkG/snYheSzkjmvdEtEXB1+jt7A2HmSEiO6XIJPIbo92lHNGNySvE5pZcs5Q=="
+                    "version": "1.0.30001529",
+                    "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001529.tgz",
+                    "integrity": "sha512-n2pUQYGAkrLG4QYj2desAh+NqsJpHbNmVZz87imptDdxLAtjxary7Df/psdfyDGmskJK/9Dt9cPnx5RZ3CU4Og=="
                 },
                 "electron-to-chromium": {
-                    "version": "1.4.510",
-                    "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.510.tgz",
-                    "integrity": "sha512-xPfLIPFcN/WLXBpQ/K4UgE98oUBO5Tia6BD4rkSR0wE7ep/PwBVlgvPJQrIBpmJGVAmUzwPKuDbVt9XV6+uC2g=="
+                    "version": "1.4.513",
+                    "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.513.tgz",
+                    "integrity": "sha512-cOB0xcInjm+E5qIssHeXJ29BaUyWpMyFKT5RB3bsLENDheCja0wMkHJyiPl0NBE/VzDI7JDuNEQWhe6RitEUcw=="
                 }
             }
         },
diff --git a/package.json b/package.json
index c218d80ff..9f0b91628 100644
--- a/package.json
+++ b/package.json
@@ -178,7 +178,7 @@
         "body-parser": "^1.19.2",
         "bootstrap": "^4.6.1",
         "brotli": "^1.3.3",
-        "browndash-components": "^0.1.23",
+        "browndash-components": "^0.1.25",
         "browser-assert": "^1.2.1",
         "bson": "^4.6.1",
         "canvas": "^2.9.3",
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index aa5f2658a..8bedea562 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -763,7 +763,6 @@ export class CurrentUserUtils {
     }
     /// Initializes all the default buttons for the top bar context menu
     static setupTopbarButtons(doc: Doc, field="myTopBarBtns") {
-        if (Doc.UserDoc().currentRecording) Doc.RemFromMyOverlay(DocCast(Doc.UserDoc().currentRecording));
         Doc.UserDoc().currentRecording = undefined;
         Doc.UserDoc().workspaceRecordingState = undefined;
         Doc.UserDoc().workspaceReplayingState = undefined;
diff --git a/src/client/util/SettingsManager.tsx b/src/client/util/SettingsManager.tsx
index 720badd40..53cfbc947 100644
--- a/src/client/util/SettingsManager.tsx
+++ b/src/client/util/SettingsManager.tsx
@@ -142,6 +142,7 @@ export class SettingsManager extends React.Component<{}> {
                     formLabel="Theme"
                     size={Size.SMALL}
                     type={Type.TERT}
+                    closeOnSelect={false}
                     selectedVal={userTheme}
                     setSelectedVal={scheme => this.changeColorScheme(scheme as string)}
                     items={colorSchemes.map((scheme, i) => ({
@@ -294,6 +295,7 @@ export class SettingsManager extends React.Component<{}> {
                                         },
                                     };
                                 })}
+                                closeOnSelect={true}
                                 dropdownType={DropdownType.SELECT}
                                 type={Type.TERT}
                                 selectedVal={StrCast(Doc.UserDoc().fontFamily)}
@@ -373,6 +375,7 @@ export class SettingsManager extends React.Component<{}> {
                     <div className="tab-column-content">
                         <Dropdown
                             formLabel={'Mode'}
+                            closeOnSelect={true}
                             items={[
                                 {
                                     text: 'Novice',
@@ -403,7 +406,8 @@ export class SettingsManager extends React.Component<{}> {
                     </div>
                     <div className="tab-column-content">
                         <Dropdown
-                            formLabel={'Scroll Mode'}
+                            formLabel="Scroll Mode"
+                            closeOnSelect={true}
                             items={[
                                 {
                                     text: 'Scroll to Pan',
diff --git a/src/client/util/reportManager/ReportManager.tsx b/src/client/util/reportManager/ReportManager.tsx
index 6a236face..08467448d 100644
--- a/src/client/util/reportManager/ReportManager.tsx
+++ b/src/client/util/reportManager/ReportManager.tsx
@@ -308,6 +308,7 @@ export class ReportManager extends React.Component<{}> {
                     <Dropdown
                         color={StrCast(Doc.UserDoc().userColor)}
                         formLabel={'Type'}
+                        closeOnSelect={true}
                         items={bugDropdownItems}
                         selectedVal={this.formData.type}
                         setSelectedVal={val => {
@@ -320,6 +321,7 @@ export class ReportManager extends React.Component<{}> {
                     <Dropdown
                         color={StrCast(Doc.UserDoc().userColor)}
                         formLabel={'Priority'}
+                        closeOnSelect={true}
                         items={priorityDropdownItems}
                         selectedVal={this.formData.priority}
                         setSelectedVal={val => {
diff --git a/src/client/views/DashboardView.tsx b/src/client/views/DashboardView.tsx
index 1d1d0eaab..014a6358f 100644
--- a/src/client/views/DashboardView.tsx
+++ b/src/client/views/DashboardView.tsx
@@ -371,6 +371,7 @@ export class DashboardView extends React.Component {
 
         Doc.AddDocToList(Doc.MyHeaderBar, 'data', freeformDoc);
         dashboardDoc['pane-count'] = 1;
+        freeformDoc.embedContainer = dashboardDoc;
 
         Doc.AddDocToList(Doc.MyDashboards, 'data', dashboardDoc);
 
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 8adb28fe1..2b4f4d5f7 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -810,7 +810,11 @@ export class MainView extends React.Component {
                             </div>
                         )}
                         <div className="properties-container" style={{ width: this.propertiesWidth(), color: SettingsManager.userColor }}>
-                            {this.propertiesWidth() < 10 ? null : <PropertiesView styleProvider={DefaultStyleProvider} addDocTab={DocumentViewInternal.addDocTabFunc} width={this.propertiesWidth()} height={this.propertiesHeight()} />}
+                            {
+                                <div style={{ display: this.propertiesWidth() < 10 ? 'none' : undefined }}>
+                                    <PropertiesView styleProvider={DefaultStyleProvider} addDocTab={DocumentViewInternal.addDocTabFunc} width={this.propertiesWidth()} height={this.propertiesHeight()} />
+                                </div>
+                            }
                         </div>
                     </div>
                 </div>
diff --git a/src/client/views/OverlayView.tsx b/src/client/views/OverlayView.tsx
index 5d95c5fda..c174befc0 100644
--- a/src/client/views/OverlayView.tsx
+++ b/src/client/views/OverlayView.tsx
@@ -16,6 +16,7 @@ import { LightboxView } from './LightboxView';
 import { DocumentView, DocumentViewInternal } from './nodes/DocumentView';
 import './OverlayView.scss';
 import { DefaultStyleProvider } from './StyleProvider';
+const _global = (window /* browser */ || global) /* node */ as any;
 
 export type OverlayDisposer = () => void;
 
@@ -115,6 +116,20 @@ export class OverlayView extends React.Component {
         super(props);
         if (!OverlayView.Instance) {
             OverlayView.Instance = this;
+            new _global.ResizeObserver(
+                action((entries: any) => {
+                    for (const entry of entries) {
+                        DocListCast(Doc.MyOverlayDocs?.data).forEach(doc => {
+                            if (NumCast(doc.overlayX) > entry.contentRect.width - 10) {
+                                doc.overlayX = entry.contentRect.width - 10;
+                            }
+                            if (NumCast(doc.overlayY) > entry.contentRect.height - 10) {
+                                doc.overlayY = entry.contentRect.height - 10;
+                            }
+                        });
+                    }
+                })
+            ).observe(window.document.body);
         }
     }
 
diff --git a/src/client/views/PropertiesButtons.tsx b/src/client/views/PropertiesButtons.tsx
index 42db0b9be..d939470e9 100644
--- a/src/client/views/PropertiesButtons.tsx
+++ b/src/client/views/PropertiesButtons.tsx
@@ -376,6 +376,7 @@ export class PropertiesButtons extends React.Component<{}, {}> {
             <Dropdown
                 tooltip={'Choose onClick behavior'}
                 items={items}
+                closeOnSelect={true}
                 selectedVal={this.onClickVal}
                 setSelectedVal={val => this.handleOptionChange(val as string)}
                 title={'Choose onClick behaviour'}
diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx
index 72ff906f6..9cc75b1c6 100644
--- a/src/client/views/PropertiesView.tsx
+++ b/src/client/views/PropertiesView.tsx
@@ -52,6 +52,12 @@ interface PropertiesViewProps {
 export class PropertiesView extends React.Component<PropertiesViewProps> {
     private _widthUndo?: UndoManager.Batch;
 
+    public static Instance: PropertiesView | undefined;
+    constructor(props: any) {
+        super(props);
+        PropertiesView.Instance = this;
+    }
+
     @computed get MAX_EMBED_HEIGHT() {
         return 200;
     }
@@ -75,6 +81,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
     }
 
     @observable layoutFields: boolean = false;
+    @observable layoutDocAcls: boolean = false;
 
     @observable openOptions: boolean = true;
     @observable openSharing: boolean = true;
@@ -86,8 +93,6 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
     @observable openTransform: boolean = true;
     @observable openFilters: boolean = false;
 
-    @observable layoutDocAcls: boolean = false;
-
     //Pres Trails booleans:
     @observable openPresTransitions: boolean = true;
     @observable openPresProgressivize: boolean = false;
@@ -103,7 +108,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
         this._disposers.link = reaction(
             () => LinkManager.currentLink,
             link => {
-                link && this.onDoubleClick();
+                link && this.CloseAll();
                 link && (this.openLinks = true);
             },
             { fireImmediately: true }
@@ -970,7 +975,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
     };
 
     @action
-    onDoubleClick = () => {
+    CloseAll = () => {
         this.openContexts = false;
         this.openLinks = false;
         this.openOptions = false;
@@ -1120,7 +1125,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                 isOpen={this.openOptions}
                 setInSection={bool => (this.inOptions = bool)}
                 setIsOpen={bool => (this.openOptions = bool)}
-                onDoubleClick={this.onDoubleClick}
+                onDoubleClick={this.CloseAll}
             />
         );
     }
@@ -1147,7 +1152,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                 }
                 isOpen={this.openSharing}
                 setIsOpen={bool => (this.openSharing = bool)}
-                onDoubleClick={() => this.onDoubleClick()}
+                onDoubleClick={() => this.CloseAll()}
             />
         );
     }
@@ -1187,7 +1192,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                 }
                 isOpen={this.openFilters}
                 setIsOpen={bool => (this.openFilters = bool)}
-                onDoubleClick={() => this.onDoubleClick()}
+                onDoubleClick={() => this.CloseAll()}
             />
         );
     }
@@ -1197,8 +1202,8 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
 
         return (
             <>
-                <PropertiesSection title="Appearance" content={this.isInk ? this.appearanceEditor : null} isOpen={this.openAppearance} setIsOpen={bool => (this.openAppearance = bool)} onDoubleClick={() => this.onDoubleClick()} />
-                <PropertiesSection title="Transform" content={this.transformEditor} isOpen={this.openTransform} setIsOpen={bool => (this.openTransform = bool)} onDoubleClick={() => this.onDoubleClick()} />
+                <PropertiesSection title="Appearance" content={this.isInk ? this.appearanceEditor : null} isOpen={this.openAppearance} setIsOpen={bool => (this.openAppearance = bool)} onDoubleClick={() => this.CloseAll()} />
+                <PropertiesSection title="Transform" content={this.transformEditor} isOpen={this.openTransform} setIsOpen={bool => (this.openTransform = bool)} onDoubleClick={() => this.CloseAll()} />
             </>
         );
     }
@@ -1210,29 +1215,23 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                 content={<div className="propertiesView-content fields">{Doc.noviceMode ? this.noviceFields : this.expandedField}</div>}
                 isOpen={this.openFields}
                 setIsOpen={bool => (this.openFields = bool)}
-                onDoubleClick={() => this.onDoubleClick()}
+                onDoubleClick={() => this.CloseAll()}
             />
         );
     }
 
     @computed get contextsSubMenu() {
         return (
-            <PropertiesSection
-                title="Other Contexts"
-                content={this.contextCount > 0 ? this.contexts : 'There are no other contexts.'}
-                isOpen={this.openContexts}
-                setIsOpen={bool => (this.openContexts = bool)}
-                onDoubleClick={() => this.onDoubleClick()}
-            />
+            <PropertiesSection title="Other Contexts" content={this.contextCount > 0 ? this.contexts : 'There are no other contexts.'} isOpen={this.openContexts} setIsOpen={bool => (this.openContexts = bool)} onDoubleClick={() => this.CloseAll()} />
         );
     }
 
     @computed get linksSubMenu() {
-        return <PropertiesSection title="Linked To" content={this.linkCount > 0 ? this.links : 'There are no current links.'} isOpen={this.openLinks} setIsOpen={bool => (this.openLinks = bool)} onDoubleClick={this.onDoubleClick} />;
+        return <PropertiesSection title="Linked To" content={this.linkCount > 0 ? this.links : 'There are no current links.'} isOpen={this.openLinks} setIsOpen={bool => (this.openLinks = bool)} onDoubleClick={this.CloseAll} />;
     }
 
     @computed get layoutSubMenu() {
-        return <PropertiesSection title="Layout" content={this.layoutPreview} isOpen={this.openLayout} setIsOpen={bool => (this.openLayout = bool)} onDoubleClick={this.onDoubleClick} />;
+        return <PropertiesSection title="Layout" content={this.layoutPreview} isOpen={this.openLayout} setIsOpen={bool => (this.openLayout = bool)} onDoubleClick={this.CloseAll} />;
     }
 
     @computed get description() {
@@ -1723,7 +1722,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                         {this.contextsSubMenu}
                         {this.fieldsSubMenu}
                         {isNovice ? null : this.sharingSubMenu}
-                        {isNovice ? null : this.filtersSubMenu}
+                        {this.filtersSubMenu}
                         {isNovice ? null : this.layoutSubMenu}
                     </div>
                 );
diff --git a/src/client/views/StyleProvider.scss b/src/client/views/StyleProvider.scss
index c06bb287e..f069e7e1b 100644
--- a/src/client/views/StyleProvider.scss
+++ b/src/client/views/StyleProvider.scss
@@ -18,10 +18,15 @@
     cursor: default;
 }
 .styleProvider-filter {
-    right: 0;
+    right: 15;
+    .styleProvider-filterShift {
+        left: 0;
+        top: 0;
+        position: absolute;
+    }
 }
 .styleProvider-audio {
-    right: 15;
+    right: 30;
 }
 .styleProvider-lock:hover,
 .styleProvider-audio:hover,
diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx
index 069bfd049..8a5ad3139 100644
--- a/src/client/views/StyleProvider.tsx
+++ b/src/client/views/StyleProvider.tsx
@@ -1,7 +1,7 @@
 import { IconProp } from '@fortawesome/fontawesome-svg-core';
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { Tooltip } from '@material-ui/core';
-import { IconButton, Shadows, Size } from 'browndash-components';
+import { Dropdown, DropdownType, IconButton, IListItemProps, ListBox, ListItem, Popup, Shadows, Size, Type } from 'browndash-components';
 import { action, runInAction } from 'mobx';
 import { extname } from 'path';
 import { BsArrowDown, BsArrowDownUp, BsArrowUp } from 'react-icons/bs';
@@ -24,6 +24,8 @@ import { KeyValueBox } from './nodes/KeyValueBox';
 import { SliderBox } from './nodes/SliderBox';
 import './StyleProvider.scss';
 import React = require('react');
+import { PropertiesView } from './PropertiesView';
+import { FaFilter } from 'react-icons/fa';
 
 export enum StyleProp {
     TreeViewIcon = 'treeView_Icon',
@@ -283,13 +285,44 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
             const filter = () => {
                 const showFilterIcon =
                     StrListCast(doc?._childFilters).length || StrListCast(doc?._childFiltersByRanges).length
-                        ? '#18c718bd' //'hasFilter'
+                        ? 'green' // #18c718bd' //'hasFilter'
                         : docProps?.childFilters?.().filter(f => Utils.IsRecursiveFilter(f) && f !== Utils.noDragsDocFilter).length || docProps?.childFiltersByRanges().length
                         ? 'orange' //'inheritsFilter'
                         : undefined;
                 return !showFilterIcon ? null : (
-                    <div className="styleProvider-filter" onClick={action(() => (SettingsManager.propertiesWidth = 250))}>
-                        <FontAwesomeIcon icon={'filter'} size="lg" style={{ position: 'absolute', top: '1%', right: '1%', cursor: 'pointer', padding: 1, color: showFilterIcon, zIndex: 1 }} />
+                    <div className="styleProvider-filter">
+                        <Dropdown
+                            type={Type.TERT}
+                            dropdownType={DropdownType.CLICK}
+                            fillWidth
+                            iconProvider={(active:boolean) => <div className='styleProvider-filterShift'><FaFilter/></div>}
+                            closeOnSelect={true}
+                            setSelectedVal={
+                                action((dv) => {
+                                    (dv as any).select(false);
+                                    (SettingsManager.propertiesWidth = 250);
+                                    setTimeout(action(() => {
+                                        if (PropertiesView.Instance) {
+                                            PropertiesView.Instance.CloseAll();
+                                            PropertiesView.Instance.openFilters = true;
+                                        }
+                                    }));
+                                })
+                            }
+                            size={Size.XSMALL}
+                            width={15}
+                            height={15}
+                            title={showFilterIcon === 'green' ? 
+                                "This view is filtered.  Click to view/change filters":
+                                "this view inherits filters from one of its parents"}
+                            color={SettingsManager.userColor}
+                            background={showFilterIcon}
+                            items={[...(props?.docViewPath?.()??[]), ...(props?.DocumentView?[props?.DocumentView?.()]:[])].map(dv => ({
+                                text: StrCast(dv.rootDoc.title),
+                                val: dv as any,
+                                style: {color:SettingsManager.userColor, background:SettingsManager.userBackgroundColor},
+                            } as IListItemProps)) }
+                        />
                     </div>
                 );
             };
diff --git a/src/client/views/UndoStack.tsx b/src/client/views/UndoStack.tsx
index 1afd5ad22..093bb8b9c 100644
--- a/src/client/views/UndoStack.tsx
+++ b/src/client/views/UndoStack.tsx
@@ -1,14 +1,12 @@
-import { action, observable } from 'mobx';
+import { Tooltip } from '@mui/material';
+import { Popup, Type } from 'browndash-components';
+import { observable } from 'mobx';
 import { observer } from 'mobx-react';
 import * as React from 'react';
-import { UndoManager } from '../util/UndoManager';
-import './UndoStack.scss';
 import { StrCast } from '../../fields/Types';
-import { Doc } from '../../fields/Doc';
-import { Popup, Type, isDark } from 'browndash-components';
-import { Colors } from './global/globalEnums';
 import { SettingsManager } from '../util/SettingsManager';
-import { Tooltip } from '@mui/material';
+import { UndoManager } from '../util/UndoManager';
+import './UndoStack.scss';
 
 interface UndoStackProps {
     width?: number;
diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
index 9ea1ed2de..d9faab063 100644
--- a/src/client/views/collections/TabDocView.tsx
+++ b/src/client/views/collections/TabDocView.tsx
@@ -17,6 +17,7 @@ import { CollectionViewType, DocumentType } from '../../documents/DocumentTypes'
 import { DocumentManager } from '../../util/DocumentManager';
 import { DragManager, dropActionType } from '../../util/DragManager';
 import { SelectionManager } from '../../util/SelectionManager';
+import { SettingsManager } from '../../util/SettingsManager';
 import { SnappingManager } from '../../util/SnappingManager';
 import { Transform } from '../../util/Transform';
 import { undoable, UndoManager } from '../../util/UndoManager';
@@ -33,7 +34,6 @@ import { CollectionFreeFormView } from './collectionFreeForm/CollectionFreeFormV
 import { CollectionView } from './CollectionView';
 import './TabDocView.scss';
 import React = require('react');
-import { SettingsManager } from '../../util/SettingsManager';
 const _global = (window /* browser */ || global) /* node */ as any;
 
 interface TabDocViewProps {
@@ -420,7 +420,7 @@ export class TabDocView extends React.Component<TabDocViewProps> {
     PanelHeight = () => this._panelHeight;
     miniMapColor = () => Colors.MEDIUM_GRAY;
     tabView = () => this._view;
-    disableMinimap = () => !this._document || this._document.layout !== CollectionView.LayoutString(Doc.LayoutFieldKey(this._document)) || this._document?._type_collection !== CollectionViewType.Freeform;
+    disableMinimap = () => !this._document;
     whenChildContentActiveChanges = (isActive: boolean) => (this._isAnyChildContentActive = isActive);
     isContentActive = () => this._isContentActive;
     waitForDoubleClick = () => (DocumentView.ExploreMode ? 'never' : undefined);
@@ -461,9 +461,7 @@ export class TabDocView extends React.Component<TabDocViewProps> {
                     bringToFront={emptyFunction}
                     pinToPres={TabDocView.PinDoc}
                 />
-                {this.disableMinimap() || this._document._type_collection !== CollectionViewType.Freeform ? null : (
-                    <TabMinimapView key="minimap" addDocTab={this.addDocTab} PanelHeight={this.PanelHeight} PanelWidth={this.PanelWidth} background={this.miniMapColor} document={this._document} tabView={this.tabView} />
-                )}
+                {this.disableMinimap() ? null : <TabMinimapView key="minimap" addDocTab={this.addDocTab} PanelHeight={this.PanelHeight} PanelWidth={this.PanelWidth} background={this.miniMapColor} document={this._document} tabView={this.tabView} />}
             </>
         );
     }
@@ -615,7 +613,7 @@ export class TabMinimapView extends React.Component<TabMinimapViewProps> {
         );
     };
     render() {
-        return (
+        return this.props.document.layout !== CollectionView.LayoutString(Doc.LayoutFieldKey(this.props.document)) || this.props.document?._type_collection !== CollectionViewType.Freeform ? null : (
             <div className="miniMap-hidden">
                 <Popup icon={<FontAwesomeIcon icon="globe-asia" size="lg" />} color={SettingsManager.userVariantColor} type={Type.TERT} onPointerDown={e => e.stopPropagation()} placement={'top-end'} popup={this.popup} />
             </div>
diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
index 182a33fd1..5c7dcc1a4 100644
--- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
+++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
@@ -609,10 +609,10 @@ export class CollectionSchemaView extends CollectionSubView() {
         this._menuKeys = this.documentKeys.filter(value => value.toLowerCase().includes(this._menuValue.toLowerCase()));
     };
 
-    getFieldFilters = (field: string) => StrListCast(this.Document._childFilters).filter(filter => filter.split(':')[0] == field);
+    getFieldFilters = (field: string) => StrListCast(this.Document._childFilters).filter(filter => filter.split(Doc.FilterSep)[0] == field);
 
     removeFieldFilters = (field: string) => {
-        this.getFieldFilters(field).forEach(filter => Doc.setDocFilter(this.Document, field, filter.split(':')[1], 'remove'));
+        this.getFieldFilters(field).forEach(filter => Doc.setDocFilter(this.Document, field, filter.split(Doc.FilterSep)[1], 'remove'));
     };
 
     onFilterKeyDown = (e: React.KeyboardEvent) => {
@@ -766,8 +766,8 @@ export class CollectionSchemaView extends CollectionSubView() {
         return keyOptions.map(key => {
             let bool = false;
             if (filters !== undefined) {
-                const ind = filters.findIndex(filter => filter.split(':')[1] === key);
-                const fields = ind === -1 ? undefined : filters[ind].split(':');
+                const ind = filters.findIndex(filter => filter.split(Doc.FilterSep)[1] === key);
+                const fields = ind === -1 ? undefined : filters[ind].split(Doc.FilterSep);
                 bool = fields ? fields[2] === 'check' : false;
             }
             return (
diff --git a/src/client/views/nodes/FontIconBox/FontIconBox.tsx b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
index 1eb6fd51c..0a59818ad 100644
--- a/src/client/views/nodes/FontIconBox/FontIconBox.tsx
+++ b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
@@ -246,10 +246,11 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
         return (
             <Dropdown
                 selectedVal={text}
-                setSelectedVal={undoable(val => script.script.run({ this: this.layoutDoc, self: this.rootDoc, val }), `dropdown select ${this.label}`)}
+                setSelectedVal={undoable(value => script.script.run({ this: this.layoutDoc, self: this.rootDoc, value }), `dropdown select ${this.label}`)}
                 color={SettingsManager.userColor}
                 background={SettingsManager.userVariantColor}
                 type={Type.TERT}
+                closeOnSelect={false}
                 dropdownType={DropdownType.SELECT}
                 onItemDown={this.dropdownItemDown}
                 items={list}
diff --git a/src/client/views/nodes/RecordingBox/RecordingBox.tsx b/src/client/views/nodes/RecordingBox/RecordingBox.tsx
index 1f113110b..481e43feb 100644
--- a/src/client/views/nodes/RecordingBox/RecordingBox.tsx
+++ b/src/client/views/nodes/RecordingBox/RecordingBox.tsx
@@ -119,7 +119,7 @@ export class RecordingBox extends ViewBoxBaseComponent<FieldViewProps>() {
     public static replayWorkspace(value: Doc) {
         Doc.UserDoc().currentRecording = value;
         value.overlayX = 70;
-        value.overlayY = 590;
+        value.overlayY = window.innerHeight - 180;
         Doc.AddToMyOverlay(value);
         DocumentManager.Instance.AddViewRenderedCb(value, docView => {
             Doc.UserDoc().currentRecording = docView.rootDoc;
@@ -147,11 +147,10 @@ export class RecordingBox extends ViewBoxBaseComponent<FieldViewProps>() {
     @action
     public static resumeWorkspaceReplaying(doc: Doc) {
         const docView = DocumentManager.Instance.getDocumentView(doc);
-        const videoBox = docView?.ComponentView as VideoBox;
-        if (videoBox) {
-            videoBox.Play();
-            Doc.UserDoc().workspaceReplayingState = media_state.Playing;
+        if (docView?.ComponentView instanceof VideoBox) {
+            docView.ComponentView.Play();
         }
+        Doc.UserDoc().workspaceReplayingState = media_state.Playing;
     }
 
     @action
-- 
cgit v1.2.3-70-g09d2


From 18e39170619a9b32cbecc50f5b857631c1a33251 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Fri, 8 Sep 2023 17:35:17 -0400
Subject: from last

---
 src/client/views/nodes/FontIconBox/FontIconBox.tsx | 1 +
 1 file changed, 1 insertion(+)

(limited to 'src/client/views/nodes/FontIconBox/FontIconBox.tsx')

diff --git a/src/client/views/nodes/FontIconBox/FontIconBox.tsx b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
index 0a59818ad..394108be4 100644
--- a/src/client/views/nodes/FontIconBox/FontIconBox.tsx
+++ b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
@@ -185,6 +185,7 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
             emptyFunction,
             emptyFunction
         );
+        return false;
     };
 
     /**
-- 
cgit v1.2.3-70-g09d2

