From aab4148a23a6505f103564fff305ac4c97b64479 Mon Sep 17 00:00:00 2001
From: monoguitari <113245090+monoguitari@users.noreply.github.com>
Date: Wed, 23 Aug 2023 13:15:31 -0400
Subject: Basic implementation of micahels branching trail on master

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

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

diff --git a/src/client/views/OverlayView.tsx b/src/client/views/OverlayView.tsx
index 339507f65..e838473d2 100644
--- a/src/client/views/OverlayView.tsx
+++ b/src/client/views/OverlayView.tsx
@@ -146,6 +146,7 @@ export class OverlayView extends React.Component {
 
     @action
     addWindow(contents: JSX.Element, options: OverlayElementOptions): OverlayDisposer {
+        console.log("adding window");
         const remove = action(() => {
             const index = this._elements.indexOf(contents);
             if (index !== -1) this._elements.splice(index, 1);
-- 
cgit v1.2.3-70-g09d2


From 349e586b01b18c641a4c753b709f4217a3f3e528 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Tue, 29 Aug 2023 12:55:49 -0400
Subject: cleanup

---
 src/client/util/CurrentUserUtils.ts                |  6 ++--
 src/client/views/OverlayView.tsx                   |  2 --
 src/client/views/UndoStack.tsx                     |  2 +-
 src/client/views/collections/TreeView.scss         |  4 +--
 .../collectionLinear/CollectionLinearView.tsx      |  2 +-
 .../views/nodes/RecordingBox/RecordingView.tsx     |  3 --
 src/client/views/nodes/VideoBox.tsx                |  4 ---
 src/client/views/nodes/trails/PresBox.tsx          | 12 +++----
 src/client/views/nodes/trails/PresElementBox.tsx   | 37 +++++++---------------
 9 files changed, 21 insertions(+), 51 deletions(-)

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

diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 873361587..b705bde7f 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -20,6 +20,7 @@ import { DashboardView } from "../views/DashboardView";
 import { Colors } from "../views/global/globalEnums";
 import { OpenWhere } from "../views/nodes/DocumentView";
 import { ButtonType } from "../views/nodes/FontIconBox/FontIconBox";
+import { ImportElementBox } from "../views/nodes/importBox/ImportElementBox";
 import { OverlayView } from "../views/OverlayView";
 import { DragManager, dropActionType } from "./DragManager";
 import { MakeTemplate } from "./DropConverter";
@@ -28,7 +29,6 @@ import { LinkManager } from "./LinkManager";
 import { ScriptingGlobals } from "./ScriptingGlobals";
 import { ColorScheme, SettingsManager } from "./SettingsManager";
 import { UndoManager } from "./UndoManager";
-import { ImportElementBox } from "../views/nodes/importBox/ImportElementBox";
 
 interface Button {
     // DocumentOptions fields a button can set
@@ -746,10 +746,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>;
         if (Doc.UserDoc().currentRecording) {
-            //@ts-ignore
-            Doc.RemFromMyOverlay(Doc.UserDoc().currentRecording);
+            Doc.RemFromMyOverlay(DocCast(Doc.UserDoc().currentRecording));
         }
         Doc.UserDoc().isRecording = false;
         Doc.UserDoc().isRecPlayback = false;
diff --git a/src/client/views/OverlayView.tsx b/src/client/views/OverlayView.tsx
index 7d65914b3..5d95c5fda 100644
--- a/src/client/views/OverlayView.tsx
+++ b/src/client/views/OverlayView.tsx
@@ -1,4 +1,3 @@
-
 import { action, computed, observable } from 'mobx';
 import { observer } from 'mobx-react';
 import { computedFn } from 'mobx-utils';
@@ -145,7 +144,6 @@ export class OverlayView extends React.Component {
 
     @action
     addWindow(contents: JSX.Element, options: OverlayElementOptions): OverlayDisposer {
-        console.log("adding window");
         const remove = action(() => {
             const index = this._elements.indexOf(contents);
             if (index !== -1) this._elements.splice(index, 1);
diff --git a/src/client/views/UndoStack.tsx b/src/client/views/UndoStack.tsx
index cdc389efe..47853b5e4 100644
--- a/src/client/views/UndoStack.tsx
+++ b/src/client/views/UndoStack.tsx
@@ -46,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 }}>
                                             {StrCast(name).replace(/[^\.]*\./, '')}
                                         </div>
                                     </div>
diff --git a/src/client/views/collections/TreeView.scss b/src/client/views/collections/TreeView.scss
index d3ba23b4e..0cc11bf1c 100644
--- a/src/client/views/collections/TreeView.scss
+++ b/src/client/views/collections/TreeView.scss
@@ -23,7 +23,7 @@
     .treeView-bulletIcons {
         width: 100%;
         height: 100%;
-        // position: absolute;
+        // changes start here.
 
         .treeView-expandIcon {
             display: none;
@@ -42,6 +42,7 @@
                 display: unset;
             }
         }
+        // end changes
         position: relative;
         display: flex;
         flex-direction: row;
@@ -140,7 +141,6 @@
             filter: opacity(0.2) !important;
         }
     }
-    
 
     //align-items: center;
     ::-webkit-scrollbar {
diff --git a/src/client/views/collections/collectionLinear/CollectionLinearView.tsx b/src/client/views/collections/collectionLinear/CollectionLinearView.tsx
index 0854bc611..3481d5130 100644
--- a/src/client/views/collections/collectionLinear/CollectionLinearView.tsx
+++ b/src/client/views/collections/collectionLinear/CollectionLinearView.tsx
@@ -210,7 +210,7 @@ export class CollectionLinearView extends CollectionSubView() {
                 text={Cast(this.props.Document.icon, 'string', null)}
                 icon={Cast(this.props.Document.icon, 'string', null) ? undefined : <FontAwesomeIcon color={SettingsManager.userColor} icon={isExpanded ? 'minus' : 'plus'} />}
                 color={SettingsManager.userColor}
-                // background={SettingsManager.userVariantColor}
+                background={SettingsManager.userVariantColor}
                 type={Type.TERT}
                 onPointerDown={e => e.stopPropagation()}
                 toggleType={ToggleType.BUTTON}
diff --git a/src/client/views/nodes/RecordingBox/RecordingView.tsx b/src/client/views/nodes/RecordingBox/RecordingView.tsx
index 755f1adc0..f7ed82643 100644
--- a/src/client/views/nodes/RecordingBox/RecordingView.tsx
+++ b/src/client/views/nodes/RecordingBox/RecordingView.tsx
@@ -9,7 +9,6 @@ import { Networking } from '../../../Network';
 import { Presentation, TrackMovements } from '../../../util/TrackMovements';
 import { ProgressBar } from './ProgressBar';
 import './RecordingView.scss';
-import { ScriptingGlobals } from '../../../util/ScriptingGlobals';
 
 export interface MediaSegment {
     videoChunks: any[];
@@ -164,9 +163,7 @@ 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/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx
index 5c2d09b0c..56508abf6 100644
--- a/src/client/views/nodes/VideoBox.tsx
+++ b/src/client/views/nodes/VideoBox.tsx
@@ -191,10 +191,6 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
                 this._finished = false;
                 start = this.timeline.trimStart;
             }
-            if (this.dataDoc._data_presentation) {
-                console.log("ninja")
-            }
-            console.log(this.dataDoc.data_presentation)
             try {
                 this._audioPlayer && this.player && (this._audioPlayer.currentTime = this.player?.currentTime);
                 update && this.player && this.playFrom(start, undefined, true);
diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx
index b0101d9a7..02132b7b3 100644
--- a/src/client/views/nodes/trails/PresBox.tsx
+++ b/src/client/views/nodes/trails/PresBox.tsx
@@ -303,7 +303,7 @@ 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");
+        console.log('next');
         const progressiveReveal = (first: boolean) => {
             const presIndexed = Cast(this.activeItem?.presentation_indexed, 'number', null);
             if (presIndexed !== undefined) {
@@ -345,7 +345,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
             // before moving onto next slide, run the subroutines :)
             const currentDoc = this.childDocs[this.itemIndex];
             //could i do this.childDocs[this.itemIndex] for first arg?
-            this.runSubroutines(TreeView.GetRunningChildren.get(currentDoc)?.() , this.childDocs[this.itemIndex + 1]);
+            this.runSubroutines(TreeView.GetRunningChildren.get(currentDoc)?.(), this.childDocs[this.itemIndex + 1]);
 
             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
@@ -386,7 +386,7 @@ 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");
+        console.log('going to document');
         Doc.UnBrushAllDocs();
         if (index >= 0 && index < this.childDocs.length) {
             this.rootDoc._itemIndex = index;
@@ -747,7 +747,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
 
         console.log(pinDoc.presData);
     }
-    
+
     /**
      * This method makes sure that cursor navigates to the element that
      * has the option open and last in the group.
@@ -759,7 +759,6 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
     navigateToActiveItem = (afterNav?: () => void) => {
         const activeItem: Doc = this.activeItem;
         const targetDoc: Doc = this.targetDoc;
-        // BranchingTrailManager.Instance.observeDocumentChange(targetDoc, this);
         const finished = () => {
             afterNav?.();
             console.log('Finish Slide Nav: ' + targetDoc.title);
@@ -1149,17 +1148,14 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
     //Regular click
     @action
     selectElement = (doc: Doc, noNav = false) => {
-        // BranchingTrailManager.Instance.observeDocumentChange(doc, this);
         CollectionStackedTimeline.CurrentlyPlaying?.map((clip, i) => clip?.ComponentView?.Pause?.());
         if (noNav) {
             const index = this.childDocs.indexOf(doc);
             if (index >= 0 && index < this.childDocs.length) {
                 this.rootDoc._itemIndex = index;
             }
-            console.log("no nav")
         } else {
             this.gotoDocument(this.childDocs.indexOf(doc), this.activeItem);
-            console.log('e bitch')
         }
         this.updateCurrentPresentation(DocCast(doc.embedContainer));
     };
diff --git a/src/client/views/nodes/trails/PresElementBox.tsx b/src/client/views/nodes/trails/PresElementBox.tsx
index d90f96249..121eb87d5 100644
--- a/src/client/views/nodes/trails/PresElementBox.tsx
+++ b/src/client/views/nodes/trails/PresElementBox.tsx
@@ -316,15 +316,15 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() {
         console.log('reverting');
         // console.log("reverting to previosly saved\n");
         // console.log(this.prevTarget);
-        console.log("Content continuously updating");
+        console.log('Content continuously updating');
         const target = DocCast(activeItem.annotationOn) ?? activeItem;
-        console.log(presTargetDoc.pinData)
+        console.log(presTargetDoc.pinData);
         PresBox.reversePin(activeItem, target);
         // console.log("new target\n");
-        // console.log(target); 
+        // 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
-    }
+    };
 
     /**
      * Method called for updating the view of the currently selected document
@@ -388,7 +388,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
@@ -453,7 +453,7 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() {
         const hasChildren: boolean = Cast(this.rootDoc?.hasChildren, 'boolean') || false;
 
         const items: JSX.Element[] = [];
-       
+
         items.push(
             <Tooltip key="slide" title={<div className="dash-tooltip">Update captured doc layout</div>}>
                 <div
@@ -464,31 +464,16 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() {
                 </div>
             </Tooltip>
         );
-        // items.push(
-        //     <Tooltip key="flex" title={<div className="dash-tooltip">Update captured doc content</div>}>
-        //         <div
-        //             className="slideButton"
-        //             onPointerDown={e => setupMoveUpEvents(this, e, returnFalse, emptyFunction, () => this.updateCapturedViewContents(targetDoc, activeItem))}
-        //             style={{ opacity: activeItem.config_pinData || activeItem.config_pinView ? 1 : 0.5, fontWeight: 700, display: 'flex' }}>
-        //             C
-        //         </div>
-        //     </Tooltip>
-        // );
         items.push(
             <Tooltip key="flex" title={<div className="dash-tooltip">Update captured doc content</div>}>
                 <div
-                    className="slideButton" 
-                    style={{fontWeight: 700, display: 'flex'}}
-                >
-                 <MultiToggle  type={Type.PRIM} items={[
-                        {icon: <FontAwesomeIcon icon="rotate-left" color="white" size='sm'/>, tooltip: "Save data to presentation", val: 'revert',
-                        onPointerDown: e => setupMoveUpEvents(this, e, returnFalse, emptyFunction, () => this.updateCapturedViewContents(targetDoc, activeItem))},
-                        {icon: <FontAwesomeIcon icon="floppy-disk" color="white" size='sm'/>, tooltip: "Continously update content", val: "floppy-disk",
-                        onPointerDown: e => setupMoveUpEvents(this, e, returnFalse, emptyFunction, () => this.revertToPreviouslySaved(targetDoc, activeItem))},
-                    ]} />
+                    className="slideButton"
+                    onPointerDown={e => setupMoveUpEvents(this, e, returnFalse, emptyFunction, () => this.updateCapturedViewContents(targetDoc, activeItem))}
+                    style={{ opacity: activeItem.config_pinData || activeItem.config_pinView ? 1 : 0.5, fontWeight: 700, display: 'flex' }}>
+                    C
                 </div>
             </Tooltip>
-        )
+        );
         items.push(
             <Tooltip key="slash" title={<div className="dash-tooltip">{this.recordingIsInOverlay ? 'Hide Recording' : `${PresElementBox.videoIsRecorded(activeItem) ? 'Show' : 'Start'} recording`}</div>}>
                 <div className="slideButton" onClick={e => (this.recordingIsInOverlay ? this.hideRecording(e, true) : this.startRecording(e, activeItem))} style={{ fontWeight: 700 }}>
-- 
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/OverlayView.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

