From c654a31fdb48a76fb4b0562168c920ca850a7b9e Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Sun, 3 Dec 2023 16:21:52 -0500
Subject: cleaned up warnings and errors, working with typescript 20.10

---
 src/client/views/ComponentDecorations.tsx | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

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

diff --git a/src/client/views/ComponentDecorations.tsx b/src/client/views/ComponentDecorations.tsx
index 66d1bd63d..0a34b283b 100644
--- a/src/client/views/ComponentDecorations.tsx
+++ b/src/client/views/ComponentDecorations.tsx
@@ -1,14 +1,14 @@
-import { observer } from "mobx-react";
-import { SelectionManager } from "../util/SelectionManager";
+import { observer } from 'mobx-react';
+import { SelectionManager } from '../util/SelectionManager';
 import './ComponentDecorations.scss';
-import React = require("react");
+import * as React from 'react';
 
 @observer
-export class ComponentDecorations extends React.Component<{ boundsTop: number, boundsLeft: number }, { value: string }> {
+export class ComponentDecorations extends React.Component<{ boundsTop: number; boundsLeft: number }, { value: string }> {
     static Instance: ComponentDecorations;
 
     render() {
         const seldoc = SelectionManager.Views().lastElement();
-        return seldoc?.ComponentView?.componentUI?.(this.props.boundsLeft, this.props.boundsTop) ?? (null);
+        return seldoc?.ComponentView?.componentUI?.(this.props.boundsLeft, this.props.boundsTop) ?? null;
     }
-}
\ No newline at end of file
+}
-- 
cgit v1.2.3-70-g09d2


From 85c09a9e5df77ad00f3e00a2fb1e0f2e3449f97d Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Tue, 12 Dec 2023 14:39:09 -0500
Subject: cleaned up SelectionManager. fixed schema view

---
 src/client/util/CaptureManager.tsx                 |   2 +-
 src/client/util/DictationManager.ts                |   2 +-
 src/client/util/DragManager.ts                     |   4 +-
 src/client/util/HypothesisUtils.ts                 |   2 +-
 src/client/util/SelectionManager.ts                | 124 +++++++++------------
 src/client/util/SharingManager.tsx                 |   8 +-
 src/client/util/SnappingManager.ts                 |  28 ++---
 src/client/views/ComponentDecorations.tsx          |   2 +-
 src/client/views/DocumentButtonBar.tsx             |   6 +-
 src/client/views/DocumentDecorations.tsx           |  80 ++++++-------
 src/client/views/GlobalKeyHandler.ts               |  48 +++-----
 src/client/views/InkControlPtHandles.tsx           |   4 +-
 src/client/views/MainView.tsx                      |   6 +-
 src/client/views/PropertiesButtons.tsx             |  22 ++--
 .../views/PropertiesDocBacklinksSelector.tsx       |   4 +-
 src/client/views/PropertiesView.tsx                |  22 ++--
 src/client/views/collections/CollectionMenu.tsx    |   2 +-
 src/client/views/collections/CollectionSubView.tsx |   4 +-
 .../views/collections/CollectionTreeView.tsx       |   2 +-
 .../collectionFreeForm/CollectionFreeFormView.tsx  |  12 +-
 .../collections/collectionFreeForm/MarqueeView.tsx |   2 +-
 .../collectionSchema/CollectionSchemaView.tsx      | 116 ++++++++++---------
 .../collections/collectionSchema/SchemaRowBox.tsx  |  38 ++++---
 src/client/views/global/globalScripts.ts           |  40 ++++---
 src/client/views/nodes/DocumentView.tsx            |   8 +-
 src/client/views/nodes/FontIconBox/FontIconBox.tsx |   2 +-
 src/client/views/nodes/LinkAnchorBox.tsx           |   4 +-
 src/client/views/nodes/MapBox/MapAnchorMenu.tsx    |   2 +-
 src/client/views/nodes/MapBox/MapBox2.tsx          |   4 +-
 .../views/nodes/formattedText/RichTextMenu.tsx     |  16 +--
 src/client/views/nodes/trails/PresBox.tsx          |   4 +-
 src/client/views/pdf/AnchorMenu.tsx                |   4 +-
 src/client/views/pdf/PDFViewer.tsx                 |   2 +-
 33 files changed, 308 insertions(+), 318 deletions(-)

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

diff --git a/src/client/util/CaptureManager.tsx b/src/client/util/CaptureManager.tsx
index 8a4f37121..271cf7495 100644
--- a/src/client/util/CaptureManager.tsx
+++ b/src/client/util/CaptureManager.tsx
@@ -81,7 +81,7 @@ export class CaptureManager extends React.Component<{}> {
                     <div
                         className="cancel"
                         onClick={() => {
-                            const selected = SelectionManager.Views().slice();
+                            const selected = SelectionManager.Views.slice();
                             SelectionManager.DeselectAll();
                             selected.map(dv => dv.props.removeDocument?.(dv.props.Document));
                             this.close();
diff --git a/src/client/util/DictationManager.ts b/src/client/util/DictationManager.ts
index 0fd7e840c..039bb360e 100644
--- a/src/client/util/DictationManager.ts
+++ b/src/client/util/DictationManager.ts
@@ -236,7 +236,7 @@ export namespace DictationManager {
         export const execute = async (phrase: string) => {
             return UndoManager.RunInBatch(async () => {
                 console.log('PHRASE: ' + phrase);
-                const targets = SelectionManager.Views();
+                const targets = SelectionManager.Views;
                 if (!targets || !targets.length) {
                     return;
                 }
diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index e96bbcaaf..c711db31a 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -618,7 +618,7 @@ export namespace DragManager {
 
 ScriptingGlobals.add(function toggleRaiseOnDrag(readOnly?: boolean) {
     if (readOnly) {
-        return SelectionManager.Views().some(dv => dv.Document.keepZWhenDragged);
+        return SelectionManager.Views.some(dv => dv.Document.keepZWhenDragged);
     }
-    SelectionManager.Views().map(dv => (dv.Document.keepZWhenDragged = !dv.Document.keepZWhenDragged));
+    SelectionManager.Views.map(dv => (dv.Document.keepZWhenDragged = !dv.Document.keepZWhenDragged));
 });
diff --git a/src/client/util/HypothesisUtils.ts b/src/client/util/HypothesisUtils.ts
index 151f18d6f..990798ed3 100644
--- a/src/client/util/HypothesisUtils.ts
+++ b/src/client/util/HypothesisUtils.ts
@@ -27,7 +27,7 @@ export namespace Hypothesis {
      * Search for a WebDocument whose url field matches the given uri, return undefined if not found
      */
     export const findWebDoc = async (uri: string) => {
-        const currentDoc = SelectionManager.Docs().lastElement();
+        const currentDoc = SelectionManager.Docs.lastElement();
         if (currentDoc && Cast(currentDoc.data, WebField)?.url.href === uri) return currentDoc; // always check first whether the currently selected doc is the annotation's source, only use Search otherwise
 
         const results: Doc[] = [];
diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts
index b837cdd08..64cced3f1 100644
--- a/src/client/util/SelectionManager.ts
+++ b/src/client/util/SelectionManager.ts
@@ -10,90 +10,72 @@ import { LinkManager } from './LinkManager';
 import { ScriptingGlobals } from './ScriptingGlobals';
 import { UndoManager } from './UndoManager';
 
-export namespace SelectionManager {
-    class Manager {
-        @observable.shallow SelectedViews: DocumentView[] = [];
-        @observable IsDragging: boolean = false;
-        @observable SelectedSchemaDocument: Doc | undefined = undefined;
-
-        constructor() {
-            makeObservable(this);
-        }
-
-        @action
-        SelectSchemaViewDoc(doc: Opt<Doc>) {
-            manager.SelectedSchemaDocument = doc;
-        }
-        @action
-        SelectView(docView: DocumentView, extendSelection: boolean): void {
-            if (!docView.SELECTED) {
-                if (!extendSelection) this.DeselectAll();
-                manager.SelectedViews.push(docView);
-                docView.SELECTED = true;
-                docView._props.whenChildContentsActiveChanged(true);
-            }
-        }
-        @action
-        DeselectView(docView?: DocumentView): void {
-            if (docView && manager.SelectedViews.includes(docView)) {
-                docView.SELECTED = false;
-                manager.SelectedViews.splice(manager.SelectedViews.indexOf(docView), 1);
-                docView._props.whenChildContentsActiveChanged(false);
-            }
-        }
-        @action
-        DeselectAll(): void {
-            LinkManager.currentLink = undefined;
-            LinkManager.currentLinkAnchor = undefined;
-            manager.SelectedSchemaDocument = undefined;
-            manager.SelectedViews.forEach(dv => {
-                dv.SELECTED = false;
-                dv._props.whenChildContentsActiveChanged(false);
-            });
-            manager.SelectedViews.length = 0;
-        }
+export class SelectionManager {
+    private static _manager: SelectionManager;
+    private static get Instance() {
+        return SelectionManager._manager ?? new SelectionManager();
     }
 
-    const manager = new Manager();
+    @observable.shallow SelectedViews: DocumentView[] = [];
+    @observable IsDragging: boolean = false;
+    @observable SelectedSchemaDocument: Doc | undefined = undefined;
 
-    export function DeselectView(docView?: DocumentView): void {
-        manager.DeselectView(docView);
-    }
-    export function SelectView(docView: DocumentView | undefined, ctrlPressed: boolean): void {
-        if (!docView) DeselectAll();
-        else manager.SelectView(docView, ctrlPressed);
-    }
-    export function SelectSchemaViewDoc(document: Opt<Doc>, deselectAllFirst?: boolean): void {
-        if (deselectAllFirst) manager.DeselectAll();
-        manager.SelectSchemaViewDoc(document);
+    private constructor() {
+        SelectionManager._manager = this;
+        makeObservable(this);
     }
 
-    export function IsSelected(doc?: Doc): boolean {
-        return Array.from(doc?.[DocViews] ?? []).some(dv => dv?.SELECTED);
+    @action
+    public static SelectSchemaViewDoc(doc: Opt<Doc>, deselectAllFirst?: boolean) {
+        if (deselectAllFirst) this.DeselectAll();
+        else this.Instance.SelectedSchemaDocument = doc;
     }
 
-    export function DeselectAll(except?: Doc): void {
-        const found = manager.SelectedViews.find(dv => dv.Document === except);
-        manager.DeselectAll();
-        if (found) manager.SelectView(found, false);
+    @action
+    public static SelectView(docView: DocumentView, extendSelection: boolean): void {
+        if (!docView) this.DeselectAll();
+        else if (!docView.SELECTED) {
+            if (!extendSelection) this.DeselectAll();
+            this.Instance.SelectedViews.push(docView);
+            docView.SELECTED = true;
+            docView._props.whenChildContentsActiveChanged(true);
+        }
     }
 
-    export function Views(): Array<DocumentView> {
-        return manager.SelectedViews;
-    }
-    export function SelectedSchemaDoc(): Doc | undefined {
-        return manager.SelectedSchemaDocument;
+    @action
+    public static DeselectView(docView?: DocumentView): void {
+        if (docView && this.Instance.SelectedViews.includes(docView)) {
+            docView.SELECTED = false;
+            this.Instance.SelectedViews.splice(this.Instance.SelectedViews.indexOf(docView), 1);
+            docView._props.whenChildContentsActiveChanged(false);
+        }
     }
-    export function Docs(): Doc[] {
-        return manager.SelectedViews.map(dv => dv.Document).filter(doc => doc?._type_collection !== CollectionViewType.Docking);
+    @action
+    public static DeselectAll(except?: Doc): void {
+        const found = this.Instance.SelectedViews.find(dv => dv.Document === except);
+        LinkManager.currentLink = undefined;
+        LinkManager.currentLinkAnchor = undefined;
+        this.Instance.SelectedSchemaDocument = undefined;
+        this.Instance.SelectedViews.forEach(dv => {
+            dv.SELECTED = false;
+            dv._props.whenChildContentsActiveChanged(false);
+        });
+        this.Instance.SelectedViews.length = 0;
+        if (found) this.SelectView(found, false);
     }
+
+    public static IsSelected = (doc?: Doc) => Array.from(doc?.[DocViews] ?? []).some(dv => dv?.SELECTED);
+    public static get Views() { return this.Instance.SelectedViews; } // prettier-ignore
+    public static get SelectedSchemaDoc() { return this.Instance.SelectedSchemaDocument; } // prettier-ignore
+    public static get Docs() { return this.Instance.SelectedViews.map(dv => dv.Document).filter(doc => doc?._type_collection !== CollectionViewType.Docking); } // prettier-ignore
 }
+
 ScriptingGlobals.add(function SelectionManager_selectedDocType(type: string, expertMode: boolean, checkContext?: boolean) {
     if (Doc.noviceMode && expertMode) return false;
     if (type === 'tab') {
-        return SelectionManager.Views().lastElement()?._props.renderDepth === 0;
+        return SelectionManager.Views.lastElement()?._props.renderDepth === 0;
     }
-    let selected = (sel => (checkContext ? DocCast(sel?.embedContainer) : sel))(SelectionManager.SelectedSchemaDoc() ?? SelectionManager.Docs().lastElement());
+    let selected = (sel => (checkContext ? DocCast(sel?.embedContainer) : sel))(SelectionManager.SelectedSchemaDoc ?? SelectionManager.Docs.lastElement());
     return selected?.type === type || selected?.type_collection === type || !type;
 });
 ScriptingGlobals.add(function deselectAll() {
@@ -118,8 +100,8 @@ ScriptingGlobals.add(function redo() {
     return UndoManager.Redo();
 });
 ScriptingGlobals.add(function selectedDocs(container: Doc, excludeCollections: boolean, prevValue: any) {
-    const docs = SelectionManager.Views()
-        .map(dv => dv.Document)
-        .filter(d => !Doc.AreProtosEqual(d, container) && !d.annotationOn && d.type !== DocumentType.KVP && (!excludeCollections || d.type !== DocumentType.COL || !Cast(d.data, listSpec(Doc), null)));
+    const docs = SelectionManager.Views.map(dv => dv.Document).filter(
+        d => !Doc.AreProtosEqual(d, container) && !d.annotationOn && d.type !== DocumentType.KVP && (!excludeCollections || d.type !== DocumentType.COL || !Cast(d.data, listSpec(Doc), null))
+    );
     return docs.length ? new List(docs) : prevValue;
 });
diff --git a/src/client/util/SharingManager.tsx b/src/client/util/SharingManager.tsx
index a46c6363e..7176b568e 100644
--- a/src/client/util/SharingManager.tsx
+++ b/src/client/util/SharingManager.tsx
@@ -162,7 +162,7 @@ export class SharingManager extends React.Component<{}> {
         const { user, sharingDoc } = recipient;
         const target = targetDoc || this.targetDoc!;
         const acl = `acl-${normalizeEmail(user.email)}`;
-        const docs = SelectionManager.Views().length < 2 ? [target] : SelectionManager.Views().map(docView => docView.Document);
+        const docs = SelectionManager.Views.length < 2 ? [target] : SelectionManager.Views.map(docView => docView.Document);
         docs.map(doc => (this.layoutDocAcls || doc.dockingConfig ? doc : Doc.GetProto(doc))).forEach(doc => {
             distributeAcls(acl, permission as SharingPermissions, doc, undefined, this.upgradeNested ? true : undefined);
             if (permission !== SharingPermissions.None) {
@@ -180,7 +180,7 @@ export class SharingManager extends React.Component<{}> {
         const target = targetDoc || this.targetDoc!;
         const acl = `acl-${normalizeEmail(StrCast(group.title))}`;
 
-        const docs = SelectionManager.Views().length < 2 ? [target] : SelectionManager.Views().map(docView => docView.Document);
+        const docs = SelectionManager.Views.length < 2 ? [target] : SelectionManager.Views.map(docView => docView.Document);
         docs.map(doc => (this.layoutDocAcls || doc.dockingConfig ? doc : Doc.GetProto(doc))).forEach(doc => {
             distributeAcls(acl, permission as SharingPermissions, doc, undefined, this.upgradeNested ? true : undefined);
 
@@ -317,7 +317,7 @@ export class SharingManager extends React.Component<{}> {
 
     private focusOn = (contents: string) => {
         const title = this.targetDoc ? StrCast(this.targetDoc.title) : '';
-        const docs = SelectionManager.Views().length > 1 ? SelectionManager.Views().map(docView => docView.props.Document) : [this.targetDoc];
+        const docs = SelectionManager.Views.length > 1 ? SelectionManager.Views.map(docView => docView.props.Document) : [this.targetDoc];
         return (
             <span
                 className="focus-span"
@@ -444,7 +444,7 @@ export class SharingManager extends React.Component<{}> {
         const users = this.individualSort === 'ascending' ? this.users.slice().sort(this.sortUsers) : this.individualSort === 'descending' ? this.users.slice().sort(this.sortUsers).reverse() : this.users;
         const groups = this.groupSort === 'ascending' ? groupList.slice().sort(this.sortGroups) : this.groupSort === 'descending' ? groupList.slice().sort(this.sortGroups).reverse() : groupList;
 
-        let docs = SelectionManager.Views().length < 2 ? [this.targetDoc] : SelectionManager.Views().map(docView => docView.Document);
+        let docs = SelectionManager.Views.length < 2 ? [this.targetDoc] : SelectionManager.Views.map(docView => docView.Document);
 
         if (this.myDocAcls) {
             const newDocs: Doc[] = [];
diff --git a/src/client/util/SnappingManager.ts b/src/client/util/SnappingManager.ts
index 44c6aad52..48ec61f85 100644
--- a/src/client/util/SnappingManager.ts
+++ b/src/client/util/SnappingManager.ts
@@ -2,7 +2,7 @@ import { observable, action, runInAction, reaction, makeObservable } from 'mobx'
 import { Doc } from '../../fields/Doc';
 
 export class SnappingManager {
-    static _manager: SnappingManager;
+    private static _manager: SnappingManager;
     private static get Instance() {
         return SnappingManager._manager ?? new SnappingManager();
     }
@@ -15,7 +15,7 @@ export class SnappingManager {
     @observable _horizSnapLines: number[] = [];
     @observable _vertSnapLines: number[] = [];
 
-    constructor() {
+    private constructor() {
         SnappingManager._manager = this;
         makeObservable(this);
     }
@@ -26,16 +26,16 @@ export class SnappingManager {
         this.Instance._vertSnapLines.push(...vertLines);
     };
 
-    public static get HorizSnapLines() { return SnappingManager.Instance._horizSnapLines; } // prettier-ignore
-    public static get VertSnapLines()  { return  SnappingManager.Instance._vertSnapLines; } // prettier-ignore
-    public static get ShiftKey()       { return SnappingManager.Instance._shiftKey; } // prettier-ignore
-    public static get CtrlKey()        { return SnappingManager.Instance._ctrlKey; } // prettier-ignore
-    public static get IsDragging()     { return SnappingManager.Instance._isDragging; } // prettier-ignore
-    public static get IsResizing()     { return SnappingManager.Instance._isResizing; } // prettier-ignore
-    public static get CanEmbed()       { return SnappingManager.Instance._canEmbed; } // prettier-ignore
-    public static SetShiftKey = (down: boolean) => runInAction(() => (SnappingManager.Instance._shiftKey = down));
-    public static SetCtrlKey = (down: boolean) => runInAction(() => (SnappingManager.Instance._ctrlKey = down));
-    public static SetIsDragging = (dragging: boolean) => runInAction(() => (SnappingManager.Instance._isDragging = dragging));
-    public static SetIsResizing = (doc: Doc | undefined) => runInAction(() => (SnappingManager.Instance._isResizing = doc));
-    public static SetCanEmbed = (canEmbed: boolean) => runInAction(() => (SnappingManager.Instance._canEmbed = canEmbed));
+    public static get HorizSnapLines() { return this.Instance._horizSnapLines; } // prettier-ignore
+    public static get VertSnapLines()  { return this.Instance._vertSnapLines; } // prettier-ignore
+    public static get ShiftKey()       { return this.Instance._shiftKey; } // prettier-ignore
+    public static get CtrlKey()        { return this.Instance._ctrlKey; } // prettier-ignore
+    public static get IsDragging()     { return this.Instance._isDragging; } // prettier-ignore
+    public static get IsResizing()     { return this.Instance._isResizing; } // prettier-ignore
+    public static get CanEmbed()       { return this.Instance._canEmbed; } // prettier-ignore
+    public static SetShiftKey = (down: boolean) => runInAction(() => (this.Instance._shiftKey = down));
+    public static SetCtrlKey = (down: boolean) => runInAction(() => (this.Instance._ctrlKey = down));
+    public static SetIsDragging = (dragging: boolean) => runInAction(() => (this.Instance._isDragging = dragging));
+    public static SetIsResizing = (doc: Doc | undefined) => runInAction(() => (this.Instance._isResizing = doc));
+    public static SetCanEmbed = (canEmbed: boolean) => runInAction(() => (this.Instance._canEmbed = canEmbed));
 }
diff --git a/src/client/views/ComponentDecorations.tsx b/src/client/views/ComponentDecorations.tsx
index 0a34b283b..ca4e5f2bc 100644
--- a/src/client/views/ComponentDecorations.tsx
+++ b/src/client/views/ComponentDecorations.tsx
@@ -8,7 +8,7 @@ export class ComponentDecorations extends React.Component<{ boundsTop: number; b
     static Instance: ComponentDecorations;
 
     render() {
-        const seldoc = SelectionManager.Views().lastElement();
+        const seldoc = SelectionManager.Views.lastElement();
         return seldoc?.ComponentView?.componentUI?.(this.props.boundsLeft, this.props.boundsTop) ?? null;
     }
 }
diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx
index 47ec0f1b4..a8ad4150e 100644
--- a/src/client/views/DocumentButtonBar.tsx
+++ b/src/client/views/DocumentButtonBar.tsx
@@ -375,7 +375,7 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
             );
         };
         return !targetDoc ? null : (
-            <Tooltip title={<div className="dash-tooltip">{`Pin Document ${SelectionManager.Views().length > 1 ? 'multiple documents' : ''} to Trail`}</div>}>
+            <Tooltip title={<div className="dash-tooltip">{`Pin Document ${SelectionManager.Views.length > 1 ? 'multiple documents' : ''} to Trail`}</div>}>
                 <div
                     className="documentButtonBar-icon documentButtonBar-pin"
                     onClick={e => {
@@ -526,7 +526,7 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
     }
 
     openContextMenu = (e: PointerEvent) => {
-        let child = SelectionManager.Views()[0].ContentDiv!.children[0];
+        let child = SelectionManager.Views[0].ContentDiv!.children[0];
         while (child.children.length) {
             const next = Array.from(child.children).find(c => c.className?.toString().includes('SVGAnimatedString') || typeof c.className === 'string');
             if (next?.className?.toString().includes(DocumentView.ROOT_DIV)) break;
@@ -606,7 +606,7 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
                     Doc.noviceMode ? null : <div className="documentButtonBar-button">{this.templateButton}</div>
                     /*<div className="documentButtonBar-button"> {this.metadataButton} </div> */
                 }
-                {!SelectionManager.Views()?.some(v => v.allLinks.length) ? null : <div className="documentButtonBar-button">{this.followLinkButton}</div>}
+                {!SelectionManager.Views?.some(v => v.allLinks.length) ? null : <div className="documentButtonBar-button">{this.followLinkButton}</div>}
                 <div className="documentButtonBar-button">{this.pinButton}</div>
                 <div className="documentButtonBar-button">{this.recordButton}</div>
                 {!Doc.UserDoc()['documentLinksButton-fullMenu'] ? null : <div className="documentButtonBar-button">{this.shareButton}</div>}
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index b93df36eb..8bcc1cb56 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -77,7 +77,7 @@ export class DocumentDecorations extends React.Component<DocumentDecorationsProp
                 const center = {x: (this.Bounds.x+this.Bounds.r)/2, y: (this.Bounds.y+this.Bounds.b)/2};
                 const {x,y} = Utils.rotPt(e.clientX - center.x, 
                                           e.clientY - center.y, 
-                                          NumCast(SelectionManager.Views().lastElement()?.screenToLocalTransform().Rotate));
+                                          NumCast(SelectionManager.Views.lastElement()?.screenToLocalTransform().Rotate));
                 (this._showNothing = !(this.Bounds.x !== Number.MAX_VALUE && //
                     (this.Bounds.x > center.x+x || this.Bounds.r < center.x+x || 
                      this.Bounds.y > center.y+y || this.Bounds.b < center.y+y )));
@@ -99,7 +99,7 @@ export class DocumentDecorations extends React.Component<DocumentDecorationsProp
     @computed get Bounds() {
         return (LinkFollower.IsFollowing || DocumentView.ExploreMode) ? 
             { x: 0, y: 0, r: 0, b: 0 }
-            : SelectionManager.Views()
+            : SelectionManager.Views
                 .filter(dv => dv._props.renderDepth > 0)
                 .map(dv => dv.getBounds())
                 .reduce((bounds, rect) => !rect ? bounds
@@ -107,7 +107,7 @@ export class DocumentDecorations extends React.Component<DocumentDecorationsProp
                                 y: Math.min(rect.top, bounds.y),
                                 r: Math.max(rect.right, bounds.r),
                                 b: Math.max(rect.bottom, bounds.b),
-                                c: SelectionManager.Views().length === 1 ? rect.center : undefined },
+                                c: SelectionManager.Views.length === 1 ? rect.center : undefined },
                     { x: Number.MAX_VALUE, y: Number.MAX_VALUE, r: Number.MIN_VALUE, b: Number.MIN_VALUE, c: undefined as { X: number; Y: number } | undefined }); // prettier-ignore
     }
 
@@ -121,7 +121,7 @@ export class DocumentDecorations extends React.Component<DocumentDecorationsProp
             UndoManager.RunInBatch(
                 () =>
                     titleFieldKey &&
-                    SelectionManager.Views().forEach(d => {
+                    SelectionManager.Views.forEach(d => {
                         if (titleFieldKey === 'title') {
                             d.dataDoc.title_custom = !this._accumulatedTitle.startsWith('-');
                             if (StrCast(d.Document.title).startsWith('@') && !this._accumulatedTitle.startsWith('@')) {
@@ -165,7 +165,7 @@ export class DocumentDecorations extends React.Component<DocumentDecorationsProp
     };
 
     onContainerDown = (e: React.PointerEvent) => {
-        const effectiveLayoutAcl = GetEffectiveAcl(SelectionManager.Views()[0].Document);
+        const effectiveLayoutAcl = GetEffectiveAcl(SelectionManager.Views[0].Document);
         if (effectiveLayoutAcl == AclAdmin || effectiveLayoutAcl == AclEdit || effectiveLayoutAcl == AclAugment) {
             setupMoveUpEvents(this, e, e => this.onBackgroundMove(true, e), emptyFunction, emptyFunction);
             e.stopPropagation();
@@ -173,7 +173,7 @@ export class DocumentDecorations extends React.Component<DocumentDecorationsProp
     };
 
     onTitleDown = (e: React.PointerEvent) => {
-        const effectiveLayoutAcl = GetEffectiveAcl(SelectionManager.Views()[0].Document);
+        const effectiveLayoutAcl = GetEffectiveAcl(SelectionManager.Views[0].Document);
         if (effectiveLayoutAcl == AclAdmin || effectiveLayoutAcl == AclEdit || effectiveLayoutAcl == AclAugment) {
             setupMoveUpEvents(
                 this,
@@ -196,17 +196,17 @@ export class DocumentDecorations extends React.Component<DocumentDecorationsProp
     };
     @action
     onBackgroundMove = (dragTitle: boolean, e: PointerEvent): boolean => {
-        const dragDocView = SelectionManager.Views()[0];
+        const dragDocView = SelectionManager.Views[0];
         const effectiveLayoutAcl = GetEffectiveAcl(dragDocView.Document);
         if (effectiveLayoutAcl != AclAdmin && effectiveLayoutAcl != AclEdit && effectiveLayoutAcl != AclAugment) {
             return false;
         }
         const containers = new Set<Doc | undefined>();
-        SelectionManager.Views().forEach(v => containers.add(DocCast(v.Document.embedContainer)));
+        SelectionManager.Views.forEach(v => containers.add(DocCast(v.Document.embedContainer)));
         if (containers.size > 1) return false;
         const { left, top } = dragDocView.getBounds() || { left: 0, top: 0 };
         const dragData = new DragManager.DocumentDragData(
-            SelectionManager.Views().map(dv => dv.Document),
+            SelectionManager.Views.map(dv => dv.Document),
             dragDocView._props.dropAction
         );
         dragData.offset = dragDocView._props.ScreenToLocalTransform().transformDirection(e.x - left, e.y - top);
@@ -216,7 +216,7 @@ export class DocumentDecorations extends React.Component<DocumentDecorationsProp
         dragData.canEmbed = dragTitle;
         this._hidden = true;
         DragManager.StartDocumentDrag(
-            SelectionManager.Views().map(dv => dv.ContentDiv!),
+            SelectionManager.Views.map(dv => dv.ContentDiv!),
             dragData,
             e.x,
             e.y,
@@ -231,7 +231,7 @@ export class DocumentDecorations extends React.Component<DocumentDecorationsProp
     _deleteAfterIconify = false;
     _iconifyBatch: UndoManager.Batch | undefined;
     onCloseClick = (forceDeleteOrIconify: boolean | undefined) => {
-        const views = SelectionManager.Views().filter(v => v && v._props.renderDepth > 0);
+        const views = SelectionManager.Views.filter(v => v && v._props.renderDepth > 0);
         if (forceDeleteOrIconify === false && this._iconifyBatch) return;
         this._deleteAfterIconify = forceDeleteOrIconify || this._iconifyBatch ? true : false;
         var iconifyingCount = views.length;
@@ -264,11 +264,11 @@ export class DocumentDecorations extends React.Component<DocumentDecorationsProp
     };
 
     onMaximizeDown = (e: React.PointerEvent) => {
-        setupMoveUpEvents(this, e, () => DragManager.StartWindowDrag?.(e, [SelectionManager.Views().lastElement().Document]) ?? false, emptyFunction, this.onMaximizeClick, false, false);
+        setupMoveUpEvents(this, e, () => DragManager.StartWindowDrag?.(e, [SelectionManager.Views.lastElement().Document]) ?? false, emptyFunction, this.onMaximizeClick, false, false);
         e.stopPropagation();
     };
     onMaximizeClick = (e: any): void => {
-        const selectedDocs = SelectionManager.Views();
+        const selectedDocs = SelectionManager.Views;
         if (selectedDocs.length) {
             if (e.ctrlKey) {
                 // open an embedding in a new tab with Ctrl Key
@@ -300,11 +300,11 @@ export class DocumentDecorations extends React.Component<DocumentDecorationsProp
     };
 
     onIconifyClick = (): void => {
-        SelectionManager.Views().forEach(dv => dv?.iconify());
+        SelectionManager.Views.forEach(dv => dv?.iconify());
         SelectionManager.DeselectAll();
     };
 
-    onSelectContainerDocClick = () => SelectionManager.Views()?.[0]?._props.docViewPath?.().lastElement()?.select(false);
+    onSelectContainerDocClick = () => SelectionManager.Views?.[0]?._props.docViewPath?.().lastElement()?.select(false);
     /**
      * sets up events when user clicks on the border radius editor
      */
@@ -319,7 +319,7 @@ export class DocumentDecorations extends React.Component<DocumentDecorationsProp
                 const [x, y] = [this.Bounds.x + 3, this.Bounds.y + 3];
                 const maxDist = Math.min((this.Bounds.r - this.Bounds.x) / 2, (this.Bounds.b - this.Bounds.y) / 2);
                 const dist = e.clientX < x && e.clientY < y ? 0 : Math.sqrt((e.clientX - x) * (e.clientX - x) + (e.clientY - y) * (e.clientY - y));
-                SelectionManager.Docs().map(doc => {
+                SelectionManager.Docs.map(doc => {
                     const docMax = Math.min(NumCast(doc.width) / 2, NumCast(doc.height) / 2);
                     const radius = Math.min(1, dist / maxDist) * docMax; // set radius based on ratio of drag distance to half diagonal distance of bounding box
                     doc.layout_borderRounding = `${radius}px`;
@@ -344,7 +344,7 @@ export class DocumentDecorations extends React.Component<DocumentDecorationsProp
             returnFalse, // don't care about move or up event,
             emptyFunction, // just care about whether we get a click event
             e => UndoManager.RunInBatch(
-                () => SelectionManager.Docs().forEach(doc =>
+                () => SelectionManager.Docs.forEach(doc =>
                         doc._pointerEvents = (doc._lockedPosition = !doc._lockedPosition)? 'none' : undefined ),
                 'toggleBackground' ) // prettier-ignore
         );
@@ -362,7 +362,7 @@ export class DocumentDecorations extends React.Component<DocumentDecorationsProp
     @action
     onRotateCenterDown = (e: React.PointerEvent): void => {
         this._isRotating = true;
-        const seldocview = SelectionManager.Views()[0];
+        const seldocview = SelectionManager.Views[0];
         setupMoveUpEvents(
             this,
             e,
@@ -378,11 +378,11 @@ export class DocumentDecorations extends React.Component<DocumentDecorationsProp
         this._isRotating = true;
         const rcScreen = { X: this.rotCenter[0], Y: this.rotCenter[1] };
         const rotateUndo = UndoManager.StartBatch('drag rotation');
-        const selectedInk = SelectionManager.Views().filter(i => i.ComponentView instanceof InkingStroke);
+        const selectedInk = SelectionManager.Views.filter(i => i.ComponentView instanceof InkingStroke);
         const centerPoint = this.rotCenter.slice();
         const infos = new Map<Doc, { unrotatedDocPos: { x: number; y: number }; startRotCtr: { x: number; y: number }; accumRot: number }>();
-        const seldocview = SelectionManager.Views()[0];
-        SelectionManager.Views().forEach(dv => {
+        const seldocview = SelectionManager.Views[0];
+        SelectionManager.Views.forEach(dv => {
             const accumRot = (NumCast(dv.Document._rotation) / 180) * Math.PI;
             const localRotCtr = dv._props.ScreenToLocalTransform().transformPoint(rcScreen.X, rcScreen.Y);
             const localRotCtrOffset = [localRotCtr[0] - NumCast(dv.Document.width) / 2, localRotCtr[1] - NumCast(dv.Document.height) / 2];
@@ -391,7 +391,7 @@ export class DocumentDecorations extends React.Component<DocumentDecorationsProp
             infos.set(dv.Document, { unrotatedDocPos, startRotCtr, accumRot });
         });
         const infoRot = (angle: number, isAbs = false) => {
-            SelectionManager.Views().forEach(
+            SelectionManager.Views.forEach(
                 action(dv => {
                     const { unrotatedDocPos, startRotCtr, accumRot } = infos.get(dv.Document)!;
                     const endRotCtr = Utils.rotPt(startRotCtr.x, startRotCtr.y, isAbs ? angle : accumRot + angle);
@@ -439,7 +439,7 @@ export class DocumentDecorations extends React.Component<DocumentDecorationsProp
 
     @action
     onPointerDown = (e: React.PointerEvent): void => {
-        SnappingManager.SetIsResizing(SelectionManager.Docs().lastElement());
+        SnappingManager.SetIsResizing(SelectionManager.Docs.lastElement());
         setupMoveUpEvents(this, e, this.onPointerMove, this.onPointerUp, emptyFunction);
         e.stopPropagation();
         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
@@ -448,7 +448,7 @@ export class DocumentDecorations extends React.Component<DocumentDecorationsProp
         this._offset = { x: this._resizeHdlId.toLowerCase().includes('left') ? bounds.right - e.clientX : bounds.left - e.clientX, y: this._resizeHdlId.toLowerCase().includes('top') ? bounds.bottom - e.clientY : bounds.top - e.clientY };
         this._resizeUndo = UndoManager.StartBatch('drag resizing');
         this._snapPt = { x: e.pageX, y: e.pageY };
-        SelectionManager.Views().forEach(docView => docView.CollectionFreeFormView?.dragStarting(false, false));
+        SelectionManager.Views.forEach(docView => docView.CollectionFreeFormView?.dragStarting(false, false));
     };
 
     projectDragToAspect = (e: PointerEvent, docView: DocumentView, fixedAspect: number) => {
@@ -466,7 +466,7 @@ export class DocumentDecorations extends React.Component<DocumentDecorationsProp
         return project([e.clientX + this._offset.x, e.clientY + this._offset.y], tl, [tl[0] + fixedAspect, tl[1] + 1]);
     };
     onPointerMove = (e: PointerEvent, down: number[], move: number[]): boolean => {
-        const first = SelectionManager.Views()[0];
+        const first = SelectionManager.Views[0];
         const effectiveAcl = GetEffectiveAcl(first.Document);
         if (!(effectiveAcl == AclAdmin || effectiveAcl == AclEdit || effectiveAcl == AclAugment)) return false;
         if (!first) return false;
@@ -483,10 +483,10 @@ export class DocumentDecorations extends React.Component<DocumentDecorationsProp
         !this._interactionLock && runInAction(async () => {   // resize selected docs if we're not in the middle of a resize (ie, throttle input events to frame rate)
             this._interactionLock = true;
             this._snapPt = thisPt;
-            e.ctrlKey && (SelectionManager.Views().forEach(docView => !Doc.NativeHeight(docView.Document) && docView.toggleNativeDimensions()));
-            const fixedAspect = SelectionManager.Docs().some(this.hasFixedAspect);
+            e.ctrlKey && (SelectionManager.Views.forEach(docView => !Doc.NativeHeight(docView.Document) && docView.toggleNativeDimensions()));
+            const fixedAspect = SelectionManager.Docs.some(this.hasFixedAspect);
             const scaleAspect = {x:scale.x === 1 && fixedAspect ? scale.y : scale.x, y: scale.x !== 1 && fixedAspect ? scale.x : scale.y};
-            SelectionManager.Views().forEach(docView => 
+            SelectionManager.Views.forEach(docView => 
                 this.resizeView(docView, refPt, scaleAspect, { dragHdl, ctrlKey:e.ctrlKey })); // prettier-ignore
             await new Promise<any>(res => setTimeout(() => res(this._interactionLock = undefined)));
         }); // prettier-ignore
@@ -600,7 +600,7 @@ export class DocumentDecorations extends React.Component<DocumentDecorationsProp
         this._resizeUndo?.end();
 
         // detect layout_autoHeight gesture and apply
-        SelectionManager.Docs().forEach(doc => NumCast(doc._height) < 20 && (doc._layout_autoHeight = true));
+        SelectionManager.Docs.forEach(doc => NumCast(doc._height) < 20 && (doc._layout_autoHeight = true));
         //need to change points for resize, or else rotation/control points will fail.
         this._inkDragDocs
             .map(oldbds => ({ oldbds, inkPts: Cast(oldbds.doc.data, InkField)?.inkData || [] }))
@@ -617,8 +617,8 @@ export class DocumentDecorations extends React.Component<DocumentDecorationsProp
 
     @computed
     get selectionTitle(): string {
-        if (SelectionManager.Views().length === 1) {
-            const selected = SelectionManager.Views()[0];
+        if (SelectionManager.Views.length === 1) {
+            const selected = SelectionManager.Views[0];
             if (this._titleControlString.startsWith('=')) {
                 return ScriptField.MakeFunction(this._titleControlString.substring(1), { doc: Doc.name })!.script.run({ self: selected.Document, this: selected.layoutDoc }, console.log).result?.toString() || '';
             }
@@ -627,11 +627,11 @@ export class DocumentDecorations extends React.Component<DocumentDecorationsProp
             }
             return this._accumulatedTitle;
         }
-        return SelectionManager.Views().length > 1 ? '-multiple-' : '-unset-';
+        return SelectionManager.Views.length > 1 ? '-multiple-' : '-unset-';
     }
 
     @computed get rotCenter() {
-        const lastView = SelectionManager.Views().lastElement();
+        const lastView = SelectionManager.Views.lastElement();
         if (lastView) {
             const invXf = lastView._props.ScreenToLocalTransform().inverse();
             const seldoc = lastView.layoutDoc;
@@ -643,7 +643,7 @@ export class DocumentDecorations extends React.Component<DocumentDecorationsProp
 
     render() {
         const { b, r, x, y } = this.Bounds;
-        const seldocview = SelectionManager.Views().lastElement();
+        const seldocview = SelectionManager.Views.lastElement();
         if (SnappingManager.IsDragging || r - x < 1 || x === Number.MAX_VALUE || !seldocview || this._hidden || isNaN(r) || isNaN(b) || isNaN(x) || isNaN(y)) {
             setTimeout(action(() => (this._showNothing = true)));
             return null;
@@ -667,7 +667,7 @@ export class DocumentDecorations extends React.Component<DocumentDecorationsProp
             hideDecorations ||
             seldocview._props.hideOpenButton ||
             seldocview.Document.layout_hideOpenButton ||
-            SelectionManager.Views().some(docView => docView.Document._dragOnlyWithinContainer || docView.Document.isGroup || docView.Document.layout_hideOpenButton) ||
+            SelectionManager.Views.some(docView => docView.Document._dragOnlyWithinContainer || docView.Document.isGroup || docView.Document.layout_hideOpenButton) ||
             this._isRounding ||
             this._isRotating;
         const hideDeleteButton =
@@ -677,7 +677,7 @@ export class DocumentDecorations extends React.Component<DocumentDecorationsProp
             this._isRotating ||
             seldocview._props.hideDeleteButton ||
             seldocview.Document.hideDeleteButton ||
-            SelectionManager.Views().some(docView => {
+            SelectionManager.Views.some(docView => {
                 const collectionAcl = docView._props.docViewPath()?.lastElement() ? GetEffectiveAcl(docView._props.docViewPath().lastElement().dataDoc) : AclEdit;
                 return collectionAcl !== AclAdmin && collectionAcl !== AclEdit && GetEffectiveAcl(docView.Document) !== AclAdmin;
             });
@@ -692,7 +692,7 @@ export class DocumentDecorations extends React.Component<DocumentDecorationsProp
         const bounds = this.ClippedBounds;
         const useLock = bounds.r - bounds.x > 135 && seldocview.CollectionFreeFormDocumentView;
         const useRotation = !hideResizers && seldocview.Document.type !== DocumentType.EQUATION && seldocview.CollectionFreeFormDocumentView; // when do we want an object to not rotate?
-        const rotation = SelectionManager.Views().length == 1 ? seldocview.screenToLocalTransform().inverse().RotateDeg : 0;
+        const rotation = SelectionManager.Views.length == 1 ? seldocview.screenToLocalTransform().inverse().RotateDeg : 0;
 
         // Radius constants
         const useRounding = seldocview.ComponentView instanceof ImageBox || seldocview.ComponentView instanceof FormattedTextBox || seldocview.ComponentView instanceof CollectionFreeFormView;
@@ -754,7 +754,7 @@ export class DocumentDecorations extends React.Component<DocumentDecorationsProp
         );
         const centery = hideTitle ? 0 : this._titleHeight;
         const transformOrigin = `${50}% calc(50% + ${centery / 2}px)`;
-        const freeformDoc = SelectionManager.Views().some(v => v.CollectionFreeFormDocumentView);
+        const freeformDoc = SelectionManager.Views.some(v => v.CollectionFreeFormDocumentView);
         return (
             <div className="documentDecorations" style={{ display: this._showNothing && !freeformDoc ? 'none' : undefined }}>
                 <div
@@ -767,7 +767,7 @@ export class DocumentDecorations extends React.Component<DocumentDecorationsProp
                         transformOrigin,
                         background: SnappingManager.ShiftKey ? undefined : 'yellow',
                         pointerEvents: SnappingManager.ShiftKey || DocumentView.Interacting ? 'none' : 'all',
-                        display: SelectionManager.Views().length <= 1 || hideDecorations ? 'none' : undefined,
+                        display: SelectionManager.Views.length <= 1 || hideDecorations ? 'none' : undefined,
                         transform: `rotate(${rotation}deg)`,
                     }}
                     onPointerDown={this.onBackgroundDown}
@@ -824,7 +824,7 @@ export class DocumentDecorations extends React.Component<DocumentDecorationsProp
                                     style={{
                                         transform: `translate(${-this._resizeBorderWidth / 2 + 10}px, ${this._resizeBorderWidth + bounds.b - bounds.y + this._titleHeight}px) `,
                                     }}>
-                                    <DocumentButtonBar views={SelectionManager.Views} />
+                                    <DocumentButtonBar views={() => SelectionManager.Views} />
                                 </div>
                             )}
                         </div>
diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts
index 174f7951d..4015fb321 100644
--- a/src/client/views/GlobalKeyHandler.ts
+++ b/src/client/views/GlobalKeyHandler.ts
@@ -90,8 +90,8 @@ export class KeyManager {
     });
 
     nudge = (x: number, y: number, label: string) => {
-        const nudgeable = SelectionManager.Views().some(dv => dv.CollectionFreeFormDocumentView?.nudge);
-        nudgeable && UndoManager.RunInBatch(() => SelectionManager.Views().map(dv => dv.CollectionFreeFormDocumentView?.nudge(x, y)), label);
+        const nudgeable = SelectionManager.Views.some(dv => dv.CollectionFreeFormDocumentView?.nudge);
+        nudgeable && UndoManager.RunInBatch(() => SelectionManager.Views.map(dv => dv.CollectionFreeFormDocumentView?.nudge(x, y)), label);
         return { stopPropagation: nudgeable, preventDefault: nudgeable };
     };
 
@@ -99,18 +99,18 @@ export class KeyManager {
         switch (keyname) {
             case 'u':
                 if (document.activeElement?.tagName !== 'INPUT' && document.activeElement?.tagName !== 'TEXTAREA') {
-                    const ungroupings = SelectionManager.Views();
+                    const ungroupings = SelectionManager.Views;
                     UndoManager.RunInBatch(() => ungroupings.map(dv => (dv.layoutDoc.group = undefined)), 'ungroup');
                     SelectionManager.DeselectAll();
                 }
                 break;
             case 'g':
                 if (document.activeElement?.tagName !== 'INPUT' && document.activeElement?.tagName !== 'TEXTAREA') {
-                    const selected = SelectionManager.Views();
+                    const selected = SelectionManager.Views;
                     const collectionView = selected.reduce((col, dv) => (col === null || dv.CollectionFreeFormView === col ? dv.CollectionFreeFormView : undefined), null as null | undefined | CollectionFreeFormView);
                     if (collectionView) {
                         UndoManager.RunInBatch(() =>
-                            collectionView._marqueeViewRef.current?.collection(e, true, SelectionManager.Docs())
+                            collectionView._marqueeViewRef.current?.collection(e, true, SelectionManager.Docs)
                         , 'grouping');
                         break;
                     }
@@ -182,14 +182,14 @@ export class KeyManager {
             case 'arrowdown':  return this.nudge(0, 10, 'nudge down');
             case 'u' : 
                 if (document.activeElement?.tagName !== 'INPUT' && document.activeElement?.tagName !== 'TEXTAREA') {
-                    UndoManager.RunInBatch(() => SelectionManager.Docs().forEach(doc => (doc.group = undefined)), 'unggroup');
+                    UndoManager.RunInBatch(() => SelectionManager.Docs.forEach(doc => (doc.group = undefined)), 'unggroup');
                     SelectionManager.DeselectAll();
                 }
                 break;
             case 'g':
                 if (document.activeElement?.tagName !== 'INPUT' && document.activeElement?.tagName !== 'TEXTAREA') {
                     const randomGroup = random(0, 1000);
-                    UndoManager.RunInBatch(() => SelectionManager.Docs().forEach(doc => (doc.group = randomGroup)), 'group');
+                    UndoManager.RunInBatch(() => SelectionManager.Docs.forEach(doc => (doc.group = randomGroup)), 'group');
                     SelectionManager.DeselectAll();
                 }
                 break;
@@ -208,7 +208,7 @@ export class KeyManager {
         switch (keyname) {
             case 'ƒ':
             case 'f':
-                const dv = SelectionManager.Views()?.[0];
+                const dv = SelectionManager.Views?.[0];
                 UndoManager.RunInBatch(() => dv.CollectionFreeFormDocumentView?.float(), 'float');
         }
 
@@ -256,8 +256,8 @@ export class KeyManager {
                 }
                 break;
             case 'f':
-                if (SelectionManager.Views().length === 1 && SelectionManager.Views()[0].ComponentView?.search) {
-                    SelectionManager.Views()[0].ComponentView?.search?.('', false, false);
+                if (SelectionManager.Views.length === 1 && SelectionManager.Views[0].ComponentView?.search) {
+                    SelectionManager.Views[0].ComponentView?.search?.('', false, false);
                 } else {
                     const searchBtn = DocListCast(Doc.MyLeftSidebarMenu.data).find(d => d.target === Doc.MySearcher);
                     if (searchBtn) {
@@ -299,17 +299,11 @@ export class KeyManager {
                 preventDefault = false;
                 break;
             case 'x':
-                if (SelectionManager.Views().length) {
+                if (SelectionManager.Views.length) {
                     const bds = DocumentDecorations.Instance.Bounds;
-                    const pt = SelectionManager.Views()[0]
-                        .props.ScreenToLocalTransform()
-                        .transformPoint(bds.x + (bds.r - bds.x) / 2, bds.y + (bds.b - bds.y) / 2);
-                    const text =
-                        `__DashDocId(${pt?.[0] || 0},${pt?.[1] || 0}):` +
-                        SelectionManager.Views()
-                            .map(dv => dv.Document[Id])
-                            .join(':');
-                    SelectionManager.Views().length && navigator.clipboard.writeText(text);
+                    const pt = SelectionManager.Views[0].props.ScreenToLocalTransform().transformPoint(bds.x + (bds.r - bds.x) / 2, bds.y + (bds.b - bds.y) / 2);
+                    const text = `__DashDocId(${pt?.[0] || 0},${pt?.[1] || 0}):` + SelectionManager.Views.map(dv => dv.Document[Id]).join(':');
+                    SelectionManager.Views.length && navigator.clipboard.writeText(text);
                     DocumentDecorations.Instance.onCloseClick(true);
                     stopPropagation = false;
                     preventDefault = false;
@@ -318,15 +312,9 @@ export class KeyManager {
             case 'c':
                 if ((document.activeElement as any)?.type !== 'text' && !AnchorMenu.Instance.Active && DocumentDecorations.Instance.Bounds.r - DocumentDecorations.Instance.Bounds.x > 2) {
                     const bds = DocumentDecorations.Instance.Bounds;
-                    const pt = SelectionManager.Views()[0]
-                        .props.ScreenToLocalTransform()
-                        .transformPoint(bds.x + (bds.r - bds.x) / 2, bds.y + (bds.b - bds.y) / 2);
-                    const text =
-                        `__DashCloneId(${pt?.[0] || 0},${pt?.[1] || 0}):` +
-                        SelectionManager.Views()
-                            .map(dv => dv.Document[Id])
-                            .join(':');
-                    SelectionManager.Views().length && navigator.clipboard.writeText(text);
+                    const pt = SelectionManager.Views[0].props.ScreenToLocalTransform().transformPoint(bds.x + (bds.r - bds.x) / 2, bds.y + (bds.b - bds.y) / 2);
+                    const text = `__DashCloneId(${pt?.[0] || 0},${pt?.[1] || 0}):` + SelectionManager.Views.map(dv => dv.Document[Id]).join(':');
+                    SelectionManager.Views.length && navigator.clipboard.writeText(text);
                     stopPropagation = false;
                 }
                 preventDefault = false;
@@ -344,7 +332,7 @@ export class KeyManager {
         if (!plain) return;
         const clone = plain.startsWith('__DashCloneId(');
         const docids = plain.split(':'); // hack!  docids[0] is the top left of the selection rectangle
-        const addDocument = SelectionManager.Views().lastElement()?.ComponentView?.addDocument;
+        const addDocument = SelectionManager.Views.lastElement()?.ComponentView?.addDocument;
         if (addDocument && (plain.startsWith('__DashDocId(') || clone)) {
             Doc.Paste(docids.slice(1), clone, addDocument);
         }
diff --git a/src/client/views/InkControlPtHandles.tsx b/src/client/views/InkControlPtHandles.tsx
index b835a3798..a5c2d99d2 100644
--- a/src/client/views/InkControlPtHandles.tsx
+++ b/src/client/views/InkControlPtHandles.tsx
@@ -208,8 +208,8 @@ export class InkEndPtHandles extends React.Component<InkEndProps> {
                 const v1n = { X: v1.X / v1len, Y: v1.Y / v1len };
                 const v2n = { X: v2.X / v2len, Y: v2.Y / v2len };
                 const angle = Math.acos(v1n.X * v2n.X + v1n.Y * v2n.Y) * Math.sign(v1.X * v2.Y - v2.X * v1.Y);
-                InkStrokeProperties.Instance.stretchInk(SelectionManager.Views(), scaling, p2, v1n, e.shiftKey);
-                InkStrokeProperties.Instance.rotateInk(SelectionManager.Views(), angle, pt2()); // bcz: call pt2() func here because pt2 will have changed from previous stretchInk call
+                InkStrokeProperties.Instance.stretchInk(SelectionManager.Views, scaling, p2, v1n, e.shiftKey);
+                InkStrokeProperties.Instance.rotateInk(SelectionManager.Views, angle, pt2()); // bcz: call pt2() func here because pt2 will have changed from previous stretchInk call
                 return false;
             }),
             action(() => {
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 73a6b687a..4f96b9234 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -145,7 +145,7 @@ export class MainView extends React.Component {
     componentDidMount() {
         reaction(
             // when a multi-selection occurs, remove focus from all active elements to allow keyboad input to go only to global key manager to act upon selection
-            () => SelectionManager.Views().slice(),
+            () => SelectionManager.Views.slice(),
             views => views.length > 1 && (document.activeElement as any)?.blur !== undefined && (document.activeElement as any)!.blur()
         );
         const scriptTag = document.createElement('script');
@@ -924,9 +924,7 @@ export class MainView extends React.Component {
         );
     }
     @computed get snapLines() {
-        SnappingManager.IsDragging;
-        SnappingManager.IsResizing;
-        const dragged = DragManager.docsBeingDragged.lastElement() ?? SelectionManager.Docs().lastElement();
+        const dragged = DragManager.docsBeingDragged.lastElement() ?? SelectionManager.Docs.lastElement();
         const dragPar = dragged ? DocumentManager.Instance.getDocumentView(dragged)?.CollectionFreeFormView : undefined;
         return !dragPar?.layoutDoc.freeform_snapLines ? null : (
             <div className="mainView-snapLines">
diff --git a/src/client/views/PropertiesButtons.tsx b/src/client/views/PropertiesButtons.tsx
index 7824ad1c8..8540e81e1 100644
--- a/src/client/views/PropertiesButtons.tsx
+++ b/src/client/views/PropertiesButtons.tsx
@@ -40,13 +40,13 @@ export class PropertiesButtons extends React.Component<{}, {}> {
     @observable public static Instance: PropertiesButtons;
 
     @computed get selectedDoc() {
-        return SelectionManager.SelectedSchemaDoc() || SelectionManager.Views().lastElement()?.Document;
+        return SelectionManager.SelectedSchemaDoc || SelectionManager.Views.lastElement()?.Document;
     }
     @computed get selectedLayoutDoc() {
-        return SelectionManager.SelectedSchemaDoc() || SelectionManager.Views().lastElement()?.layoutDoc;
+        return SelectionManager.SelectedSchemaDoc || SelectionManager.Views.lastElement()?.layoutDoc;
     }
     @computed get selectedTabView() {
-        return !SelectionManager.SelectedSchemaDoc() && SelectionManager.Views().lastElement()?.topMost;
+        return !SelectionManager.SelectedSchemaDoc && SelectionManager.Views.lastElement()?.topMost;
     }
 
     propertyToggleBtn = (label: (on?: any) => string, property: string, tooltip: (on?: any) => string, icon: (on?: any) => any, onClick?: (dv: Opt<DocumentView>, doc: Doc, property: string) => void, useUserDoc?: boolean) => {
@@ -64,8 +64,8 @@ export class PropertiesButtons extends React.Component<{}, {}> {
                 fillWidth={true}
                 toggleType={ToggleType.BUTTON}
                 onClick={undoable(() => {
-                    if (SelectionManager.Views().length > 1) {
-                        SelectionManager.Views().forEach(dv => (onClick ?? onPropToggle)(dv, dv.Document, property));
+                    if (SelectionManager.Views.length > 1) {
+                        SelectionManager.Views.forEach(dv => (onClick ?? onPropToggle)(dv, dv.Document, property));
                     } else if (targetDoc) (onClick ?? onPropToggle)(undefined, targetDoc, property);
                 }, property)}
             />
@@ -82,7 +82,7 @@ export class PropertiesButtons extends React.Component<{}, {}> {
             on => `${on ? 'Set' : 'Remove'} lightbox flag`,
             on => 'window-restore',
             onClick => {
-                SelectionManager.Views().forEach(dv => {
+                SelectionManager.Views.forEach(dv => {
                     const containerDoc = dv.Document;
                     //containerDoc.followAllLinks =
                     // containerDoc.noShadow =
@@ -200,7 +200,7 @@ export class PropertiesButtons extends React.Component<{}, {}> {
     //         on => `${on ? 'Set' : 'Remove'} lightbox flag`,
     //         on => 'window-restore',
     //         onClick => {
-    //             SelectionManager.Views().forEach(dv => {
+    //             SelectionManager.Views.forEach(dv => {
     //                 const containerDoc = dv.Document;
     //                 //containerDoc.followAllLinks =
     //                 // containerDoc.noShadow =
@@ -352,8 +352,7 @@ export class PropertiesButtons extends React.Component<{}, {}> {
     @undoBatch
     handlePerspectiveChange = (e: any) => {
         this.selectedDoc && (this.selectedDoc._type_collection = e.target.value);
-        SelectionManager.Views()
-            .filter(dv => dv.docView)
+        SelectionManager.Views.filter(dv => dv.docView)
             .map(dv => dv.docView!)
             .forEach(docView => (docView.layoutDoc._type_collection = e.target.value));
     };
@@ -416,8 +415,7 @@ export class PropertiesButtons extends React.Component<{}, {}> {
     @undoBatch
     @action
     handleOptionChange = (onClick: string) => {
-        SelectionManager.Views()
-            .filter(dv => dv.docView)
+        SelectionManager.Views.filter(dv => dv.docView)
             .map(dv => dv.docView!)
             .forEach(docView => {
                 const linkButton = IsFollowLinkScript(docView.props.Document.onClick);
@@ -443,7 +441,7 @@ export class PropertiesButtons extends React.Component<{}, {}> {
 
     @undoBatch
     editOnClickScript = () => {
-        if (SelectionManager.Views().length) SelectionManager.Views().forEach(dv => DocUtils.makeCustomViewClicked(dv.Document, undefined, 'onClick'));
+        if (SelectionManager.Views.length) SelectionManager.Views.forEach(dv => DocUtils.makeCustomViewClicked(dv.Document, undefined, 'onClick'));
         else this.selectedDoc && DocUtils.makeCustomViewClicked(this.selectedDoc, undefined, 'onClick');
     };
 
diff --git a/src/client/views/PropertiesDocBacklinksSelector.tsx b/src/client/views/PropertiesDocBacklinksSelector.tsx
index b1e99c3f5..58d3b72e8 100644
--- a/src/client/views/PropertiesDocBacklinksSelector.tsx
+++ b/src/client/views/PropertiesDocBacklinksSelector.tsx
@@ -34,10 +34,10 @@ export class PropertiesDocBacklinksSelector extends React.Component<PropertiesDo
     });
 
     render() {
-        return !SelectionManager.Views().length ? null : (
+        return !SelectionManager.Views.length ? null : (
             <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 }} />
+                <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 b4c591b89..442d09739 100644
--- a/src/client/views/PropertiesView.tsx
+++ b/src/client/views/PropertiesView.tsx
@@ -67,14 +67,14 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
     }
 
     @computed get selectedDoc() {
-        return SelectionManager.SelectedSchemaDoc() || this.selectedDocumentView?.Document || Doc.ActiveDashboard;
+        return SelectionManager.SelectedSchemaDoc || this.selectedDocumentView?.Document || Doc.ActiveDashboard;
     }
 
     @computed get selectedLayoutDoc() {
-        return SelectionManager.SelectedSchemaDoc() || this.selectedDocumentView?.layoutDoc || Doc.ActiveDashboard;
+        return SelectionManager.SelectedSchemaDoc || this.selectedDocumentView?.layoutDoc || Doc.ActiveDashboard;
     }
     @computed get selectedDocumentView() {
-        if (SelectionManager.Views().length) return SelectionManager.Views()[0];
+        if (SelectionManager.Views.length) return SelectionManager.Views[0];
         if (PresBox.Instance?.selectedArray.size) return DocumentManager.Instance.getDocumentView(PresBox.Instance.Document);
         return undefined;
     }
@@ -177,7 +177,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
         const rows: JSX.Element[] = [];
         if (this.dataDoc && this.selectedDoc) {
             const ids = new Set<string>(reqdKeys);
-            const docs: Doc[] = SelectionManager.Views().length < 2 ? [this.layoutFields ? Doc.Layout(this.selectedDoc) : this.dataDoc] : SelectionManager.Views().map(dv => (this.layoutFields ? dv.layoutDoc : dv.dataDoc));
+            const docs: Doc[] = SelectionManager.Views.length < 2 ? [this.layoutFields ? Doc.Layout(this.selectedDoc) : this.dataDoc] : SelectionManager.Views.map(dv => (this.layoutFields ? dv.layoutDoc : dv.dataDoc));
             docs.forEach(doc => Object.keys(doc).forEach(key => doc[key] !== ComputedField.undefined && ids.add(key)));
 
             // prettier-ignore
@@ -226,7 +226,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
 
     @undoBatch
     setKeyValue = (value: string) => {
-        const docs = SelectionManager.Views().length < 2 && this.selectedDoc ? [this.layoutFields ? Doc.Layout(this.selectedDoc) : this.dataDoc!] : SelectionManager.Views().map(dv => (this.layoutFields ? dv.layoutDoc : dv.dataDoc));
+        const docs = SelectionManager.Views.length < 2 && this.selectedDoc ? [this.layoutFields ? Doc.Layout(this.selectedDoc) : this.dataDoc!] : SelectionManager.Views.map(dv => (this.layoutFields ? dv.layoutDoc : dv.dataDoc));
         docs.forEach(doc => {
             if (value.indexOf(':') !== -1) {
                 const newVal = value[0].toUpperCase() + value.substring(1, value.length);
@@ -290,7 +290,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
     }
 
     @computed get layoutPreview() {
-        if (SelectionManager.Views().length > 1) {
+        if (SelectionManager.Views.length > 1) {
             return '-- multiple selected --';
         }
         if (this.selectedDoc) {
@@ -339,7 +339,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
      */
     @undoBatch
     changePermissions = (e: any, user: string) => {
-        const docs = SelectionManager.Views().length < 2 ? [this.selectedDoc] : SelectionManager.Views().map(dv => (this.layoutDocAcls ? dv.layoutDoc : dv.dataDoc));
+        const docs = SelectionManager.Views.length < 2 ? [this.selectedDoc] : SelectionManager.Views.map(dv => (this.layoutDocAcls ? dv.layoutDoc : dv.dataDoc));
         SharingManager.Instance.shareFromPropertiesSidebar(user, e.currentTarget.value as SharingPermissions, docs, this.layoutDocAcls);
     };
 
@@ -457,7 +457,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
      */
     @computed get sharingTable() {
         // all selected docs
-        const docs = SelectionManager.Views().length < 2 && this.selectedDoc ? [this.selectedDoc] : SelectionManager.Views().map(docView => docView.Document);
+        const docs = SelectionManager.Views.length < 2 && this.selectedDoc ? [this.selectedDoc] : SelectionManager.Views.map(docView => docView.Document);
         const target = docs[0];
 
         const showAdmin = GetEffectiveAcl(target) == AclAdmin;
@@ -573,7 +573,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
 
     @computed get editableTitle() {
         const titles = new Set<string>();
-        SelectionManager.Views().forEach(dv => titles.add(StrCast(dv.Document.title)));
+        SelectionManager.Views.forEach(dv => titles.add(StrCast(dv.Document.title)));
         const title = Array.from(titles.keys()).length > 1 ? '--multiple selected--' : StrCast(this.selectedDoc?.title);
         return (
             <div>
@@ -628,8 +628,8 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
 
     @undoBatch
     setTitle = (value: string | number) => {
-        if (SelectionManager.Views().length > 1) {
-            SelectionManager.Views().map(dv => Doc.SetInPlace(dv.Document, 'title', value, true));
+        if (SelectionManager.Views.length > 1) {
+            SelectionManager.Views.map(dv => Doc.SetInPlace(dv.Document, 'title', value, true));
         } else if (this.dataDoc) {
             if (this.selectedDoc) Doc.SetInPlace(this.selectedDoc, 'title', value, true);
             else KeyValueBox.SetField(this.dataDoc, 'title', value as string, true);
diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx
index f8e80ed87..08fcd544e 100644
--- a/src/client/views/collections/CollectionMenu.tsx
+++ b/src/client/views/collections/CollectionMenu.tsx
@@ -49,7 +49,7 @@ export class CollectionMenu extends AntimodeMenu<CollectionMenuProps> {
 
     componentDidMount() {
         reaction(
-            () => SelectionManager.Views().lastElement(),
+            () => SelectionManager.Views.lastElement(),
             view => view && this.SetSelection(view)
         );
     }
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index a74c6858c..79b15fdb1 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -344,7 +344,7 @@ export function CollectionSubView<X>(moreProps?: X) {
                                 }
                             });
                         } else {
-                            const srcWeb = SelectionManager.Views().lastElement();
+                            const srcWeb = SelectionManager.Views.lastElement();
                             const srcUrl = (srcWeb?.Document.data as WebField)?.url?.href?.match(/https?:\/\/[^/]*/)?.[0];
                             const reg = new RegExp(Utils.prepend(''), 'g');
                             const modHtml = srcUrl ? html.replace(reg, srcUrl) : html;
@@ -353,7 +353,7 @@ export function CollectionSubView<X>(moreProps?: X) {
                             Doc.GetProto(htmlDoc)['data-text'] = Doc.GetProto(htmlDoc).text = text;
                             addDocument(htmlDoc);
                             if (srcWeb) {
-                                const iframe = SelectionManager.Views()[0].ContentDiv?.getElementsByTagName('iframe')?.[0];
+                                const iframe = SelectionManager.Views[0].ContentDiv?.getElementsByTagName('iframe')?.[0];
                                 const focusNode = iframe?.contentDocument?.getSelection()?.focusNode as any;
                                 if (focusNode) {
                                     const anchor = srcWeb?.ComponentView?.getAnchor?.(true);
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index 917241c5f..658d60523 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -168,7 +168,7 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
         const targetDataDoc = this.Document[DocData];
         const value = DocListCast(targetDataDoc[this._props.fieldKey]);
         const result = value.filter(v => !docs.includes(v));
-        if ((doc instanceof Doc ? [doc] : doc).some(doc => SelectionManager.Views().some(dv => Doc.AreProtosEqual(dv.Document, doc)))) SelectionManager.DeselectAll();
+        if ((doc instanceof Doc ? [doc] : doc).some(doc => SelectionManager.Views.some(dv => Doc.AreProtosEqual(dv.Document, doc)))) SelectionManager.DeselectAll();
         if (result.length !== value.length && doc instanceof Doc) {
             const ind = DocListCast(targetDataDoc[this._props.fieldKey]).indexOf(doc);
             const prev = ind && DocListCast(targetDataDoc[this._props.fieldKey])[ind - 1];
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index ec31f77b2..aa40fb809 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -1961,18 +1961,18 @@ export function CollectionBrowseClick(dv: DocumentView, clientX: number, clientY
 }
 ScriptingGlobals.add(CollectionBrowseClick);
 ScriptingGlobals.add(function nextKeyFrame(readOnly: boolean) {
-    !readOnly && (SelectionManager.Views()[0].ComponentView as CollectionFreeFormView)?.changeKeyFrame();
+    !readOnly && (SelectionManager.Views[0].ComponentView as CollectionFreeFormView)?.changeKeyFrame();
 });
 ScriptingGlobals.add(function prevKeyFrame(readOnly: boolean) {
-    !readOnly && (SelectionManager.Views()[0].ComponentView as CollectionFreeFormView)?.changeKeyFrame(true);
+    !readOnly && (SelectionManager.Views[0].ComponentView as CollectionFreeFormView)?.changeKeyFrame(true);
 });
 ScriptingGlobals.add(function curKeyFrame(readOnly: boolean) {
-    const selView = SelectionManager.Views();
+    const selView = SelectionManager.Views;
     if (readOnly) return selView[0].ComponentView?.getKeyFrameEditing?.() ? Colors.MEDIUM_BLUE : 'transparent';
     runInAction(() => selView[0].ComponentView?.setKeyFrameEditing?.(!selView[0].ComponentView?.getKeyFrameEditing?.()));
 });
 ScriptingGlobals.add(function pinWithView(pinContent: boolean) {
-    SelectionManager.Views().forEach(view =>
+    SelectionManager.Views.forEach(view =>
         view.props.pinToPres(view.Document, {
             currentFrame: Cast(view.Document.currentFrame, 'number', null),
             pinData: {
@@ -1984,8 +1984,8 @@ ScriptingGlobals.add(function pinWithView(pinContent: boolean) {
     );
 });
 ScriptingGlobals.add(function bringToFront() {
-    SelectionManager.Views().forEach(view => view.CollectionFreeFormView?.bringToFront(view.Document));
+    SelectionManager.Views.forEach(view => view.CollectionFreeFormView?.bringToFront(view.Document));
 });
 ScriptingGlobals.add(function sendToBack(doc: Doc) {
-    SelectionManager.Views().forEach(view => view.CollectionFreeFormView?.bringToFront(view.Document, true));
+    SelectionManager.Views.forEach(view => view.CollectionFreeFormView?.bringToFront(view.Document, true));
 });
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index 9f316bef3..10beb120a 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -176,7 +176,7 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque
                 this.pasteTable(ns, x, y);
             })();
             e.stopPropagation();
-        } else if (!e.ctrlKey && !e.metaKey && SelectionManager.Views().length < 2) {
+        } else if (!e.ctrlKey && !e.metaKey && SelectionManager.Views.length < 2) {
             FormattedTextBox.SelectOnLoadChar = Doc.UserDoc().defaultTextLayout && !this._props.childLayoutString ? e.key : '';
             FormattedTextBox.LiveTextUndo = UndoManager.StartBatch('type new note');
             this._props.addLiveTextDocument(DocUtils.GetNewTextDoc('-typed text-', x, y, 200, 100, this._props.xPadding === 0));
diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
index 9a00595f9..276415d56 100644
--- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
+++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
@@ -1,13 +1,13 @@
 import * as React from 'react';
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { action, computed, observable, ObservableMap, observe } from 'mobx';
+import { action, computed, makeObservable, observable, ObservableMap, observe, override } from 'mobx';
 import { observer } from 'mobx-react';
 import { Doc, DocListCast, Field, NumListCast, Opt, StrListCast } from '../../../../fields/Doc';
 import { Id } from '../../../../fields/FieldSymbols';
 import { List } from '../../../../fields/List';
 import { listSpec } from '../../../../fields/Schema';
 import { BoolCast, Cast, DocCast, NumCast, StrCast } from '../../../../fields/Types';
-import { emptyFunction, returnEmptyDoclist, returnEmptyString, returnFalse, returnIgnore, returnNever, returnTrue, setupMoveUpEvents, smoothScroll } from '../../../../Utils';
+import { copyProps, emptyFunction, returnEmptyDoclist, returnEmptyString, returnFalse, returnIgnore, returnNever, returnTrue, setupMoveUpEvents, smoothScroll } from '../../../../Utils';
 import { Docs, DocumentOptions, DocUtils, FInfo } from '../../../documents/Documents';
 import { DocumentManager } from '../../../util/DocumentManager';
 import { DragManager } from '../../../util/DragManager';
@@ -19,7 +19,7 @@ import { Colors } from '../../global/globalEnums';
 import { DocFocusOptions, DocumentView, DocumentViewProps } from '../../nodes/DocumentView';
 import { KeyValueBox } from '../../nodes/KeyValueBox';
 import { DefaultStyleProvider, StyleProp } from '../../StyleProvider';
-import { CollectionSubView } from '../CollectionSubView';
+import { CollectionSubView, SubCollectionViewProps } from '../CollectionSubView';
 import './CollectionSchemaView.scss';
 import { SchemaColumnHeader } from './SchemaColumnHeader';
 import { SchemaRowBox } from './SchemaRowBox';
@@ -79,15 +79,27 @@ export class CollectionSchemaView extends CollectionSubView() {
     @observable _filterSearchValue: string = '';
     @observable _selectedCell: [Doc, number] | undefined = undefined;
 
+    _prevProps: SubCollectionViewProps;
+    @override _props: SubCollectionViewProps;
+    constructor(props: SubCollectionViewProps) {
+        super(props);
+        this._props = this._prevProps = props;
+        makeObservable(this);
+    }
+
+    componentDidUpdate() {
+        copyProps(this);
+    }
+
     // target HTMLelement portal for showing a popup menu to edit cell values.
     public get MenuTarget() {
         return this._menuTarget.current;
     }
 
     @computed get _selectedDocs() {
-        const selected = SelectionManager.Docs().filter(doc => Doc.AreProtosEqual(DocCast(doc.embedContainer), this.Document));
+        const selected = SelectionManager.Docs.filter(doc => Doc.AreProtosEqual(DocCast(doc.embedContainer), this.Document));
         if (!selected.length) {
-            for (const sel of SelectionManager.Docs()) {
+            for (const sel of SelectionManager.Docs) {
                 const contextPath = DocumentManager.GetContextPath(sel, true);
                 if (contextPath.includes(this.Document)) {
                     const parentInd = contextPath.indexOf(this.Document);
@@ -107,7 +119,7 @@ export class CollectionSchemaView extends CollectionSubView() {
     }
 
     @computed get tableWidth() {
-        return this.props.PanelWidth() - this.previewWidth - (this.previewWidth === 0 ? 0 : CollectionSchemaView._previewDividerWidth);
+        return this._props.PanelWidth() - this.previewWidth - (this.previewWidth === 0 ? 0 : CollectionSchemaView._previewDividerWidth);
     }
 
     @computed get columnKeys() {
@@ -139,9 +151,8 @@ export class CollectionSchemaView extends CollectionSubView() {
         return BoolCast(this.layoutDoc.sortDesc);
     }
 
-    @action
     componentDidMount() {
-        this.props.setContentView?.(this);
+        this._props.setContentView?.(this);
         document.addEventListener('keydown', this.onKeyDown);
 
         Object.entries(this._documentOptions).forEach((pair: [string, FInfo]) => this.fieldInfos.set(pair[0], pair[1]));
@@ -239,7 +250,6 @@ export class CollectionSchemaView extends CollectionSubView() {
     };
 
     @undoBatch
-    @action
     setColumnSort = (field: string | undefined, desc: boolean = false) => {
         this.layoutDoc.sortField = field;
         this.layoutDoc.sortDesc = desc;
@@ -248,7 +258,6 @@ export class CollectionSchemaView extends CollectionSubView() {
     addRow = (doc: Doc | Doc[]) => this.addDocument(doc);
 
     @undoBatch
-    @action
     changeColumnKey = (index: number, newKey: string, defaultVal?: any) => {
         if (!this.documentKeys.includes(newKey)) {
             this.addNewKey(newKey, defaultVal);
@@ -260,7 +269,6 @@ export class CollectionSchemaView extends CollectionSubView() {
     };
 
     @undoBatch
-    @action
     addColumn = (key: string, defaultVal?: any) => {
         if (!this.documentKeys.includes(key)) {
             this.addNewKey(key, defaultVal);
@@ -281,7 +289,6 @@ export class CollectionSchemaView extends CollectionSubView() {
     addNewKey = (key: string, defaultVal: any) => this.childDocs.forEach(doc => (doc[key] = defaultVal));
 
     @undoBatch
-    @action
     removeColumn = (index: number) => {
         if (this.columnKeys.length === 1) return;
         const currWidths = this.storedColumnWidths.slice();
@@ -320,8 +327,8 @@ export class CollectionSchemaView extends CollectionSubView() {
                 change = this._displayColumnWidths[shrinking] - CollectionSchemaView._minColWidth;
             }
 
-            this._displayColumnWidths[shrinking] -= change * this.props.ScreenToLocalTransform().Scale;
-            this._displayColumnWidths[growing] += change * this.props.ScreenToLocalTransform().Scale;
+            this._displayColumnWidths[shrinking] -= change * this._props.ScreenToLocalTransform().Scale;
+            this._displayColumnWidths[growing] += change * this._props.ScreenToLocalTransform().Scale;
 
             return false;
         }
@@ -335,7 +342,6 @@ export class CollectionSchemaView extends CollectionSubView() {
     };
 
     @undoBatch
-    @action
     moveColumn = (fromIndex: number, toIndex: number) => {
         let currKeys = this.columnKeys.slice();
         currKeys.splice(toIndex, 0, currKeys.splice(fromIndex, 1)[0]);
@@ -379,7 +385,7 @@ export class CollectionSchemaView extends CollectionSubView() {
     @action
     highlightDropColumn = (e: PointerEvent) => {
         e.stopPropagation();
-        const mouseX = this.props.ScreenToLocalTransform().transformPoint(e.clientX, e.clientY)[0];
+        const mouseX = this._props.ScreenToLocalTransform().transformPoint(e.clientX, e.clientY)[0];
         const index = this.findDropIndex(mouseX);
         this._colEles.forEach((colRef, i) => {
             let leftStyle = '';
@@ -439,7 +445,7 @@ export class CollectionSchemaView extends CollectionSubView() {
 
     onInternalDrop = (e: Event, de: DragManager.DropEvent) => {
         if (de.complete.columnDragData) {
-            const mouseX = this.props.ScreenToLocalTransform().transformPoint(de.x, de.y)[0];
+            const mouseX = this._props.ScreenToLocalTransform().transformPoint(de.x, de.y)[0];
             const index = this.findDropIndex(mouseX);
             this.moveColumn(de.complete.columnDragData.colIndex, index ?? de.complete.columnDragData.colIndex);
 
@@ -483,7 +489,7 @@ export class CollectionSchemaView extends CollectionSubView() {
         const nativeWidth = this._previewRef!.getBoundingClientRect();
         const minWidth = 40;
         const maxWidth = 1000;
-        const movedWidth = this.props.ScreenToLocalTransform().transformDirection(nativeWidth.right - e.clientX, 0)[0];
+        const movedWidth = this._props.ScreenToLocalTransform().transformDirection(nativeWidth.right - e.clientX, 0)[0];
         const width = movedWidth < minWidth ? minWidth : movedWidth > maxWidth ? maxWidth : movedWidth;
         this.layoutDoc.schema_previewWidth = width;
         return false;
@@ -507,8 +513,8 @@ export class CollectionSchemaView extends CollectionSubView() {
         const found = this._tableContentRef && Array.from(this._tableContentRef.getElementsByClassName('documentView-node')).find((node: any) => node.id === doc[Id]);
         if (found) {
             const rect = found.getBoundingClientRect();
-            const localRect = this.props.ScreenToLocalTransform().transformBounds(rect.left, rect.top, rect.width, rect.height);
-            if (localRect.y < this.rowHeightFunc() || localRect.y + localRect.height > this.props.PanelHeight()) {
+            const localRect = this._props.ScreenToLocalTransform().transformBounds(rect.left, rect.top, rect.width, rect.height);
+            if (localRect.y < this.rowHeightFunc() || localRect.y + localRect.height > this._props.PanelHeight()) {
                 let focusSpeed = options.zoomTime ?? 50;
                 smoothScroll(focusSpeed, this._tableContentRef!, localRect.y + this._tableContentRef!.scrollTop - this.rowHeightFunc(), options.easeFunc);
                 return focusSpeed;
@@ -755,7 +761,7 @@ export class CollectionSchemaView extends CollectionSubView() {
     @computed get renderFilterOptions() {
         const keyOptions: string[] = [];
         const columnKey = this.columnKeys[this._filterColumnIndex!];
-        const allDocs = DocListCast(this.dataDoc[this.props.fieldKey]);
+        const allDocs = DocListCast(this.dataDoc[this._props.fieldKey]);
         allDocs.forEach(doc => {
             const value = StrCast(doc[columnKey]);
             if (!keyOptions.includes(value) && value !== '' && (this._filterSearchValue === '' || value.includes(this._filterSearchValue))) {
@@ -779,9 +785,9 @@ export class CollectionSchemaView extends CollectionSubView() {
                         onClick={e => e.stopPropagation()}
                         onChange={action(e => {
                             if (e.target.checked) {
-                                Doc.setDocFilter(this.props.Document, columnKey, key, 'check');
+                                Doc.setDocFilter(this.Document, columnKey, key, 'check');
                             } else {
-                                Doc.setDocFilter(this.props.Document, columnKey, key, 'remove');
+                                Doc.setDocFilter(this.Document, columnKey, key, 'remove');
                             }
                         })}
                         checked={bool}
@@ -828,8 +834,8 @@ export class CollectionSchemaView extends CollectionSubView() {
     }
     rowHeightFunc = () => (BoolCast(this.layoutDoc._schema_singleLine) ? CollectionSchemaView._rowSingleLineHeight : CollectionSchemaView._rowHeight);
     sortedDocsFunc = () => this.sortedDocs;
-    isContentActive = () => this.props.isSelected() || this.props.isContentActive();
-    screenToLocal = () => this.props.ScreenToLocalTransform().translate(-this.tableWidth, 0);
+    isContentActive = () => this._props.isSelected() || this._props.isContentActive();
+    screenToLocal = () => this._props.ScreenToLocalTransform().translate(-this.tableWidth, 0);
     previewWidthFunc = () => this.previewWidth;
     render() {
         return (
@@ -838,7 +844,7 @@ export class CollectionSchemaView extends CollectionSubView() {
                 <div
                     className="schema-table"
                     style={{ width: `calc(100% - ${this.previewWidth}px)` }}
-                    onWheel={e => this.props.isContentActive() && e.stopPropagation()}
+                    onWheel={e => this._props.isContentActive() && e.stopPropagation()}
                     ref={r => {
                         // prevent wheel events from passively propagating up through containers
                         r?.addEventListener('wheel', (e: WheelEvent) => {}, { passive: false });
@@ -864,7 +870,7 @@ export class CollectionSchemaView extends CollectionSubView() {
                                 openContextMenu={this.openContextMenu}
                                 dragColumn={this.dragColumn}
                                 setColRef={this.setColRef}
-                                isContentActive={this.props.isContentActive}
+                                isContentActive={this._props.isContentActive}
                             />
                         ))}
                     </div>
@@ -895,10 +901,10 @@ export class CollectionSchemaView extends CollectionSubView() {
                                 onClickScriptDisable="always"
                                 focus={emptyFunction}
                                 defaultDoubleClick={returnIgnore}
-                                renderDepth={this.props.renderDepth + 1}
+                                renderDepth={this._props.renderDepth + 1}
                                 rootSelected={this.rootSelected}
                                 PanelWidth={this.previewWidthFunc}
-                                PanelHeight={this.props.PanelHeight}
+                                PanelHeight={this._props.PanelHeight}
                                 isContentActive={returnTrue}
                                 isDocumentActive={returnFalse}
                                 ScreenToLocalTransform={this.screenToLocal}
@@ -907,12 +913,12 @@ export class CollectionSchemaView extends CollectionSubView() {
                                 searchFilterDocs={this.searchFilterDocs}
                                 styleProvider={DefaultStyleProvider}
                                 docViewPath={returnEmptyDoclist}
-                                moveDocument={this.props.moveDocument}
+                                moveDocument={this._props.moveDocument}
                                 addDocument={this.addRow}
-                                removeDocument={this.props.removeDocument}
+                                removeDocument={this._props.removeDocument}
                                 whenChildContentsActiveChanged={returnFalse}
-                                addDocTab={this.props.addDocTab}
-                                pinToPres={this.props.pinToPres}
+                                addDocTab={this._props.addDocTab}
+                                pinToPres={this._props.pinToPres}
                                 bringToFront={returnFalse}
                             />
                         )}
@@ -936,7 +942,7 @@ class CollectionSchemaViewDocs extends React.Component<CollectionSchemaViewDocsP
         return (
             <div className="schema-table-content" ref={this.props.setRef} style={{ height: `calc(100% - ${CollectionSchemaView._newNodeInputHeight + this.props.rowHeight()}px)` }}>
                 {this.props.childDocs().docs.map((doc: Doc, index: number) => (
-                    <div className="schema-row-wrapper" style={{ height: this.props.rowHeight() }}>
+                    <div key={doc[Id]} className="schema-row-wrapper" style={{ height: this.props.rowHeight() }}>
                         <CollectionSchemaViewDoc doc={doc} schema={this.props.schema} index={index} rowHeight={this.props.rowHeight} />
                     </div>
                 ))}
@@ -954,8 +960,18 @@ interface CollectionSchemaViewDocProps {
 
 @observer
 class CollectionSchemaViewDoc extends React.Component<CollectionSchemaViewDocProps> {
-    tableWidthFunc = () => this.props.schema.tableWidth;
-    screenToLocalXf = () => this.props.schema.props.ScreenToLocalTransform().translate(0, -this.props.rowHeight() - this.props.index * this.props.rowHeight());
+    _prevProps: CollectionSchemaViewDocProps;
+    @observable _props;
+    constructor(props: CollectionSchemaViewDocProps) {
+        super(props);
+        this._props = this._prevProps = props;
+        makeObservable(this);
+    }
+    componentDidUpdate() {
+        copyProps(this);
+    }
+    tableWidthFunc = () => this._props.schema.tableWidth;
+    screenToLocalXf = () => this._props.schema._props.ScreenToLocalTransform().translate(0, -this._props.rowHeight() - this._props.index * this._props.rowHeight());
     noOpacityStyleProvider = (doc: Opt<Doc>, props: Opt<DocumentViewProps>, property: string) => {
         if (property === StyleProp.Opacity) return 1;
         return DefaultStyleProvider(doc, props, property);
@@ -963,30 +979,30 @@ class CollectionSchemaViewDoc extends React.Component<CollectionSchemaViewDocPro
     render() {
         return (
             <DocumentView
-                key={this.props.doc[Id]}
-                {...this.props.schema.props}
-                LayoutTemplate={this.props.schema.props.childLayoutTemplate}
-                LayoutTemplateString={SchemaRowBox.LayoutString(this.props.schema.props.fieldKey, this.props.index)}
-                Document={this.props.doc}
-                renderDepth={this.props.schema.props.renderDepth + 1}
+                key={this._props.doc[Id]}
+                {...this._props.schema._props}
+                LayoutTemplate={this._props.schema._props.childLayoutTemplate}
+                LayoutTemplateString={SchemaRowBox.LayoutString(this._props.schema._props.fieldKey, this._props.index)}
+                Document={this._props.doc}
+                renderDepth={this._props.schema._props.renderDepth + 1}
                 PanelWidth={this.tableWidthFunc}
-                PanelHeight={this.props.rowHeight}
+                PanelHeight={this._props.rowHeight}
                 styleProvider={this.noOpacityStyleProvider}
                 waitForDoubleClickToClick={returnNever}
                 defaultDoubleClick={returnIgnore}
                 dragAction="move"
                 onClickScriptDisable="always"
-                focus={this.props.schema.focusDocument}
-                childFilters={this.props.schema.childDocFilters}
-                childFiltersByRanges={this.props.schema.childDocRangeFilters}
-                searchFilterDocs={this.props.schema.searchFilterDocs}
-                rootSelected={this.props.schema.rootSelected}
+                focus={this._props.schema.focusDocument}
+                childFilters={this._props.schema.childDocFilters}
+                childFiltersByRanges={this._props.schema.childDocRangeFilters}
+                searchFilterDocs={this._props.schema.searchFilterDocs}
+                rootSelected={this._props.schema.rootSelected}
                 ScreenToLocalTransform={this.screenToLocalXf}
                 bringToFront={emptyFunction}
                 dragWhenActive={true}
-                isDocumentActive={this.props.schema.props.childDocumentsActive?.() ? this.props.schema.props.isDocumentActive : this.props.schema.isContentActive}
+                isDocumentActive={this._props.schema._props.childDocumentsActive?.() ? this._props.schema._props.isDocumentActive : this._props.schema.isContentActive}
                 isContentActive={emptyFunction}
-                whenChildContentsActiveChanged={this.props.schema.props.whenChildContentsActiveChanged}
+                whenChildContentsActiveChanged={this._props.schema._props.whenChildContentsActiveChanged}
                 hideDecorations={true}
                 hideTitle={true}
                 hideDocumentButtonBar={true}
diff --git a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
index 5a2926159..737d7e0f4 100644
--- a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
@@ -1,13 +1,13 @@
 import * as React from 'react';
 import { IconButton, Size } from 'browndash-components';
-import { computed } from 'mobx';
+import { computed, makeObservable, override } from 'mobx';
 import { observer } from 'mobx-react';
 import { computedFn } from 'mobx-utils';
 import { CgClose } from 'react-icons/cg';
 import { FaExternalLinkAlt } from 'react-icons/fa';
 import { Doc } from '../../../../fields/Doc';
 import { BoolCast } from '../../../../fields/Types';
-import { emptyFunction, returnFalse, setupMoveUpEvents } from '../../../../Utils';
+import { copyProps, emptyFunction, returnFalse, setupMoveUpEvents } from '../../../../Utils';
 import { DragManager } from '../../../util/DragManager';
 import { SnappingManager } from '../../../util/SnappingManager';
 import { Transform } from '../../../util/Transform';
@@ -28,17 +28,27 @@ export class SchemaRowBox extends ViewBoxBaseComponent<FieldViewProps & SchemaRo
     public static LayoutString(fieldKey: string, rowIndex: number) {
         return FieldView.LayoutString(SchemaRowBox, fieldKey).replace('fieldKey', `rowIndex={${rowIndex}} fieldKey`);
     }
-
     private _ref: HTMLDivElement | null = null;
 
+    _prevProps: FieldViewProps & SchemaRowBoxProps;
+    @override _props: FieldViewProps & SchemaRowBoxProps;
+    constructor(props: FieldViewProps & SchemaRowBoxProps) {
+        super(props);
+        this._props = this._prevProps = props;
+        makeObservable(this);
+    }
+    componentDidUpdate() {
+        copyProps(this);
+    }
+
     bounds = () => this._ref?.getBoundingClientRect();
 
     @computed get schemaView() {
-        return this.props.DocumentView?.()._props.docViewPath().lastElement()?.ComponentView as CollectionSchemaView;
+        return this._props.DocumentView?.()._props.docViewPath().lastElement()?.ComponentView as CollectionSchemaView;
     }
 
     @computed get schemaDoc() {
-        return this.props.DocumentView?.()._props.docViewPath().lastElement()?.Document;
+        return this._props.DocumentView?.()._props.docViewPath().lastElement()?.Document;
     }
 
     @computed get rowIndex() {
@@ -46,7 +56,7 @@ export class SchemaRowBox extends ViewBoxBaseComponent<FieldViewProps & SchemaRo
     }
 
     componentDidMount(): void {
-        this.props.setContentView?.(this);
+        this._props.setContentView?.(this);
     }
 
     select = (ctrlKey: boolean, shiftKey: boolean) => {
@@ -54,12 +64,12 @@ export class SchemaRowBox extends ViewBoxBaseComponent<FieldViewProps & SchemaRo
         const lastSelected = Array.from(this.schemaView._selectedDocs).lastElement();
         if (shiftKey && lastSelected) this.schemaView.selectRows(this.Document, lastSelected);
         else {
-            this.props.select?.(ctrlKey);
+            this._props.select?.(ctrlKey);
         }
     };
 
     onPointerEnter = (e: any) => {
-        if (SnappingManager.IsDragging && this.props.isContentActive()) {
+        if (SnappingManager.IsDragging && this._props.isContentActive()) {
             document.removeEventListener('pointermove', this.onPointerMove);
             document.addEventListener('pointermove', this.onPointerMove);
         }
@@ -103,7 +113,7 @@ export class SchemaRowBox extends ViewBoxBaseComponent<FieldViewProps & SchemaRo
         return (
             <div
                 className="schema-row"
-                style={{ height: this.props.PanelHeight(), backgroundColor: this.props.isSelected() ? Colors.LIGHT_BLUE : undefined }}
+                style={{ height: this._props.PanelHeight(), backgroundColor: this._props.isSelected() ? Colors.LIGHT_BLUE : undefined }}
                 onPointerEnter={this.onPointerEnter}
                 onPointerLeave={this.onPointerLeave}
                 ref={(row: HTMLDivElement | null) => {
@@ -114,7 +124,7 @@ export class SchemaRowBox extends ViewBoxBaseComponent<FieldViewProps & SchemaRo
                     className="row-menu"
                     style={{
                         width: CollectionSchemaView._rowMenuWidth,
-                        pointerEvents: !this.props.isContentActive() ? 'none' : undefined,
+                        pointerEvents: !this._props.isContentActive() ? 'none' : undefined,
                     }}>
                     <IconButton
                         tooltip="close"
@@ -128,7 +138,7 @@ export class SchemaRowBox extends ViewBoxBaseComponent<FieldViewProps & SchemaRo
                                 emptyFunction,
                                 undoable(e => {
                                     e.stopPropagation();
-                                    this.props.removeDocument?.(this.Document);
+                                    this._props.removeDocument?.(this.Document);
                                 }, 'Delete Row')
                             )
                         }
@@ -145,7 +155,7 @@ export class SchemaRowBox extends ViewBoxBaseComponent<FieldViewProps & SchemaRo
                                 emptyFunction,
                                 undoable(e => {
                                     e.stopPropagation();
-                                    this.props.addDocTab(this.Document, OpenWhere.addRight);
+                                    this._props.addDocTab(this.Document, OpenWhere.addRight);
                                 }, 'Open schema Doc preview')
                             )
                         }
@@ -161,7 +171,7 @@ export class SchemaRowBox extends ViewBoxBaseComponent<FieldViewProps & SchemaRo
                             allowCRs={false} // to enter text with new lines, must use \n
                             columnWidth={this.columnWidth(index)}
                             rowHeight={this.schemaView.rowHeightFunc}
-                            isRowActive={this.props.isContentActive}
+                            isRowActive={this._props.isContentActive}
                             getFinfo={this.getFinfo}
                             selectCell={this.selectCell}
                             deselectCell={this.deselectCell}
@@ -172,7 +182,7 @@ export class SchemaRowBox extends ViewBoxBaseComponent<FieldViewProps & SchemaRo
                             transform={() => {
                                 const ind = index === this.schemaView.columnKeys.length - 1 ? this.schemaView.columnKeys.length - 3 : index;
                                 const x = this.schemaView?.displayColumnWidths.reduce((p, c, i) => (i <= ind ? p + c : p), 0);
-                                const y = (this.props.rowIndex ?? 0) * this.props.PanelHeight();
+                                const y = (this._props.rowIndex ?? 0) * this._props.PanelHeight();
                                 return new Transform(x + CollectionSchemaView._rowMenuWidth, y, 1);
                             }}
                         />
diff --git a/src/client/views/global/globalScripts.ts b/src/client/views/global/globalScripts.ts
index dcd3bffac..814003955 100644
--- a/src/client/views/global/globalScripts.ts
+++ b/src/client/views/global/globalScripts.ts
@@ -21,18 +21,18 @@ import { RichTextMenu } from '../nodes/formattedText/RichTextMenu';
 import { WebBox } from '../nodes/WebBox';
 
 ScriptingGlobals.add(function IsNoneSelected() {
-    return SelectionManager.Views().length <= 0;
+    return SelectionManager.Views.length <= 0;
 }, 'are no document selected');
 
 // toggle: Set overlay status of selected document
 ScriptingGlobals.add(function setView(view: string) {
-    const selected = SelectionManager.Docs().lastElement();
+    const selected = SelectionManager.Docs.lastElement();
     selected ? (selected._type_collection = view) : console.log('[FontIconBox.tsx] changeView failed');
 });
 
 // toggle: Set overlay status of selected document
 ScriptingGlobals.add(function setBackgroundColor(color?: string, checkResult?: boolean) {
-    const selectedViews = SelectionManager.Views();
+    const selectedViews = SelectionManager.Views;
     if (Doc.ActiveTool !== InkTool.None) {
         if (checkResult) {
             return ActiveFillColor();
@@ -60,7 +60,7 @@ ScriptingGlobals.add(function setBackgroundColor(color?: string, checkResult?: b
             }
         });
     } else {
-        const selected = SelectionManager.Docs().length ? SelectionManager.Docs() : LinkManager.currentLink ? [LinkManager.currentLink] : [];
+        const selected = SelectionManager.Docs.length ? SelectionManager.Docs : LinkManager.currentLink ? [LinkManager.currentLink] : [];
         if (checkResult) {
             return selected.lastElement()?._backgroundColor ?? 'transparent';
         }
@@ -72,10 +72,10 @@ ScriptingGlobals.add(function setBackgroundColor(color?: string, checkResult?: b
 // toggle: Set overlay status of selected document
 ScriptingGlobals.add(function setHeaderColor(color?: string, checkResult?: boolean) {
     if (checkResult) {
-        return SelectionManager.Views().length ? StrCast(SelectionManager.Docs().lastElement().layout_headingColor) : Doc.SharingDoc().headingColor;
+        return SelectionManager.Views.length ? StrCast(SelectionManager.Docs.lastElement().layout_headingColor) : Doc.SharingDoc().headingColor;
     }
-    if (SelectionManager.Views().length) {
-        SelectionManager.Docs().forEach(doc => {
+    if (SelectionManager.Views.length) {
+        SelectionManager.Docs.forEach(doc => {
             Doc.GetProto(doc).layout_headingColor = color;
             doc.layout_showTitle = color === 'transparent' ? undefined : StrCast(doc.layout_showTitle, 'title');
         });
@@ -88,7 +88,7 @@ ScriptingGlobals.add(function setHeaderColor(color?: string, checkResult?: boole
 
 // toggle: Set overlay status of selected document
 ScriptingGlobals.add(function toggleOverlay(checkResult?: boolean) {
-    const selected = SelectionManager.Views().length ? SelectionManager.Views()[0] : undefined;
+    const selected = SelectionManager.Views.length ? SelectionManager.Views[0] : undefined;
     if (checkResult) {
         if (NumCast(selected?.Document.z) >= 1) return true;
         return false;
@@ -97,7 +97,7 @@ ScriptingGlobals.add(function toggleOverlay(checkResult?: boolean) {
 });
 
 ScriptingGlobals.add(function showFreeform(attr: 'flashcards' | 'center' | 'grid' | 'snaplines' | 'clusters' | 'arrange' | 'viewAll' | 'fitOnce', checkResult?: boolean) {
-    const selected = SelectionManager.Docs().lastElement();
+    const selected = SelectionManager.Docs.lastElement();
     // prettier-ignore
     const map: Map<'flashcards' | 'center' |'grid' | 'snaplines' | 'clusters' | 'arrange'| 'viewAll' | 'fitOnce', { waitForRender?: boolean, checkResult: (doc:Doc) => any; setDoc: (doc:Doc, dv:DocumentView) => void;}> = new Map([
         ['grid', {
@@ -140,13 +140,13 @@ ScriptingGlobals.add(function showFreeform(attr: 'flashcards' | 'center' | 'grid
         return map.get(attr)?.checkResult(selected);
     }
     const batch = map.get(attr)?.waitForRender ? UndoManager.StartBatch('set freeform attribute') : { end: () => {} };
-    SelectionManager.Views().map(dv => map.get(attr)?.setDoc(dv.layoutDoc, dv));
+    SelectionManager.Views.map(dv => map.get(attr)?.setDoc(dv.layoutDoc, dv));
     setTimeout(() => batch.end(), 100);
 });
 
 ScriptingGlobals.add(function setFontAttr(attr: 'font' | 'fontColor' | 'highlight' | 'fontSize' | 'alignment', value: any, checkResult?: boolean) {
     const editorView = RichTextMenu.Instance?.TextView?.EditorView;
-    const selected = SelectionManager.Docs().lastElement();
+    const selected = SelectionManager.Docs.lastElement();
     // prettier-ignore
     const map: Map<'font'|'fontColor'|'highlight'|'fontSize'|'alignment', { checkResult: () => any; setDoc: () => void;}> = new Map([
         ['font', {
@@ -338,7 +338,7 @@ ScriptingGlobals.add(setActiveTool, 'sets the active ink tool mode');
 
 // toggle: Set overlay status of selected document
 ScriptingGlobals.add(function setInkProperty(option: 'inkMask' | 'fillColor' | 'strokeWidth' | 'strokeColor', value: any, checkResult?: boolean) {
-    const selected = SelectionManager.Docs().lastElement() ?? Doc.UserDoc();
+    const selected = SelectionManager.Docs.lastElement() ?? Doc.UserDoc();
     // prettier-ignore
     const map: Map<'inkMask' | 'fillColor' | 'strokeWidth' | 'strokeColor', { checkResult: () => any; setInk: (doc: Doc) => void; setMode: () => void }> = new Map([
         ['inkMask', {
@@ -367,16 +367,14 @@ ScriptingGlobals.add(function setInkProperty(option: 'inkMask' | 'fillColor' | '
         return map.get(option)?.checkResult();
     }
     map.get(option)?.setMode();
-    SelectionManager.Docs()
-        .filter(doc => doc.type === DocumentType.INK)
-        .map(doc => map.get(option)?.setInk(doc));
+    SelectionManager.Docs.filter(doc => doc.type === DocumentType.INK).map(doc => map.get(option)?.setInk(doc));
 });
 
 /** WEB
  *      webSetURL
  **/
 ScriptingGlobals.add(function webSetURL(url: string, checkResult?: boolean) {
-    const selected = SelectionManager.Views().lastElement();
+    const selected = SelectionManager.Views.lastElement();
     if (selected?.Document.type === DocumentType.WEB) {
         if (checkResult) {
             return StrCast(selected.Document.data, Cast(selected.Document.data, WebField, null)?.url?.href);
@@ -386,14 +384,14 @@ ScriptingGlobals.add(function webSetURL(url: string, checkResult?: boolean) {
     }
 });
 ScriptingGlobals.add(function webForward(checkResult?: boolean) {
-    const selected = SelectionManager.Views().lastElement()?.ComponentView as WebBox;
+    const selected = SelectionManager.Views.lastElement()?.ComponentView as WebBox;
     if (checkResult) {
         return selected?.forward(checkResult) ? undefined : 'lightGray';
     }
     selected?.forward();
 });
 ScriptingGlobals.add(function webBack(checkResult?: boolean) {
-    const selected = SelectionManager.Views().lastElement()?.ComponentView as WebBox;
+    const selected = SelectionManager.Views.lastElement()?.ComponentView as WebBox;
     if (checkResult) {
         return selected?.back(checkResult) ? undefined : 'lightGray';
     }
@@ -404,7 +402,7 @@ ScriptingGlobals.add(function webBack(checkResult?: boolean) {
  *      toggleSchemaPreview
  **/
 ScriptingGlobals.add(function toggleSchemaPreview(checkResult?: boolean) {
-    const selected = SelectionManager.Docs().lastElement();
+    const selected = SelectionManager.Docs.lastElement();
     if (checkResult && selected) {
         const result: boolean = NumCast(selected.schema_previewWidth) > 0;
         if (result) return Colors.MEDIUM_BLUE;
@@ -418,7 +416,7 @@ ScriptingGlobals.add(function toggleSchemaPreview(checkResult?: boolean) {
     }
 });
 ScriptingGlobals.add(function toggleSingleLineSchema(checkResult?: boolean) {
-    const selected = SelectionManager.Docs().lastElement();
+    const selected = SelectionManager.Docs.lastElement();
     if (checkResult && selected) {
         return NumCast(selected._schema_singleLine) > 0 ? Colors.MEDIUM_BLUE : 'transparent';
     }
@@ -431,7 +429,7 @@ ScriptingGlobals.add(function toggleSingleLineSchema(checkResult?: boolean) {
  *      groupBy
  */
 ScriptingGlobals.add(function setGroupBy(key: string, checkResult?: boolean) {
-    SelectionManager.Docs().map(doc => (doc._text_fontFamily = key));
+    SelectionManager.Docs.map(doc => (doc._text_fontFamily = key));
     const editorView = RichTextMenu.Instance.TextView?.EditorView;
     if (checkResult) {
         return StrCast((editorView ? RichTextMenu.Instance : Doc.UserDoc()).fontFamily);
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index cca2ed3ba..08ee708f7 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -400,7 +400,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
 
     startDragging(x: number, y: number, dropAction: dropActionType, hideSource = false) {
         if (this._mainCont.current) {
-            const views = SelectionManager.Views().filter(dv => dv.docView?._mainCont.current);
+            const views = SelectionManager.Views.filter(dv => dv.docView?._mainCont.current);
             const selected = views.length > 1 && views.some(dv => dv.Document === this.Document) ? views : [this._props.DocumentView()];
             const dragData = new DragManager.DocumentDragData(selected.map(dv => dv.Document));
             const [left, top] = this._props.ScreenToLocalTransform().scale(this.NativeDimScaling).inverse().transformPoint(0, 0);
@@ -760,8 +760,8 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
                 if (this._props.bringToFront !== emptyFunction) {
                     const zorders = cm.findByDescription('ZOrder...');
                     const zorderItems: ContextMenuProps[] = zorders && 'subitems' in zorders ? zorders.subitems : [];
-                    zorderItems.push({ description: 'Bring to Front', event: () => SelectionManager.Views().forEach(dv => dv._props.bringToFront(dv.Document, false)), icon: 'arrow-up' });
-                    zorderItems.push({ description: 'Send to Back', event: () => SelectionManager.Views().forEach(dv => dv._props.bringToFront(dv.Document, true)), icon: 'arrow-down' });
+                    zorderItems.push({ description: 'Bring to Front', event: () => SelectionManager.Views.forEach(dv => dv._props.bringToFront(dv.Document, false)), icon: 'arrow-up' });
+                    zorderItems.push({ description: 'Send to Back', event: () => SelectionManager.Views.forEach(dv => dv._props.bringToFront(dv.Document, true)), icon: 'arrow-down' });
                     zorderItems.push({
                         description: !this.layoutDoc._keepZDragged ? 'Keep ZIndex when dragged' : 'Allow ZIndex to change when dragged',
                         event: undoBatch(action(() => (this.layoutDoc._keepZWhenDragged = !this.layoutDoc._keepZWhenDragged))),
@@ -1588,7 +1588,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
     docViewPathFunc = () => this.docViewPath;
     isSelected = () => this.SELECTED;
     select = (extendSelection: boolean, focusSelection?: boolean) => {
-        if (this.SELECTED && SelectionManager.Views().length > 1) SelectionManager.DeselectView(this);
+        if (this.SELECTED && SelectionManager.Views.length > 1) SelectionManager.DeselectView(this);
         else {
             SelectionManager.SelectView(this, extendSelection);
             if (focusSelection) {
diff --git a/src/client/views/nodes/FontIconBox/FontIconBox.tsx b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
index 22339907f..d8b1f125c 100644
--- a/src/client/views/nodes/FontIconBox/FontIconBox.tsx
+++ b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
@@ -187,7 +187,7 @@ export class FontIconBox extends ViewBoxBaseComponent<ButtonProps>() {
         let icon: IconProp = 'caret-down';
         const isViewDropdown = script?.script.originalScript.startsWith('setView');
         if (isViewDropdown) {
-            const selected = SelectionManager.Docs();
+            const selected = SelectionManager.Docs;
             if (selected.lastElement()) {
                 if (StrCast(selected.lastElement().type) === DocumentType.COL) {
                     text = StrCast(selected.lastElement()._type_collection);
diff --git a/src/client/views/nodes/LinkAnchorBox.tsx b/src/client/views/nodes/LinkAnchorBox.tsx
index 31aa15588..a7e905fca 100644
--- a/src/client/views/nodes/LinkAnchorBox.tsx
+++ b/src/client/views/nodes/LinkAnchorBox.tsx
@@ -83,9 +83,9 @@ export class LinkAnchorBox extends ViewBoxBaseComponent<FieldViewProps>() {
         const anchor = this.fieldKey === 'link_anchor_1' ? 'link_anchor_2' : 'link_anchor_1';
         const anchorScale = !this.dataDoc[this.fieldKey + '_useSmallAnchor'] && (x === 0 || x === 100 || y === 0 || y === 100) ? 1 : 0.25;
         const targetTitle = StrCast((this.dataDoc[anchor] as Doc)?.title);
-        const selView = SelectionManager.Views().lastElement()?._props.LayoutTemplateString?.includes('link_anchor_1')
+        const selView = SelectionManager.Views.lastElement()?._props.LayoutTemplateString?.includes('link_anchor_1')
             ? 'link_anchor_1'
-            : SelectionManager.Views().lastElement()?._props.LayoutTemplateString?.includes('link_anchor_2')
+            : SelectionManager.Views.lastElement()?._props.LayoutTemplateString?.includes('link_anchor_2')
               ? 'link_anchor_2'
               : '';
         return (
diff --git a/src/client/views/nodes/MapBox/MapAnchorMenu.tsx b/src/client/views/nodes/MapBox/MapAnchorMenu.tsx
index e6c1db0af..ee1ea3ceb 100644
--- a/src/client/views/nodes/MapBox/MapAnchorMenu.tsx
+++ b/src/client/views/nodes/MapBox/MapAnchorMenu.tsx
@@ -47,7 +47,7 @@ export class MapAnchorMenu extends AntimodeMenu<AntimodeMenuProps> {
 
     componentDidMount() {
         this._disposer = reaction(
-            () => SelectionManager.Views().slice(),
+            () => SelectionManager.Views.slice(),
             sel => MapAnchorMenu.Instance.fadeOut(true)
         );
     }
diff --git a/src/client/views/nodes/MapBox/MapBox2.tsx b/src/client/views/nodes/MapBox/MapBox2.tsx
index 2c4c992d1..fdd8285d5 100644
--- a/src/client/views/nodes/MapBox/MapBox2.tsx
+++ b/src/client/views/nodes/MapBox/MapBox2.tsx
@@ -510,8 +510,8 @@
 //     // TODO: auto center on select a document in the sidebar
 //     private handleMapCenter = (map: google.maps.Map) => {
 //         // console.log("print the selected views in selectionManager:")
-//         // if (SelectionManager.Views().lastElement()) {
-//         //     console.log(SelectionManager.Views().lastElement());
+//         // if (SelectionManager.Views.lastElement()) {
+//         //     console.log(SelectionManager.Views.lastElement());
 //         // }
 //     };
 
diff --git a/src/client/views/nodes/formattedText/RichTextMenu.tsx b/src/client/views/nodes/formattedText/RichTextMenu.tsx
index d7e799161..7de1eb717 100644
--- a/src/client/views/nodes/formattedText/RichTextMenu.tsx
+++ b/src/client/views/nodes/formattedText/RichTextMenu.tsx
@@ -116,7 +116,7 @@ export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps> {
     }
     componentDidMount() {
         this._disposer = reaction(
-            () => SelectionManager.Views().slice(),
+            () => SelectionManager.Views.slice(),
             views => this.updateMenu(undefined, undefined, undefined, undefined)
         );
     }
@@ -245,8 +245,8 @@ export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps> {
                 m.type === state.schema.marks.pFontSize && activeSizes.add(m.attrs.fontSize);
                 m.type === state.schema.marks.marker && activeHighlights.add(String(m.attrs.highlight));
             });
-        } else if (SelectionManager.Views().some(dv => dv.ComponentView instanceof EquationBox)) {
-            SelectionManager.Views().forEach(dv => StrCast(dv.Document._text_fontSize) && activeSizes.add(StrCast(dv.Document._text_fontSize)));
+        } else if (SelectionManager.Views.some(dv => dv.ComponentView instanceof EquationBox)) {
+            SelectionManager.Views.forEach(dv => StrCast(dv.Document._text_fontSize) && activeSizes.add(StrCast(dv.Document._text_fontSize)));
         }
         return { activeFamilies: Array.from(activeFamilies), activeSizes: Array.from(activeSizes), activeColors: Array.from(activeColors), activeHighlights: Array.from(activeHighlights) };
     }
@@ -365,8 +365,8 @@ export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps> {
                 this.setMark(fmark, this.view.state, (tx: any) => this.view!.dispatch(tx.addStoredMark(fmark)), true);
                 this.view.focus();
             }
-        } else if (SelectionManager.Views().some(dv => dv.ComponentView instanceof EquationBox)) {
-            SelectionManager.Views().forEach(dv => (dv.Document._text_fontSize = fontSize));
+        } else if (SelectionManager.Views.some(dv => dv.ComponentView instanceof EquationBox)) {
+            SelectionManager.Views.forEach(dv => (dv.Document._text_fontSize = fontSize));
         } else Doc.UserDoc().fontSize = fontSize;
         this.updateMenu(this.view, undefined, this._props, this.layoutDoc);
     };
@@ -649,7 +649,7 @@ export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps> {
                         if (linkDoc instanceof Doc) {
                             const link_anchor_1 = await Cast(linkDoc.link_anchor_1, Doc);
                             const link_anchor_2 = await Cast(linkDoc.link_anchor_2, Doc);
-                            const currentDoc = SelectionManager.Docs().lastElement();
+                            const currentDoc = SelectionManager.Docs.lastElement();
                             if (currentDoc && link_anchor_1 && link_anchor_2) {
                                 if (Doc.AreProtosEqual(currentDoc, link_anchor_1)) {
                                     return StrCast(link_anchor_2.title);
@@ -781,11 +781,11 @@ export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps> {
         //         <div className="collectionMenu-divider" key="divider 3" />
         //         {[this.createMarksDropdown(this.activeFontSize, this.fontSizeOptions, "font size", action((val: string) => {
         //             this.activeFontSize = val;
-        //             SelectionManager.Views().map(dv => dv.props.Document._text_fontSize = val);
+        //             SelectionManager.Views.map(dv => dv.props.Document._text_fontSize = val);
         //         })),
         //         this.createMarksDropdown(this.activeFontFamily, this.fontFamilyOptions, "font family", action((val: string) => {
         //             this.activeFontFamily = val;
-        //             SelectionManager.Views().map(dv => dv.props.Document._text_fontFamily = val);
+        //             SelectionManager.Views.map(dv => dv.props.Document._text_fontFamily = val);
         //         })),
         //         <div className="collectionMenu-divider" key="divider 4" />,
         //         this.createNodesDropdown(this.activeListType, this.listTypeOptions, "list type", () => ({})),
diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx
index a224ec7fa..4ff816812 100644
--- a/src/client/views/nodes/trails/PresBox.tsx
+++ b/src/client/views/nodes/trails/PresBox.tsx
@@ -139,7 +139,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
         return false;
     }
     @computed get selectedDocumentView() {
-        if (SelectionManager.Views().length) return SelectionManager.Views()[0];
+        if (SelectionManager.Views.length) return SelectionManager.Views[0];
         if (this.selectedArray.size) return DocumentManager.Instance.getDocumentView(this.Document);
     }
     @computed get isPres() {
@@ -187,7 +187,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
         this._unmounting = false;
         this.turnOffEdit(true);
         this._disposers.selection = reaction(
-            () => SelectionManager.Views().slice(),
+            () => SelectionManager.Views.slice(),
             views => (!PresBox.Instance || views.some(view => view.Document === this.Document)) && this.updateCurrentPresentation(),
             { fireImmediately: true }
         );
diff --git a/src/client/views/pdf/AnchorMenu.tsx b/src/client/views/pdf/AnchorMenu.tsx
index 3c26c307f..0627876fa 100644
--- a/src/client/views/pdf/AnchorMenu.tsx
+++ b/src/client/views/pdf/AnchorMenu.tsx
@@ -69,7 +69,7 @@ export class AnchorMenu extends AntimodeMenu<AntimodeMenuProps> {
 
     componentDidMount() {
         this._disposer = reaction(
-            () => SelectionManager.Views().slice(),
+            () => SelectionManager.Views.slice(),
             sel => AnchorMenu.Instance.fadeOut(true)
         );
     }
@@ -158,7 +158,7 @@ export class AnchorMenu extends AntimodeMenu<AntimodeMenuProps> {
      * all selected text available to summarize but its only supported for pdf and web ATM.
      * @returns Whether the GPT icon for summarization should appear
      */
-    canSummarize = () => SelectionManager.Docs().some(doc => [DocumentType.PDF, DocumentType.WEB].includes(doc.type as any));
+    canSummarize = () => SelectionManager.Docs.some(doc => [DocumentType.PDF, DocumentType.WEB].includes(doc.type as any));
 
     render() {
         const buttons =
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index 349f15c96..a581e9df6 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -119,7 +119,7 @@ export class PDFViewer extends React.Component<IViewerProps> {
 
         this._disposers.selected = reaction(
             () => this._props.isSelected(),
-            selected => SelectionManager.Views().length === 1 && this.setupPdfJsViewer(),
+            selected => SelectionManager.Views.length === 1 && this.setupPdfJsViewer(),
             { fireImmediately: true }
         );
         this._disposers.curPage = reaction(
-- 
cgit v1.2.3-70-g09d2

