From e8dde2173f3fe36e245c1b34af4440c70175bc1c Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Wed, 19 Mar 2025 01:26:33 -0400
Subject: updated react-datepicker

---
 src/client/views/nodes/calendarBox/CalendarBox.tsx | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

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

diff --git a/src/client/views/nodes/calendarBox/CalendarBox.tsx b/src/client/views/nodes/calendarBox/CalendarBox.tsx
index 009eb82cd..1cbfd5fba 100644
--- a/src/client/views/nodes/calendarBox/CalendarBox.tsx
+++ b/src/client/views/nodes/calendarBox/CalendarBox.tsx
@@ -1,23 +1,23 @@
 import { Calendar, EventClickArg, EventDropArg, EventSourceInput } from '@fullcalendar/core';
 import dayGridPlugin from '@fullcalendar/daygrid';
+import interactionPlugin from '@fullcalendar/interaction';
 import multiMonthPlugin from '@fullcalendar/multimonth';
 import timeGrid from '@fullcalendar/timegrid';
-import interactionPlugin from '@fullcalendar/interaction';
 import { IReactionDisposer, action, computed, makeObservable, observable, reaction } from 'mobx';
 import { observer } from 'mobx-react';
 import * as React from 'react';
 import { dateRangeStrToDates } from '../../../../ClientUtils';
 import { Doc } from '../../../../fields/Doc';
-import { BoolCast, NumCast, StrCast } from '../../../../fields/Types';
-import { CollectionSubView, SubCollectionViewProps } from '../../collections/CollectionSubView';
-import './CalendarBox.scss';
+import { DocData } from '../../../../fields/DocSymbols';
 import { Id } from '../../../../fields/FieldSymbols';
+import { BoolCast, NumCast, StrCast } from '../../../../fields/Types';
 import { DocServer } from '../../../DocServer';
-import { DocumentView } from '../DocumentView';
-import { OpenWhere } from '../OpenWhere';
 import { DragManager } from '../../../util/DragManager';
-import { DocData } from '../../../../fields/DocSymbols';
+import { CollectionSubView, SubCollectionViewProps } from '../../collections/CollectionSubView';
 import { ContextMenu } from '../../ContextMenu';
+import { DocumentView } from '../DocumentView';
+import { OpenWhere } from '../OpenWhere';
+import './CalendarBox.scss';
 
 type CalendarView = 'multiMonth' | 'dayGridMonth' | 'timeGridWeek' | 'timeGridDay';
 
-- 
cgit v1.2.3-70-g09d2


From d0fccd1050f5d6ccc24c1e4d2b7d1c0ed94fb2a7 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Sun, 23 Mar 2025 10:27:28 -0400
Subject: updated more [DocData] to .$ things

---
 src/client/util/CalendarManager.tsx                |  5 +--
 src/client/util/LinkManager.ts                     |  6 +--
 src/client/views/DocComponent.tsx                  |  9 ++--
 src/client/views/PropertiesDocContextSelector.tsx  |  2 +-
 src/client/views/PropertiesView.tsx                |  8 +---
 src/client/views/SidebarAnnos.tsx                  |  9 ++--
 src/client/views/StyleProviderQuiz.tsx             |  8 ++--
 src/client/views/TagsView.tsx                      | 33 +++++++--------
 .../views/collections/CollectionDockingView.tsx    |  6 +--
 .../collections/CollectionMasonryViewFieldRow.tsx  |  3 +-
 src/client/views/collections/CollectionMenu.tsx    |  3 +-
 .../views/collections/CollectionNoteTakingView.tsx |  2 +-
 .../collections/CollectionNoteTakingViewColumn.tsx |  2 +-
 .../collections/CollectionStackedTimeline.tsx      |  8 ++--
 .../views/collections/CollectionStackingView.tsx   |  5 +--
 src/client/views/collections/CollectionSubView.tsx | 12 +++++-
 src/client/views/collections/TabDocView.tsx        |  2 +-
 src/client/views/collections/TreeView.tsx          |  5 +--
 .../CollectionFreeFormInfoUI.tsx                   | 11 +++--
 .../collectionFreeForm/CollectionFreeFormView.tsx  | 25 ++++++-----
 .../collectionFreeForm/FaceCollectionBox.tsx       |  4 +-
 .../collectionFreeForm/ImageLabelBox.tsx           | 19 ++++-----
 .../collections/collectionFreeForm/MarqueeView.tsx | 19 ++++-----
 src/client/views/global/globalScripts.ts           | 49 +++++++++-------------
 src/client/views/nodes/AudioBox.tsx                |  2 +-
 src/client/views/nodes/ComparisonBox.tsx           | 10 ++---
 .../views/nodes/DataVizBox/components/TableBox.tsx |  4 +-
 src/client/views/nodes/DiagramBox.tsx              |  5 +--
 src/client/views/nodes/DocumentView.tsx            | 14 +++----
 src/client/views/nodes/ImageBox.tsx                | 42 +++++++++----------
 src/client/views/nodes/KeyValueBox.tsx             |  2 +-
 src/client/views/nodes/LinkBox.tsx                 |  6 +--
 src/client/views/nodes/LinkDescriptionPopup.tsx    |  3 +-
 src/client/views/nodes/PDFBox.tsx                  | 17 ++++----
 .../views/nodes/RecordingBox/RecordingBox.tsx      |  3 +-
 src/client/views/nodes/VideoBox.tsx                | 48 ++++++++++-----------
 src/client/views/nodes/calendarBox/CalendarBox.tsx |  2 +-
 .../nodes/chatbot/chatboxcomponents/ChatBox.tsx    |  6 +--
 .../views/nodes/formattedText/EquationView.tsx     |  5 +--
 src/client/views/nodes/imageEditor/ImageEditor.tsx |  9 ++--
 src/client/views/nodes/trails/PresBox.tsx          |  9 ++--
 src/client/views/smartdraw/SmartDrawHandler.tsx    | 21 +++++-----
 src/client/views/smartdraw/StickerPalette.tsx      | 28 ++++++-------
 src/fields/Doc.ts                                  | 25 ++++++-----
 src/fields/ScriptField.ts                          |  3 +-
 45 files changed, 243 insertions(+), 276 deletions(-)

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

diff --git a/src/client/util/CalendarManager.tsx b/src/client/util/CalendarManager.tsx
index 3357e5d59..1a5a5f889 100644
--- a/src/client/util/CalendarManager.tsx
+++ b/src/client/util/CalendarManager.tsx
@@ -17,7 +17,6 @@ import { TaskCompletionBox } from '../views/nodes/TaskCompletedBox';
 import './CalendarManager.scss';
 import { SnappingManager } from './SnappingManager';
 import { CalendarDate, DateValue } from '@internationalized/date';
-import { DocData } from '../../fields/DocSymbols';
 // import 'react-date-range/dist/styles.css';
 // import 'react-date-range/dist/theme/default.css';
 
@@ -119,7 +118,7 @@ export class CalendarManager extends ObservableReactComponent<object> {
     // TODO: Make undoable
     private addToCalendar = () => {
         const docs = DocumentView.Selected().length < 2 ? [this.targetDoc] : DocumentView.Selected().map(docView => docView.Document);
-        const targetDoc = docs[0]?.[DocData];
+        const targetDoc = docs[0];
 
         if (targetDoc) {
             let calendar: Doc;
@@ -230,7 +229,7 @@ export class CalendarManager extends ObservableReactComponent<object> {
     @computed
     get calendarInterface() {
         const docs = DocumentView.Selected().length < 2 ? [this.targetDoc] : DocumentView.Selected().map(docView => docView.Document);
-        const targetDoc = docs[0]?.[DocData];
+        const targetDoc = docs[0];
 
         return (
             <div
diff --git a/src/client/util/LinkManager.ts b/src/client/util/LinkManager.ts
index d04d41968..3f98ab3c4 100644
--- a/src/client/util/LinkManager.ts
+++ b/src/client/util/LinkManager.ts
@@ -156,7 +156,7 @@ export class LinkManager {
     }
     public deleteLink(linkDoc: Doc) {
         const ret = Doc.RemoveDocFromList(Doc.LinkDBDoc(), 'data', linkDoc);
-        linkDoc[DocData].link_anchor_1 = linkDoc[DocData].link_anchor_2 = undefined;
+        linkDoc.$link_anchor_1 = linkDoc.$link_anchor_2 = undefined;
         return ret;
     }
     public deleteAllLinksOnAnchor(anchor: Doc) {
@@ -258,8 +258,8 @@ export function UPDATE_SERVER_CACHE() {
 
     // print out cached docs
     //Doc.MyDockedBtns.linearView_IsOpen && console.log('Set cached docs = ');
-    const isFiltered = filtered.filter(doc => !Doc.IsSystem(doc));
-    const strings = isFiltered.map(doc => StrCast(doc.title) + ' ' + (Doc.IsDataProto(doc) ? '(data)' : '(embedding)'));
+    // const isFiltered = filtered.filter(doc => !Doc.IsSystem(doc));
+    // const strings = isFiltered.map(doc => StrCast(doc.title) + ' ' + (Doc.IsDataProto(doc) ? '(data)' : '(embedding)'));
     //Doc.MyDockedBtns.linearView_IsOpen && strings.sort().forEach((str, i) => console.log(i.toString() + ' ' + str));
 
     rp.post(ClientUtils.prepend('/setCacheDocumentIds'), {
diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx
index 79a0cc602..a311f6436 100644
--- a/src/client/views/DocComponent.tsx
+++ b/src/client/views/DocComponent.tsx
@@ -49,7 +49,7 @@ export function DocComponent<P extends DocComponentProps>() {
          * This is the unique data repository for a dcoument that stores the intrinsic document data
          */
         @computed get dataDoc() {
-            return this.Document[DocData];
+            return this._props.Document[DocData];
         }
     }
     return Component;
@@ -93,7 +93,7 @@ export function ViewBoxBaseComponent<P extends FieldViewProps>() {
          * This is the unique data repository for a dcoument that stores the intrinsic document data
          */
         @computed get dataDoc() {
-            return this.Document.isTemplateForField || this.Document.isTemplateDoc ? (this._props.TemplateDataDocument ?? this.Document[DocData]) : this.Document[DocData];
+            return this._props.Document.isTemplateForField || this._props.Document.isTemplateDoc ? (this._props.TemplateDataDocument ?? this._props.Document[DocData]) : this._props.Document[DocData];
         }
 
         /**
@@ -151,7 +151,7 @@ export function ViewBoxAnnotatableComponent<P extends FieldViewProps>() {
          * This is the unique data repository for a dcoument that stores the intrinsic document data
          */
         @computed get dataDoc() {
-            return this.Document.isTemplateForField || this.Document.isTemplateDoc ? (this._props.TemplateDataDocument ?? this.Document[DocData]) : this.Document[DocData];
+            return this._props.Document.isTemplateForField || this._props.Document.isTemplateDoc ? (this._props.TemplateDataDocument ?? this._props.Document[DocData]) : this._props.Document[DocData];
         }
 
         /**
@@ -225,8 +225,7 @@ export function ViewBoxAnnotatableComponent<P extends FieldViewProps>() {
                 if ([AclAugment, AclEdit, AclAdmin].includes(effectiveAcl)) {
                     added.forEach(adoc => {
                         adoc._dragOnlyWithinContainer = undefined;
-                        if (annotationKey ?? this._annotationKeySuffix()) adoc[DocData].annotationOn = this.Document;
-                        else adoc[DocData].annotationOn = undefined;
+                        adoc.$annotationOn = (annotationKey ?? this._annotationKeySuffix()) ? this.Document : undefined;
                         Doc.SetContainer(adoc, this.Document);
                         inheritParentAcls(targetDataDoc, adoc, true);
                     });
diff --git a/src/client/views/PropertiesDocContextSelector.tsx b/src/client/views/PropertiesDocContextSelector.tsx
index f494ff16a..ee6486a9c 100644
--- a/src/client/views/PropertiesDocContextSelector.tsx
+++ b/src/client/views/PropertiesDocContextSelector.tsx
@@ -26,7 +26,7 @@ export class PropertiesDocContextSelector extends ObservableReactComponent<Prope
 
     @computed get _docs() {
         if (!this._props.DocView) return [];
-        const target = this._props.DocView._props.Document;
+        const target = this._props.DocView.Document;
         const targetContext = this._props.DocView.containerViewPath?.().lastElement()?.Document;
         const embeddings = Doc.GetEmbeddings(target);
         const containerProtos = embeddings.filter(embedding => embedding.embedContainer && embedding.embedContainer instanceof Doc).reduce((set, embedding) => set.add(Cast(embedding.embedContainer, Doc, null)), new Set<Doc>());
diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx
index b95553c4e..7e9cd002b 100644
--- a/src/client/views/PropertiesView.tsx
+++ b/src/client/views/PropertiesView.tsx
@@ -181,7 +181,7 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
     @action
     docHeight = () => {
         const layoutDoc = this.selectedLayoutDoc;
-        if (layoutDoc && this.dataDoc) {
+        if (layoutDoc) {
             return Math.max(
                 70,
                 Math.min(
@@ -308,11 +308,7 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
     }
 
     @computed get contextCount() {
-        if (this.selectedDocumentView) {
-            const target = this.selectedDocumentView.Document;
-            return Doc.GetEmbeddings(target).length - 1;
-        }
-        return 0;
+        return this.selectedDocumentView ? Doc.GetEmbeddings(this.selectedDocumentView.Document).length - 1 : 0;
     }
 
     @computed get links() {
diff --git a/src/client/views/SidebarAnnos.tsx b/src/client/views/SidebarAnnos.tsx
index 816fc8ed3..b3f3a4478 100644
--- a/src/client/views/SidebarAnnos.tsx
+++ b/src/client/views/SidebarAnnos.tsx
@@ -4,7 +4,6 @@ import * as React from 'react';
 import { ClientUtils, returnAll, returnFalse, returnOne, returnZero } from '../../ClientUtils';
 import { emptyFunction } from '../../Utils';
 import { Doc, DocListCast, Field, FieldResult, FieldType, StrListCast } from '../../fields/Doc';
-import { DocData } from '../../fields/DocSymbols';
 import { Id } from '../../fields/FieldSymbols';
 import { List } from '../../fields/List';
 import { RichTextField } from '../../fields/RichTextField';
@@ -88,9 +87,9 @@ export class SidebarAnnos extends ObservableReactComponent<FieldViewProps & Extr
             .filter(data => data.split(':')[0])
             .filter(data => !filterExlusions?.includes(data.split(':')[0]))
             .map(data => {
-                const key = data.split(':')[0];
+                const key = '$'+data.split(':')[0];
                 const val = Field.Copy(this.allMetadata.get(key));
-                target[DocData][key] = val;
+                target[key] = val;
                 return {
                     type: 'dashField',
                     attrs: { fieldKey: key, docId: '', hideKey: false, hideValue: false, editable: true },
@@ -98,7 +97,7 @@ export class SidebarAnnos extends ObservableReactComponent<FieldViewProps & Extr
                 };
             });
 
-        if (!anchor.text) anchor[DocData].text = '-selection-';
+        if (!anchor.text) anchor.$text = '-selection-';
         const textLines: { type: string; attrs: object; content?: unknown[] }[] = [
             {
                 type: 'paragraph',
@@ -133,7 +132,7 @@ export class SidebarAnnos extends ObservableReactComponent<FieldViewProps & Extr
         };
         if (taggedContent.length) textLines.push(metadatatext);
         if (textLines.length) {
-            target[DocData].text = new RichTextField(
+            target.$text = new RichTextField(
                 JSON.stringify({
                     doc: {
                         type: 'doc',
diff --git a/src/client/views/StyleProviderQuiz.tsx b/src/client/views/StyleProviderQuiz.tsx
index f9ee8d3db..b4a1f53c5 100644
--- a/src/client/views/StyleProviderQuiz.tsx
+++ b/src/client/views/StyleProviderQuiz.tsx
@@ -67,7 +67,7 @@ export namespace styleProviderQuiz {
             newCol.zIndex = 1000;
             newCol.forceActive = true;
             newCol.quiz = text;
-            newCol[DocData][Doc.LayoutFieldKey(newCol) + '_transform'] = 'none';
+            newCol['$' + Doc.LayoutFieldKey(newCol) + '_transform'] = 'none';
             Doc.AddDocToList(img.Document, 'quizBoxes', newCol);
             img.addDocument(newCol);
             //   img._loading = false;
@@ -248,7 +248,7 @@ export namespace styleProviderQuiz {
     function check(img: ImageBox) {
         //this._loading = true;
         imgQuizBoxes(img).forEach(async doc => {
-            const input = StrCast(doc[DocData].title);
+            const input = StrCast(doc.$title);
             if (imgQuizMode(img) == quizMode.SMART && input) {
                 const questionText = 'Question: What was labeled in this image?';
                 const rubricText = ' Rubric: ' + StrCast(doc.quiz);
@@ -275,8 +275,8 @@ export namespace styleProviderQuiz {
 
     function redo(img: ImageBox) {
         imgQuizBoxes(img).forEach(doc => {
-            doc[DocData].title = '';
-            doc.backgroundColor = '#e4e4e4';
+            doc.$title = '';
+            doc.$backgroundColor = '#e4e4e4';
         });
     }
 
diff --git a/src/client/views/TagsView.tsx b/src/client/views/TagsView.tsx
index 93d6fb684..7d2a6be5e 100644
--- a/src/client/views/TagsView.tsx
+++ b/src/client/views/TagsView.tsx
@@ -72,7 +72,7 @@ export class TagItem extends ObservableReactComponent<TagItemProps> {
         const newTagCol = new Doc();
         newTagCol.title = tag;
         newTagCol.collections = new List<Doc>();
-        newTagCol[DocData].docs = new List<Doc>();
+        newTagCol.$docs = new List<Doc>();
         Doc.ActiveDashboard && Doc.AddDocToList(Doc.ActiveDashboard, 'myTagCollections', newTagCol);
 
         return newTagCol;
@@ -82,7 +82,7 @@ export class TagItem extends ObservableReactComponent<TagItemProps> {
      * @param tag tag string
      * @returns An array of documents that contain the tag.
      */
-    public static allDocsWithTag = (tag: string) => DocListCast(TagItem.findTagCollectionDoc(tag)?.[DocData].docs);
+    public static allDocsWithTag = (tag: string) => DocListCast(TagItem.findTagCollectionDoc(tag)?.$docs);
 
     public static docHasTag = (doc: Doc, tag: string) => StrListCast(doc?.tags).includes(tag);
     /**
@@ -95,11 +95,11 @@ export class TagItem extends ObservableReactComponent<TagItemProps> {
 
         // If the document is of type COLLECTION, make it a smart collection, otherwise, add the tag to the document.
         if (doc.type === DocumentType.COL && !doc.annotationOn) {
-            Doc.AddDocToList(tagCollection[DocData], 'collections', doc);
+            Doc.AddDocToList(tagCollection, 'collections', doc);
 
             // Iterate through the tag Doc collections and add a copy of the document to each collection
-            for (const cdoc of DocListCast(tagCollection[DocData].docs)) {
-                if (!DocListCast(doc[DocData].data).find(d => Doc.AreProtosEqual(d, cdoc))) {
+            for (const cdoc of DocListCast(tagCollection.$docs)) {
+                if (!DocListCast(doc.$data).find(d => Doc.AreProtosEqual(d, cdoc))) {
                     const newEmbedding = Doc.MakeEmbedding(cdoc);
                     Doc.AddDocToList(doc[DocData], 'data', newEmbedding);
                     Doc.SetContainer(newEmbedding, doc);
@@ -111,7 +111,7 @@ export class TagItem extends ObservableReactComponent<TagItemProps> {
 
             // Iterate through the tag document's collections and add a copy of the document to each collection
             for (const collection of DocListCast(tagCollection.collections)) {
-                if (!DocListCast(collection[DocData].data).find(d => Doc.AreProtosEqual(d, doc))) {
+                if (!DocListCast(collection.$data).find(d => Doc.AreProtosEqual(d, doc))) {
                     const newEmbedding = Doc.MakeEmbedding(doc);
                     Doc.AddDocToList(collection[DocData], 'data', newEmbedding);
                     Doc.SetContainer(newEmbedding, collection);
@@ -119,8 +119,8 @@ export class TagItem extends ObservableReactComponent<TagItemProps> {
             }
         }
 
-        if (!doc[DocData].tags) doc[DocData].tags = new List<string>();
-        const tagList = doc[DocData].tags as List<string>;
+        if (!doc.$tags) doc.$tags = new List<string>();
+        const tagList = doc.$tags as List<string>;
         if (!tagList.includes(tag)) tagList.push(tag);
     };
 
@@ -131,22 +131,22 @@ export class TagItem extends ObservableReactComponent<TagItemProps> {
      * @param tagDoc doc that collections the Docs with the tag
      */
     public static removeTagFromDoc = (doc: Doc, tag: string, tagDoc?: Doc) => {
-        if (doc[DocData].tags) {
+        if (doc.$tags) {
             if (doc.type === DocumentType.COL) {
                 tagDoc && Doc.RemoveDocFromList(tagDoc[DocData], 'collections', doc);
 
                 for (const cur_doc of TagItem.allDocsWithTag(tag)) {
-                    doc[DocData].data = new List<Doc>(DocListCast(doc[DocData].data).filter(d => !Doc.AreProtosEqual(cur_doc, d)));
+                    doc.$data = new List<Doc>(DocListCast(doc.$data).filter(d => !Doc.AreProtosEqual(cur_doc, d)));
                 }
             } else {
                 tagDoc && Doc.RemoveDocFromList(tagDoc[DocData], 'docs', doc);
 
                 for (const collection of DocListCast(tagDoc?.collections)) {
-                    collection[DocData].data = new List<Doc>(DocListCast(collection[DocData].data).filter(d => !Doc.AreProtosEqual(doc, d)));
+                    collection.$data = new List<Doc>(DocListCast(collection.$data).filter(d => !Doc.AreProtosEqual(doc, d)));
                 }
             }
         }
-        doc[DocData].tags = new List<string>(StrListCast(doc[DocData].tags).filter(label => label !== tag));
+        doc.$tags = new List<string>(StrListCast(doc.$tags).filter(label => label !== tag));
     };
 
     private _ref: React.RefObject<HTMLDivElement>;
@@ -171,11 +171,10 @@ export class TagItem extends ObservableReactComponent<TagItemProps> {
 
         // Create a new collection and set up configurations.
         const newCollection = ((doc: Doc) => {
-            const docData = doc[DocData];
-            docData.data = new List<Doc>(newEmbeddings);
-            docData.title = this._props.tag;
-            docData.tags = new List<string>([this._props.tag]);
-            docData.freeform_fitContentsToBox = true;
+            doc.$data = new List<Doc>(newEmbeddings);
+            doc.$title = this._props.tag;
+            doc.$tags = new List<string>([this._props.tag]);
+            doc.$freeform_fitContentsToBox = true;
             doc._freeform_panX = doc._freeform_panY = 0;
             doc._width = 900;
             doc._height = 900;
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index a45b37f43..12a131deb 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -5,7 +5,7 @@ import * as ReactDOM from 'react-dom/client';
 import ResizeObserver from 'resize-observer-polyfill';
 import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, DivHeight, DivWidth, incrementTitleCopy, returnTrue, UpdateIcon } from '../../../ClientUtils';
 import { Doc, DocListCast, Field, Opt } from '../../../fields/Doc';
-import { AclAdmin, AclEdit, DocData } from '../../../fields/DocSymbols';
+import { AclAdmin, AclEdit } from '../../../fields/DocSymbols';
 import { Id } from '../../../fields/FieldSymbols';
 import { InkTool } from '../../../fields/InkField';
 import { List } from '../../../fields/List';
@@ -481,7 +481,7 @@ export class CollectionDockingView extends CollectionSubView() {
             Array.from(cloned.map.entries()).forEach(entry => {
                 json = json.replace(entry[0], entry[1][Id]);
             });
-            cloned.clone[DocData].dockingConfig = json;
+            cloned.clone.$dockingConfig = json;
             return DashboardView.openDashboard(cloned.clone);
         }
         const matches = json.match(/"documentId":"[a-z0-9-]+"/g);
@@ -495,7 +495,7 @@ export class CollectionDockingView extends CollectionSubView() {
             const newtab = origtabdocs.length ? Doc.MakeCopy(origtab, true, undefined, true) : Doc.MakeEmbedding(origtab);
             const newtabdocs = origtabdocs.map(origtabdoc => Doc.MakeEmbedding(origtabdoc));
             if (newtabdocs.length) {
-                newtab[DocData].data = new List<Doc>(newtabdocs);
+                newtab.$data = new List<Doc>(newtabdocs);
                 newtabdocs.forEach(ntab => Doc.SetContainer(ntab, newtab));
             }
             json = json.replace(origtab[Id], newtab[Id]);
diff --git a/src/client/views/collections/CollectionMasonryViewFieldRow.tsx b/src/client/views/collections/CollectionMasonryViewFieldRow.tsx
index 996626575..4fe73895e 100644
--- a/src/client/views/collections/CollectionMasonryViewFieldRow.tsx
+++ b/src/client/views/collections/CollectionMasonryViewFieldRow.tsx
@@ -5,7 +5,6 @@ import * as React from 'react';
 import { returnEmptyString, returnFalse, setupMoveUpEvents } from '../../../ClientUtils';
 import { emptyFunction, numberRange } from '../../../Utils';
 import { Doc } from '../../../fields/Doc';
-import { DocData } from '../../../fields/DocSymbols';
 import { PastelSchemaPalette, SchemaHeaderField } from '../../../fields/SchemaHeaderField';
 import { ScriptField } from '../../../fields/ScriptField';
 import { Docs } from '../../documents/Documents';
@@ -164,7 +163,7 @@ export class CollectionMasonryViewFieldRow extends ObservableReactComponent<CMVF
         const { pivotField } = this._props;
         const newDoc = Docs.Create.TextDocument(value, { _layout_autoHeight: true, _width: 200, _layout_fitWidth: true, title: value });
         DocumentView.SetSelectOnLoad(newDoc);
-        pivotField && (newDoc[DocData][pivotField] = this.getValue(this._props.heading));
+        pivotField && (newDoc['$' + pivotField] = this.getValue(this._props.heading));
         const docs = this._props.parent.childDocList;
         return docs ? !!docs.splice(0, 0, newDoc) : this._props.parent._props.addDocument?.(newDoc) || false; // should really extend addDocument to specify insertion point (at beginning of list)
     };
diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx
index de999c91a..26aca458c 100644
--- a/src/client/views/collections/CollectionMenu.tsx
+++ b/src/client/views/collections/CollectionMenu.tsx
@@ -9,7 +9,6 @@ import * as React from 'react';
 import { ClientUtils, returnEmptyFilter, returnFalse, returnTrue, setupMoveUpEvents } from '../../../ClientUtils';
 import { emptyFunction } from '../../../Utils';
 import { Doc, DocListCast, Opt, returnEmptyDoclist } from '../../../fields/Doc';
-import { DocData } from '../../../fields/DocSymbols';
 import { List } from '../../../fields/List';
 import { ObjectField } from '../../../fields/ObjectField';
 import { RichTextField } from '../../../fields/RichTextField';
@@ -213,7 +212,7 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewMenu
         title: 'set content',
         script: 'getProto(this.target).data = copyField(this.source);',
         immediate: undoable((source: Doc[]) => {
-            this.target[DocData].data = new List<Doc>(source);
+            this.target.$data = new List<Doc>(source);
         }, ''),
         initialize: emptyFunction,
     };
diff --git a/src/client/views/collections/CollectionNoteTakingView.tsx b/src/client/views/collections/CollectionNoteTakingView.tsx
index c499bd288..4650727eb 100644
--- a/src/client/views/collections/CollectionNoteTakingView.tsx
+++ b/src/client/views/collections/CollectionNoteTakingView.tsx
@@ -441,7 +441,7 @@ export class CollectionNoteTakingView extends CollectionSubView() {
         if ((e.ctrlKey || fieldProps.Document._createDocOnCR) && ['Enter'].includes(e.key)) {
             e.stopPropagation?.();
             const newDoc = Doc.MakeCopy(fieldProps.Document, true);
-            newDoc[DocData].text = undefined;
+            newDoc.$text = undefined;
             DocumentView.SetSelectOnLoad(newDoc);
             return this.addDocument?.(newDoc);
         }
diff --git a/src/client/views/collections/CollectionNoteTakingViewColumn.tsx b/src/client/views/collections/CollectionNoteTakingViewColumn.tsx
index 40b3f9ef2..df9b5a1eb 100644
--- a/src/client/views/collections/CollectionNoteTakingViewColumn.tsx
+++ b/src/client/views/collections/CollectionNoteTakingViewColumn.tsx
@@ -157,7 +157,7 @@ export class CollectionNoteTakingViewColumn extends ObservableReactComponent<CSV
     deleteColumn = () => {
         const colHdrData = Array.from(Cast(this._props.Document[this._props.fieldKey + '_columnHeaders'], listSpec(SchemaHeaderField), null));
         if (this._props.headingObject) {
-            //          this._props.docList.forEach(d => (d[DocData][this._props.pivotField] = undefined));
+            //          this._props.docList.forEach(d => (d['$'+this._props.pivotField] = undefined));
             colHdrData.splice(colHdrData.indexOf(this._props.headingObject), 1);
             this._props.resizeColumns(colHdrData);
         }
diff --git a/src/client/views/collections/CollectionStackedTimeline.tsx b/src/client/views/collections/CollectionStackedTimeline.tsx
index a7a9f2114..0836cce38 100644
--- a/src/client/views/collections/CollectionStackedTimeline.tsx
+++ b/src/client/views/collections/CollectionStackedTimeline.tsx
@@ -432,8 +432,8 @@ export class CollectionStackedTimeline extends CollectionSubView<CollectionStack
                 _isTimelineLabel: true,
                 layout_borderRounding: anchorEndTime === undefined ? '100%' : undefined,
             });
-        anchor[DocData][startTag] = anchorStartTime;
-        anchor[DocData][endTag] = anchorEndTime;
+        anchor['$' + startTag] = anchorStartTime;
+        anchor['$' + endTag] = anchorEndTime;
         if (addAsAnnotation) {
             if (Cast(dataDoc[fieldKey], listSpec(Doc), null)) {
                 Cast(dataDoc[fieldKey], listSpec(Doc), []).push(anchor);
@@ -804,9 +804,7 @@ class StackedTimelineAnchor extends ObservableReactComponent<StackedTimelineAnch
     };
 
     resetTitle = () => {
-        this._props.mark[DocData].title = ComputedField.MakeFunction(
-            `["${this._props.endTag}"] ? "#" + formatToTime(this["${this._props.startTag}"]) + "-" + formatToTime(this["${this._props.endTag}"]) : "#" + formatToTime(this["${this._props.startTag}"]`
-        );
+        this._props.mark.$title = ComputedField.MakeFunction(`["${this._props.endTag}"] ? "#" + formatToTime(this["${this._props.startTag}"]) + "-" + formatToTime(this["${this._props.endTag}"]) : "#" + formatToTime(this["${this._props.startTag}"]`);
     };
     // context menu
     contextMenuItems = () => {
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index 392d85af3..9972fe03d 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -5,7 +5,6 @@ import { observer } from 'mobx-react';
 import * as React from 'react';
 import { ClientUtils, DivHeight, returnNone, returnZero, setupMoveUpEvents, smoothScroll } from '../../../ClientUtils';
 import { Doc, Opt } from '../../../fields/Doc';
-import { DocData } from '../../../fields/DocSymbols';
 import { Id } from '../../../fields/FieldSymbols';
 import { List } from '../../../fields/List';
 import { listSpec } from '../../../fields/Schema';
@@ -316,11 +315,11 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection
             const layoutFieldKey = StrCast(fieldProps.fieldKey);
             const newDoc = Doc.MakeCopy(fieldProps.Document, true);
             const dataField = fieldProps.Document[Doc.LayoutFieldKey(newDoc)];
-            newDoc[DocData][Doc.LayoutFieldKey(newDoc)] = dataField === undefined || Cast(dataField, listSpec(Doc), null)?.length !== undefined ? new List<Doc>([]) : undefined;
+            newDoc['$' + Doc.LayoutFieldKey(newDoc)] = dataField === undefined || Cast(dataField, listSpec(Doc), null)?.length !== undefined ? new List<Doc>([]) : undefined;
             if (layoutFieldKey !== 'layout' && fieldProps.Document[layoutFieldKey] instanceof Doc) {
                 newDoc[layoutFieldKey] = fieldProps.Document[layoutFieldKey];
             }
-            newDoc[DocData].text = undefined;
+            newDoc.$text = undefined;
             DocumentView.SetSelectOnLoad(newDoc);
             return this.addDocument?.(newDoc);
         }
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index 655894e40..29caead5b 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -9,7 +9,7 @@ import { Id } from '../../../fields/FieldSymbols';
 import { List } from '../../../fields/List';
 import { listSpec } from '../../../fields/Schema';
 import { ScriptField } from '../../../fields/ScriptField';
-import { BoolCast, Cast, DateCast, NumCast, ScriptCast, StrCast, toList } from '../../../fields/Types';
+import { BoolCast, Cast, DateCast, DocCast, NumCast, ScriptCast, StrCast, toList } from '../../../fields/Types';
 import { WebField } from '../../../fields/URLField';
 import { GetEffectiveAcl, TraceMobx } from '../../../fields/util';
 import { GestureUtils } from '../../../pen-gestures/GestureUtils';
@@ -85,6 +85,9 @@ export function CollectionSubView<X>() {
         constructor(props: X & SubCollectionViewProps) {
             super(props);
             makeObservable(this);
+            console.log(`propsTitle: ${this._props.Document.title} DocTitle: ${this.Document.title} LayoutTitle:${this.layoutDoc.title} DataTitle:${this.dataDoc.title}`);
+            console.log(`tempTitle: ${this._props.TemplateDataDocument?.title} LayouTResolve: ${DocCast(this.layoutDoc.resolvedDataDoc)?.title} propDocResolve: ${DocCast(this._props.Document.resolvedDataDoc)?.title}`);
+            console.log('Children:', this.childDocs, this.childLayoutPairs);
         }
 
         @observable _focusFilters: Opt<string[]> = undefined; // childFilters that are overridden when previewing a link to an anchor which has childFilters set on it
@@ -108,7 +111,12 @@ export function CollectionSubView<X>() {
         }
 
         get dataDoc() {
-            return this._props.TemplateDataDocument instanceof Doc && this.Document.isTemplateForField ? Doc.GetProto(this._props.TemplateDataDocument) : this.Document.resolvedDataDoc ? this.Document : this.Document[DocData]; // if the layout document has a resolvedDataDoc, then we don't want to get its parent which would be the unexpanded template
+            console.log(this._props.Document.title + ' isTemplate: ' + this.layoutDoc.isTemplateForField);
+            return this._props.TemplateDataDocument instanceof Doc && this.layoutDoc.isTemplateForField //
+                ? this._props.TemplateDataDocument[DocData]
+                : this.layoutDoc.resolvedDataDoc
+                  ? this._props.Document
+                  : this.Document[DocData]; // if the layout document has a resolvedDataDoc, then we don't want to get its parent which would be the unexpanded template
         }
 
         get childContainerViewPath() {
diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
index cc56a8ff9..2d2c0fce5 100644
--- a/src/client/views/collections/TabDocView.tsx
+++ b/src/client/views/collections/TabDocView.tsx
@@ -347,7 +347,7 @@ export class TabDocView extends ObservableReactComponent<TabDocViewProps> {
                 undoable(() => {
                     const target = e.currentTarget as unknown as { value: string };
                     titleEle.size = target?.value.length + 3;
-                    doc[DocData].title = target?.value ?? '';
+                    doc.$title = target?.value ?? '';
                 }, 'edit tab title')();
             };
 
diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx
index 6208905fe..d6a19e88e 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -372,9 +372,8 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
             _width: 1000,
             _height: 10,
         });
-        const bulletData = bullet[DocData];
-        bulletData.title = ComputedField.MakeFunction('this.text?.Text');
-        bulletData.data = new List<Doc>([]);
+        bullet.$title = ComputedField.MakeFunction('this.text?.Text');
+        bullet.$data = new List<Doc>([]);
         DocumentView.addViewRenderedCb(bullet, dv => dv.ComponentView?.setFocus?.());
 
         return bullet;
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoUI.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoUI.tsx
index 8b9a3e0ec..35c6d30fe 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoUI.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoUI.tsx
@@ -1,16 +1,15 @@
 import { makeObservable, observable, runInAction } from 'mobx';
 import { observer } from 'mobx-react';
 import * as React from 'react';
-import { Doc, DocListCast, FieldType, FieldResult } from '../../../../fields/Doc';
+import { Doc, DocListCast, FieldResult, FieldType } from '../../../../fields/Doc';
 import { InkTool } from '../../../../fields/InkField';
 import { StrCast } from '../../../../fields/Types';
 import { ObservableReactComponent } from '../../ObservableReactComponent';
 import { DocButtonState, DocumentLinksButton } from '../../nodes/DocumentLinksButton';
 import { TopBar } from '../../topbar/TopBar';
 import { CollectionFreeFormInfoState, InfoState, StateEntryFunc, infoState } from './CollectionFreeFormInfoState';
-import './CollectionFreeFormView.scss';
-import { DocData } from '../../../../fields/DocSymbols';
 import { CollectionFreeFormView } from './CollectionFreeFormView';
+import './CollectionFreeFormView.scss';
 
 export interface CollectionFreeFormInfoUIProps {
     Document: Doc;
@@ -41,7 +40,7 @@ export class CollectionFreeFormInfoUI extends ObservableReactComponent<Collectio
     set currState(val) { runInAction(() => {this._currState = val;}); } // prettier-ignore
 
     componentWillUnmount(): void {
-        this._props.Document[DocData].backgroundColor = this._originalbackground;
+        this._props.Document.$backgroundColor = this._originalbackground;
     }
 
     setCurrState = (state: infoState) => {
@@ -52,9 +51,9 @@ export class CollectionFreeFormInfoUI extends ObservableReactComponent<Collectio
     };
 
     setupStates = () => {
-        this._originalbackground = StrCast(this._props.Document[DocData].backgroundColor);
+        this._originalbackground = StrCast(this._props.Document.$backgroundColor);
         //  state entry functions
-        // const setBackground = (colour: string) => () => {this._props.Document[DocData].backgroundColor = colour;} // prettier-ignore
+        // const setBackground = (colour: string) => () => {this._props.Document.$backgroundColor = colour;} // prettier-ignore
         // const setOpacity = (opacity: number) => () => {this._props.LayoutDoc.opacity = opacity;} // prettier-ignore
         //  arc transition trigger conditions
         const firstDoc = () => (this._props.childDocs().length ? this._props.childDocs()[0] : undefined);
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 89aa53c35..6030e146c 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -561,7 +561,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
                 const { points } = ge;
                 const B = this.screenToFreeformContentsXf.transformBounds(ge.bounds.left, ge.bounds.top, ge.bounds.width, ge.bounds.height);
                 const inkDoc = this.createInkDoc(points, B);
-                if (Doc.ActiveInk === InkInkTool.Highlight) inkDoc[DocData].backgroundColor = 'transparent';
+                if (Doc.ActiveInk === InkInkTool.Highlight) inkDoc.$backgroundColor = 'transparent';
                 if (Doc.ActiveInk === InkInkTool.Write) {
                     this.unprocessedDocs.push(inkDoc);
                     CollectionFreeFormView.collectionsWithUnprocessedInk.add(this);
@@ -639,7 +639,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
                         const B = this.screenToFreeformContentsXf.transformBounds(bounds.left, bounds.top, bounds.width, bounds.height);
                         const inkDoc = this.createInkDoc(points, B);
                         ['color', 'fillColor', 'stroke_width', 'stroke_dash', 'stroke_bezier'].forEach(field => {
-                            inkDoc[DocData][field] = stroke.dataDoc[field];
+                            inkDoc['$' + field] = stroke.dataDoc[field];
                         });
                         this.addDocument(inkDoc);
                     });
@@ -1260,15 +1260,14 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
      * Adds the created drawing to the freeform canvas and sets the metadata.
      */
     addDrawing = (doc: Doc, opts: DrawingOptions, gptRes: string, x?: number, y?: number) => {
-        const docData = doc[DocData];
-        docData.title = opts.text;
-        docData._width = opts.size;
-        docData.ai_drawing_input = opts.text;
-        docData.ai_drawing_complexity = opts.complexity;
-        docData.ai_drawing_colored = opts.autoColor;
-        docData.ai_drawing_size = opts.size;
-        docData.ai_drawing_data = gptRes;
-        docData.ai = 'gpt';
+        doc.$title = opts.text;
+        doc.$width = opts.size;
+        doc.$ai_drawing_input = opts.text;
+        doc.$ai_drawing_complexity = opts.complexity;
+        doc.$ai_drawing_colored = opts.autoColor;
+        doc.$ai_drawing_size = opts.size;
+        doc.$ai_drawing_data = gptRes;
+        doc.$ai = 'gpt';
         this._drawingContainer = doc;
         if (x !== undefined && y !== undefined) {
             [doc.x, doc.y] = this.screenToFreeformContentsXf.transformPoint(x, y);
@@ -1493,7 +1492,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
     createTextDocCopy = undoable((fieldProps: FieldViewProps, below: boolean) => {
         const textDoc = DocCast(fieldProps.Document.rootDocument, fieldProps.Document);
         const newDoc = Doc.MakeCopy(textDoc, true);
-        newDoc[DocData][Doc.LayoutFieldKey(newDoc, fieldProps.LayoutTemplateString)] = undefined; // the copy should not copy the text contents of it source, just the render style
+        newDoc['$' + Doc.LayoutFieldKey(newDoc, fieldProps.LayoutTemplateString)] = undefined; // the copy should not copy the text contents of it source, just the render style
         newDoc.x = NumCast(textDoc.x) + (below ? 0 : NumCast(textDoc._width) + 10);
         newDoc.y = NumCast(textDoc.y) + (below ? NumCast(textDoc._height) + 10 : 0);
         DocumentView.SetSelectOnLoad(newDoc);
@@ -1686,7 +1685,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
      * since rendering a large collection of documents can be slow, at startup, docs are rendered in batches.
      * each doc's render() method will call the cutoff provider which will let the doc know if it should render itself yet, or wait
      */
-    renderCutoffProvider = computedFn((doc: Doc) => (this.Document.isTemplateDoc || this.Document.isTemplateForField ? false : !this._renderCutoffData.get(doc[Id] + '')));
+    renderCutoffProvider = computedFn((doc: Doc) => (this._props.Document.isTemplateDoc || this._props.Document.isTemplateForField ? false : !this._renderCutoffData.get(doc[Id] + '')));
 
     doEngineLayout(
         poolData: Map<string, PoolData>,
diff --git a/src/client/views/collections/collectionFreeForm/FaceCollectionBox.tsx b/src/client/views/collections/collectionFreeForm/FaceCollectionBox.tsx
index b9f8b13a7..b40189d76 100644
--- a/src/client/views/collections/collectionFreeForm/FaceCollectionBox.tsx
+++ b/src/client/views/collections/collectionFreeForm/FaceCollectionBox.tsx
@@ -108,7 +108,7 @@ export class UniqueFaceBox extends ViewBoxBaseComponent<FieldViewProps>() {
                     if (faceAnno) {
                         faceAnno.face && FaceRecognitionHandler.UniqueFaceRemoveFaceImage(faceAnno, DocCast(faceAnno.face));
                         FaceRecognitionHandler.UniqueFaceAddFaceImage(faceAnno, this.Document);
-                        faceAnno[DocData].face = this.Document[DocData];
+                        faceAnno.$face = this.Document[DocData];
                     }
                 }
             });
@@ -118,7 +118,7 @@ export class UniqueFaceBox extends ViewBoxBaseComponent<FieldViewProps>() {
                 const imgDoc = faceAnno;
                 faceAnno.face && FaceRecognitionHandler.UniqueFaceRemoveFaceImage(imgDoc, DocCast(faceAnno.face));
                 FaceRecognitionHandler.UniqueFaceAddFaceImage(faceAnno, this.Document);
-                faceAnno[DocData].face = this.Document[DocData];
+                faceAnno.$face = this.Document[DocData];
             });
         e.stopPropagation();
         return true;
diff --git a/src/client/views/collections/collectionFreeForm/ImageLabelBox.tsx b/src/client/views/collections/collectionFreeForm/ImageLabelBox.tsx
index a3d9641da..c983d7c26 100644
--- a/src/client/views/collections/collectionFreeForm/ImageLabelBox.tsx
+++ b/src/client/views/collections/collectionFreeForm/ImageLabelBox.tsx
@@ -9,7 +9,6 @@ import React from 'react';
 import { imageUrlToBase64 } from '../../../../ClientUtils';
 import { Utils, numberRange } from '../../../../Utils';
 import { Doc, NumListCast, Opt } from '../../../../fields/Doc';
-import { DocData } from '../../../../fields/DocSymbols';
 import { List } from '../../../../fields/List';
 import { ImageCast } from '../../../../fields/Types';
 import { gptGetEmbedding, gptImageLabel } from '../../../apis/gpt/GPT';
@@ -165,7 +164,7 @@ export class ImageLabelBox extends ViewBoxBaseComponent<FieldViewProps>() {
         // Converts the images into a Base64 format, afterwhich the information is sent to GPT to label them.
 
         const imageInfos = this._selectedImages.map(async doc => {
-            if (!doc[DocData].tags_chat) {
+            if (!doc.$tags_chat) {
                 const [name, type] = ImageCast(doc[Doc.LayoutFieldKey(doc)]).url.href.split('.');
                 return imageUrlToBase64(`${name}_o.${type}`).then(hrefBase64 =>
                 !hrefBase64 ? undefined : 
@@ -176,7 +175,7 @@ export class ImageLabelBox extends ViewBoxBaseComponent<FieldViewProps>() {
 
         (await Promise.all(imageInfos)).forEach(imageInfo => {
             if (imageInfo) {
-                imageInfo.doc[DocData].tags_chat = (imageInfo.doc[DocData].tags_chat as List<string>) ?? new List<string>();
+                imageInfo.doc.$tags_chat = (imageInfo.doc.$tags_chat as List<string>) ?? new List<string>();
 
                 const labels = imageInfo.labels.split('\n');
                 labels.forEach(label => {
@@ -186,7 +185,7 @@ export class ImageLabelBox extends ViewBoxBaseComponent<FieldViewProps>() {
                             .replace(/^\d+\.\s*|-|f\*/, '')
                             .replace(/^#/, '')
                             .trim();
-                    (imageInfo.doc[DocData].tags_chat as List<string>).push(hashLabel);
+                    (imageInfo.doc.$tags_chat as List<string>).push(hashLabel);
                 });
             }
         });
@@ -201,10 +200,10 @@ export class ImageLabelBox extends ViewBoxBaseComponent<FieldViewProps>() {
         this.startLoading();
 
         for (const doc of this._selectedImages) {
-            for (let index = 0; index < (doc[DocData].tags_chat as List<string>).length; index++) {
-                const label = (doc[DocData].tags_chat as List<string>)[index];
+            for (let index = 0; index < (doc.$tags_chat as List<string>).length; index++) {
+                const label = (doc.$tags_chat as List<string>)[index];
                 const embedding = await gptGetEmbedding(label);
-                doc[DocData][`tags_embedding_${index + 1}`] = new List<number>(embedding);
+                doc[`$tags_embedding_${index + 1}`] = new List<number>(embedding);
             }
         }
 
@@ -215,13 +214,13 @@ export class ImageLabelBox extends ViewBoxBaseComponent<FieldViewProps>() {
         // For each image, loop through the labels, and calculate similarity. Associate it with the
         // most similar one.
         this._selectedImages.forEach(doc => {
-            const embedLists = numberRange((doc[DocData].tags_chat as List<string>).length).map(n => Array.from(NumListCast(doc[DocData][`tags_embedding_${n + 1}`])));
+            const embedLists = numberRange((doc.$tags_chat as List<string>).length).map(n => Array.from(NumListCast(doc[`$tags_embedding_${n + 1}`])));
             const bestEmbedScore = (embedding: Opt<number[]>) => Math.max(...embedLists.map(l => (embedding && similarity(Array.from(embedding), l)!) || 0));
             const {label: mostSimilarLabelCollect} = 
                 this._labelGroups.map(label => ({ label, similarityScore: bestEmbedScore(labelToEmbedding.get(label)) }))
                            .reduce((prev, cur) => cur.similarityScore < 0.3 || cur.similarityScore <= prev.similarityScore ? prev: cur,
                                    { label: '', similarityScore: 0, }); // prettier-ignore
-            doc[DocData].data_label = mostSimilarLabelCollect; // The label most similar to the image's contents.
+            doc.$data_label = mostSimilarLabelCollect; // The label most similar to the image's contents.
         });
 
         this.endLoading();
@@ -322,7 +321,7 @@ export class ImageLabelBox extends ViewBoxBaseComponent<FieldViewProps>() {
                                             await DocumentView.showDocument(doc, { willZoomCentered: true });
                                         }}></img>
                                     <div className="image-information-labels" onClick={() => this._props.addDocTab(doc, OpenWhere.addRightKeyvalue)}>
-                                        {(doc[DocData].tags_chat as List<string>).map(label => {
+                                        {(doc.$tags_chat as List<string>).map(label => {
                                             return (
                                                 <div key={Utils.GenerateGuid()} className="image-label" style={{ backgroundColor: SettingsManager.userVariantColor, borderColor: SettingsManager.userColor }}>
                                                     {label}
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index ad52db496..e3f4c6605 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -165,7 +165,7 @@ export class MarqueeView extends ObservableReactComponent<SubCollectionViewProps
                     error && console.log(error);
                     data &&
                         ClientUtils.convertDataUri(data, this._props.Document[Id] + '_icon_' + new Date().getTime()).then(returnedfilename => {
-                            this._props.Document[DocData].icon = new ImageField(returnedfilename);
+                            this._props.Document.$icon = new ImageField(returnedfilename);
                         });
                 })
             );
@@ -371,10 +371,9 @@ export class MarqueeView extends ObservableReactComponent<SubCollectionViewProps
         const newCollection = creator
             ? creator(selected, { title: 'nested stack' })
             : ((doc: Doc) => {
-                  const docData = doc[DocData];
-                  docData.data = new List<Doc>(selected);
-                  docData.isGroup = makeGroup;
-                  docData.title = makeGroup ? 'grouping' : 'nested freeform';
+                  doc.$data = new List<Doc>(selected);
+                  doc.$isGroup = makeGroup;
+                  doc.$title = makeGroup ? 'grouping' : 'nested freeform';
                   doc._freeform_panX = doc._freeform_panY = 0;
                   return doc;
               })(Doc.MakeCopy(Doc.UserDoc().emptyCollection as Doc, true));
@@ -462,9 +461,9 @@ export class MarqueeView extends ObservableReactComponent<SubCollectionViewProps
         const newColDim = 900;
         for (const label of labelGroups) {
             const newCollection = MarqueeView.getCollection([], undefined, false, this.Bounds);
-            newCollection[DocData].title = label + ' Collection';
-            newCollection._x = this.Bounds.left + x_offset;
-            newCollection._y = this.Bounds.top + y_offset;
+            newCollection.$title = label + ' Collection';
+            newCollection.x = this.Bounds.left + x_offset;
+            newCollection.y = this.Bounds.top + y_offset;
             newCollection._width = newColDim;
             newCollection._height = newColDim;
             newCollection._freeform_panX = this.Bounds.left + this.Bounds.width / 2;
@@ -481,8 +480,8 @@ export class MarqueeView extends ObservableReactComponent<SubCollectionViewProps
         }
 
         for (const doc of selectedImages) {
-            if (doc[DocData].data_label) {
-                Doc.AddDocToList(labelToCollection.get(doc[DocData].data_label as string)!, undefined, doc);
+            if (doc.$data_label) {
+                Doc.AddDocToList(labelToCollection.get(doc.$data_label as string)!, undefined, doc);
                 this._props.removeDocument?.(doc);
             }
         }
diff --git a/src/client/views/global/globalScripts.ts b/src/client/views/global/globalScripts.ts
index 835c28daa..79d0ee88f 100644
--- a/src/client/views/global/globalScripts.ts
+++ b/src/client/views/global/globalScripts.ts
@@ -1,15 +1,12 @@
 /* eslint-disable @typescript-eslint/no-unused-vars */
 import { Colors } from '@dash/components';
 import { runInAction } from 'mobx';
-import { Doc, DocListCast, Opt, StrListCast } from '../../../fields/Doc';
-import { DocData } from '../../../fields/DocSymbols';
+import { Doc, Opt, StrListCast } from '../../../fields/Doc';
 import { InkEraserTool, InkInkTool, InkProperty, InkTool } from '../../../fields/InkField';
-import { List } from '../../../fields/List';
 import { BoolCast, Cast, NumCast, StrCast } from '../../../fields/Types';
 import { WebField } from '../../../fields/URLField';
 import { Gestures } from '../../../pen-gestures/GestureTypes';
-import { CollectionViewType, DocumentType } from '../../documents/DocumentTypes';
-import { Docs } from '../../documents/Documents';
+import { DocumentType } from '../../documents/DocumentTypes';
 import { LinkManager } from '../../util/LinkManager';
 import { ScriptingGlobals } from '../../util/ScriptingGlobals';
 import { SnappingManager } from '../../util/SnappingManager';
@@ -17,30 +14,30 @@ import { UndoManager, undoable } from '../../util/UndoManager';
 import { GestureOverlay } from '../GestureOverlay';
 import { InkTranscription } from '../InkTranscription';
 import { PropertiesView } from '../PropertiesView';
+import { docSortings } from '../collections/CollectionSubView';
 import { CollectionFreeFormView } from '../collections/collectionFreeForm';
 import { CollectionFreeFormDocumentView } from '../nodes/CollectionFreeFormDocumentView';
 import {
     ActiveEraserWidth,
-    ActiveInkFillColor,
-    ActiveInkColor,
     ActiveHideTextLabels,
+    ActiveInkColor,
+    ActiveInkFillColor,
     ActiveInkWidth,
     ActiveIsInkMask,
     DocumentView,
-    SetActiveInkFillColor,
     SetActiveInkColor,
-    SetactiveHideTextLabels,
+    SetActiveInkFillColor,
     SetActiveInkWidth,
     SetActiveIsInkMask,
     SetEraserWidth,
+    SetactiveHideTextLabels,
 } from '../nodes/DocumentView';
 import { ImageBox } from '../nodes/ImageBox';
+import { OpenWhere } from '../nodes/OpenWhere';
 import { VideoBox } from '../nodes/VideoBox';
 import { WebBox } from '../nodes/WebBox';
 import { RichTextMenu } from '../nodes/formattedText/RichTextMenu';
 import { GPTPopup, GPTPopupMode } from '../pdf/GPTPopup/GPTPopup';
-import { OpenWhere } from '../nodes/OpenWhere';
-import { docSortings } from '../collections/CollectionSubView';
 
 // eslint-disable-next-line prefer-arrow-callback
 ScriptingGlobals.add(function IsNoneSelected() {
@@ -101,10 +98,7 @@ ScriptingGlobals.add(function setBorderColor(color?: string, checkResult?: boole
             return (selected.lastElement() ?? Doc.UserDoc()).borderColor ?? defaultBorder();
         }
         if (!selected.length) setDefaultBorder(color ?? 'transparent');
-        else
-            selected.forEach(doc => {
-                doc[DocData].borderColor = color;
-            });
+        else selected.forEach(doc => (doc.$borderColor = color));
     }
     return '';
 });
@@ -114,7 +108,7 @@ ScriptingGlobals.add(function setBorderColor(color?: string, checkResult?: boole
 ScriptingGlobals.add(function setBackgroundColor(color?: string, checkResult?: boolean) {
     const selectedViews = DocumentView.Selected();
     const selectedDoc = selectedViews.lastElement()?.Document;
-    const defaultFill = selectedDoc?._layout_isSvg ? () => StrCast(selectedDoc[DocData].fillColor) : !Doc.ActiveTool || Doc.ActiveTool === InkTool.None ? () => StrCast(Doc.UserDoc().textBackgroundColor, 'transparent') : () => ActiveInkFillColor();
+    const defaultFill = selectedDoc?._layout_isSvg ? () => StrCast(selectedDoc.$fillColor) : !Doc.ActiveTool || Doc.ActiveTool === InkTool.None ? () => StrCast(Doc.UserDoc().textBackgroundColor, 'transparent') : () => ActiveInkFillColor();
     const setDefaultFill = !Doc.ActiveTool || Doc.ActiveTool === InkTool.None  ? (c: string) => { Doc.UserDoc().textBackgroundColor = c; }: SetActiveInkFillColor; // prettier-ignore
     if (Doc.ActiveTool !== InkTool.None && !selectedViews.lastElement()?.Document._layout_isSvg) {
         if (checkResult) return defaultFill();
@@ -149,10 +143,7 @@ ScriptingGlobals.add(function setBackgroundColor(color?: string, checkResult?: b
             return selected.lastElement()?._backgroundColor ?? defaultFill();
         }
         if (!selected.length) setDefaultFill(color ?? 'transparent');
-        else
-            selected.forEach(doc => {
-                doc[DocData][doc._layout_isSvg ? 'fillColor' : 'backgroundColor'] = color;
-            });
+        else selected.forEach(doc => (doc[doc._layout_isSvg ? '$fillColor' : '$backgroundColor'] = color));
     }
     return '';
 });
@@ -170,7 +161,7 @@ ScriptingGlobals.add(function setHeaderColor(color?: string, checkResult?: boole
     }
     if (DocumentView.Selected().length) {
         DocumentView.SelectedDocs().forEach(doc => {
-            doc[DocData].layout_headingColor = color === 'transparent' ? undefined : color;
+            doc.$layout_headingColor = color === 'transparent' ? undefined : color;
             doc.layout_showTitle = color === 'transparent' ? undefined : StrCast(doc.layout_showTitle, 'title');
         });
     } else {
@@ -470,23 +461,23 @@ ScriptingGlobals.add(function setInkProperty(option: InkProperty, value: string
     // prettier-ignore
     const map: Map<InkProperty, { checkResult: () => number|boolean|string|undefined; setInk: (doc: Doc) => void; setMode: () => void }> = new Map([
         [InkProperty.Mask, {
-            checkResult: () => ((selected?._layout_isSvg ? BoolCast(selected[DocData].stroke_isInkMask) : ActiveIsInkMask())),
-            setInk: (doc: Doc) => { doc[DocData].stroke_isInkMask = !doc.stroke_isInkMask; },
+            checkResult: () => ((selected?._layout_isSvg ? BoolCast(selected.$stroke_isInkMask) : ActiveIsInkMask())),
+            setInk: (doc: Doc) => { doc.$stroke_isInkMask = !doc.stroke_isInkMask; },
             setMode: () => SetActiveIsInkMask(value ? true : false)
         }],
         [InkProperty.Labels, {
-            checkResult: () => ((selected?._layout_isSvg ? BoolCast(selected[DocData].stroke_showLabel) : !ActiveHideTextLabels())),
-            setInk: (doc: Doc) => { doc[DocData].stroke_showLabel = value; },
+            checkResult: () => ((selected?._layout_isSvg ? BoolCast(selected.$stroke_showLabel) : !ActiveHideTextLabels())),
+            setInk: (doc: Doc) => { doc.$stroke_showLabel = value; },
             setMode: () => SetactiveHideTextLabels(value? false : true),
         }],
         [ InkProperty.StrokeWidth, {
-            checkResult: () => (selected?._layout_isSvg ? NumCast(selected[DocData].stroke_width, 1) : ActiveInkWidth()),
-            setInk: (doc: Doc) => { doc[DocData].stroke_width = NumCast(value); },
+            checkResult: () => (selected?._layout_isSvg ? NumCast(selected.$stroke_width, 1) : ActiveInkWidth()),
+            setInk: (doc: Doc) => { doc.$stroke_width = NumCast(value); },
             setMode: () => SetActiveInkWidth(value.toString()),
         }],
         [InkProperty.StrokeColor, {
-            checkResult: () => (selected?._layout_isSvg? StrCast(selected[DocData].color) : ActiveInkColor()),
-            setInk: (doc: Doc) => { doc[DocData].color = String(value); },
+            checkResult: () => (selected?._layout_isSvg? StrCast(selected.$color) : ActiveInkColor()),
+            setInk: (doc: Doc) => { doc.$color = String(value); },
             setMode: () => SetActiveInkColor(StrCast(value))
         }],
         [ InkProperty.EraserWidth, {
diff --git a/src/client/views/nodes/AudioBox.tsx b/src/client/views/nodes/AudioBox.tsx
index 25e76e2a6..e0d59cc9d 100644
--- a/src/client/views/nodes/AudioBox.tsx
+++ b/src/client/views/nodes/AudioBox.tsx
@@ -296,7 +296,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
                 'Content-Type': 'application/json',
             },
         });
-        this.Document[DocData].phoneticTranscription = response.data['transcription'];
+        this.Document.$phoneticTranscription = response.data['transcription'];
     };
 
     // context menu
diff --git a/src/client/views/nodes/ComparisonBox.tsx b/src/client/views/nodes/ComparisonBox.tsx
index c0c6db4d3..992fbba66 100644
--- a/src/client/views/nodes/ComparisonBox.tsx
+++ b/src/client/views/nodes/ComparisonBox.tsx
@@ -80,8 +80,8 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
             const front = Docs.Create.CenteredTextCreator('question', question, {}, img);
             const back = Docs.Create.CenteredTextCreator('answer', answer, {});
             if (useDoc) {
-                useDoc[DocData][frontKey] = front;
-                useDoc[DocData][backKey] = back;
+                useDoc['$' + frontKey] = front;
+                useDoc['$' + backKey] = back;
                 return useDoc;
             }
             return Docs.Create.FlashcardDocument(title, front, back, { _width: 300, _height: 300 });
@@ -475,7 +475,7 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
         axios
             .post(
                 'http://localhost:105/recognize/', //
-                { file: DocCast(this.Document.audio)[DocData].url },
+                { file: DocCast(this.Document.audio).$url },
                 { headers: { 'Content-Type': 'application/json' } }
             )
             .then(response => {
@@ -520,7 +520,7 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
                   action(resp => {
                       switch (resp && callType) {
                           case GPTCallType.CHATCARD:
-                              DocCast(this.dataDoc[this.backKey])[DocData].text = resp;
+                              DocCast(this.dataDoc[this.backKey]).$text = resp;
                               break;
                           case GPTCallType.QUIZDOC:
                               this._renderSide = this.backKey;
@@ -618,7 +618,7 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
             const hrefBase64 = await imageUrlToBase64(u);
             const response = await gptImageLabel(hrefBase64, 'Answer the following question as a short flashcard response. Do not include a label.' + (this.dataDoc.text as RichTextField)?.Text);
 
-            DocCast(this.dataDoc[this.backKey])[DocData].text = response;
+            DocCast(this.dataDoc[this.backKey]).$text = response;
         } catch (error) {
             console.log('Error', error);
         }
diff --git a/src/client/views/nodes/DataVizBox/components/TableBox.tsx b/src/client/views/nodes/DataVizBox/components/TableBox.tsx
index 7ef4bca6b..b31a0ec1e 100644
--- a/src/client/views/nodes/DataVizBox/components/TableBox.tsx
+++ b/src/client/views/nodes/DataVizBox/components/TableBox.tsx
@@ -160,8 +160,8 @@ export class TableBox extends ObservableReactComponent<TableBoxProps> {
                     DragManager.StartAnchorAnnoDrag(moveEv.target instanceof HTMLElement ? [moveEv.target] : [], new DragManager.AnchorAnnoDragData(this._props.docView()!, sourceAnchorCreator, targetCreator), downX, downY, {
                         dragComplete: completeEv => {
                             if (!completeEv.aborted && completeEv.annoDragData && completeEv.annoDragData.linkSourceDoc && completeEv.annoDragData.dropDocument && completeEv.linkDocument) {
-                                completeEv.linkDocument[DocData].link_matchEmbeddings = true;
-                                completeEv.linkDocument[DocData].stroke_startMarker = true;
+                                completeEv.linkDocument.$link_matchEmbeddings = true;
+                                completeEv.linkDocument.$stroke_startMarker = true;
                                 this._props.docView?.()?._props.addDocument?.(completeEv.linkDocument);
                             }
                         },
diff --git a/src/client/views/nodes/DiagramBox.tsx b/src/client/views/nodes/DiagramBox.tsx
index a49c69be3..3b666bad5 100644
--- a/src/client/views/nodes/DiagramBox.tsx
+++ b/src/client/views/nodes/DiagramBox.tsx
@@ -3,7 +3,6 @@ import { action, computed, makeObservable, observable, reaction } from 'mobx';
 import { observer } from 'mobx-react';
 import * as React from 'react';
 import { Doc, DocListCast } from '../../../fields/Doc';
-import { DocData } from '../../../fields/DocSymbols';
 import { RichTextField } from '../../../fields/RichTextField';
 import { Cast, DocCast, NumCast, RTFCast, StrCast } from '../../../fields/Types';
 import { Gestures } from '../../../pen-gestures/GestureTypes';
@@ -46,7 +45,7 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
     @observable _errorMessage = '';
 
     @computed get mermaidcode() {
-        return StrCast(this.Document[DocData].text, RTFCast(this.Document[DocData].text)?.Text);
+        return StrCast(this.Document.$text, RTFCast(this.Document.$text)?.Text);
     }
 
     componentDidMount() {
@@ -89,7 +88,7 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
     };
 
     setMermaidCode = undoable((res: string) => {
-        this.Document[DocData].text = new RichTextField(
+        this.Document.$text = new RichTextField(
             JSON.stringify({
                 doc: {
                     type: 'doc',
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 46bd076d4..e9353b001 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -9,7 +9,7 @@ import { Fade, JackInTheBox } from 'react-awesome-reveal';
 import { ClientUtils, DivWidth, isTargetChildOf as isParentOf, lightOrDark, returnFalse, returnVal, simMouseEvent, simulateMouseClick } from '../../../ClientUtils';
 import { Utils, emptyFunction } from '../../../Utils';
 import { Doc, DocListCast, Field, FieldType, Opt, StrListCast } from '../../../fields/Doc';
-import { AclAdmin, AclEdit, AclPrivate, Animation, AudioPlay, DocData, DocViews } from '../../../fields/DocSymbols';
+import { AclAdmin, AclEdit, AclPrivate, Animation, AudioPlay, DocViews } from '../../../fields/DocSymbols';
 import { Id } from '../../../fields/FieldSymbols';
 import { InkTool } from '../../../fields/InkField';
 import { List } from '../../../fields/List';
@@ -40,6 +40,7 @@ import { FieldsDropdown } from '../FieldsDropdown';
 import { ObserverJsxParser } from '../ObservableReactComponent';
 import { PinProps } from '../PinFuncs';
 import { StyleProp } from '../StyleProp';
+import { TagsView } from '../TagsView';
 import { ViewBoxInterface } from '../ViewBoxInterface';
 import { GroupActive } from './CollectionFreeFormDocumentView';
 import { DocumentContentsView } from './DocumentContentsView';
@@ -52,7 +53,6 @@ import { FormattedTextBox } from './formattedText/FormattedTextBox';
 import { PresEffect, PresEffectDirection } from './trails/PresEnums';
 import SpringAnimation from './trails/SlideEffect';
 import { SpringType, springMappings } from './trails/SpringUtils';
-import { TagsView } from '../TagsView';
 
 export interface DocumentViewProps extends FieldViewSharedProps {
     hideDecorations?: boolean; // whether to suppress all DocumentDecorations when doc is selected
@@ -426,7 +426,7 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
 
     noOnClick = undoable(() => {
         this.Document.ignoreClick = false;
-        this.Document.onClick = this.Document[DocData].onClick = undefined;
+        this.Document.onClick = this.Document.$onClick = undefined;
     }, 'default on click');
 
     deleteClicked = undoable(() => this._props.removeDocument?.(this.Document), 'delete doc');
@@ -758,7 +758,7 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
                     }}>
                     <DocumentContentsView
                         {...this._props}
-                        layoutFieldKey={StrCast(this.Document.layout_fieldKey, 'layout')}
+                        layoutFieldKey={StrCast(this._props.Document.layout_fieldKey, 'layout')}
                         pointerEvents={this.contentPointerEvents}
                         setContentViewBox={this.setContentView}
                         childFilters={this.childFilters}
@@ -1706,7 +1706,7 @@ ScriptingGlobals.add(function toggleDetail(dv: DocumentView, detailLayoutKeySuff
 
 // eslint-disable-next-line prefer-arrow-callback
 ScriptingGlobals.add(function updateLinkCollection(linkCollection: Doc, linkSource: Doc) {
-    const collectedLinks = DocListCast(linkCollection[DocData].data);
+    const collectedLinks = DocListCast(linkCollection.$data);
     let wid = NumCast(linkSource._width);
     let embedding: Doc | undefined;
     const links = Doc.Links(linkSource);
@@ -1729,7 +1729,7 @@ ScriptingGlobals.add(function updateLinkCollection(linkCollection: Doc, linkSour
 ScriptingGlobals.add(function updateTagsCollection(collection: Doc) {
     const tag = StrCast(collection.title).split('-->')[1];
     const matchedTags = Array.from(SearchUtil.SearchCollection(Doc.MyFilesystem, tag, false, ['tags']).keys());
-    const collectionDocs = DocListCast(collection[DocData].data).concat(collection);
+    const collectionDocs = DocListCast(collection.$data).concat(collection);
     let wid = 100;
     let created = false;
     const matchedDocs = matchedTags
@@ -1749,6 +1749,6 @@ ScriptingGlobals.add(function updateTagsCollection(collection: Doc) {
             return aset;
         }, new Set<Doc>());
 
-    created && (collection[DocData].data = new List<Doc>(Array.from(matchedDocs)));
+    created && (collection.$data = new List<Doc>(Array.from(matchedDocs)));
     return true;
 });
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx
index 5b06e9fc5..5d9718760 100644
--- a/src/client/views/nodes/ImageBox.tsx
+++ b/src/client/views/nodes/ImageBox.tsx
@@ -284,10 +284,9 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
     crop = (region: Doc | undefined, addCrop?: boolean) => {
         if (!region) return undefined;
         const cropping = Doc.MakeCopy(region, true);
-        const regionData = region[DocData];
-        regionData.lockedPosition = true;
-        regionData.title = 'region:' + this.Document.title;
-        regionData.followLinkToggle = true;
+        region.$lockedPosition = true;
+        region.$title = 'region:' + this.Document.title;
+        region.$followLinkToggle = true;
         this.addDocument(region);
         const anchx = NumCast(cropping.x);
         const anchy = NumCast(cropping.y);
@@ -300,24 +299,23 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
         cropping._width = anchw * (this._props.NativeDimScaling?.() || 1);
         cropping._height = anchh * (this._props.NativeDimScaling?.() || 1);
         cropping.onClick = undefined;
-        const croppingProto = cropping[DocData];
-        croppingProto.annotationOn = undefined;
-        croppingProto.isDataDoc = true;
-        croppingProto.backgroundColor = undefined;
-        croppingProto.proto = Cast(this.Document.proto, Doc, null)?.proto; // set proto of cropping's data doc to be IMAGE_PROTO
-        croppingProto.type = DocumentType.IMG;
-        croppingProto.layout = ImageBox.LayoutString('data');
-        croppingProto.data = ObjectField.MakeCopy(this.dataDoc[this.fieldKey] as ObjectField);
-        croppingProto.data_nativeWidth = anchw;
-        croppingProto.data_nativeHeight = anchh;
-        croppingProto.freeform_scale = viewScale;
-        croppingProto.freeform_panX = anchx / viewScale;
-        croppingProto.freeform_panY = anchy / viewScale;
-        croppingProto.freeform_scale_min = viewScale;
-        croppingProto.freeform_panX_min = anchx / viewScale;
-        croppingProto.freeform_panX_max = anchw / viewScale;
-        croppingProto.freeform_panY_min = anchy / viewScale;
-        croppingProto.freeform_panY_max = anchh / viewScale;
+        cropping.$annotationOn = undefined;
+        cropping.$isDataDoc = true;
+        cropping.$backgroundColor = undefined;
+        cropping.$proto = Cast(this.Document.proto, Doc, null)?.proto; // set proto of cropping's data doc to be IMAGE_PROTO
+        cropping.$type = DocumentType.IMG;
+        cropping.$layout = ImageBox.LayoutString('data');
+        cropping.$data = ObjectField.MakeCopy(this.dataDoc[this.fieldKey] as ObjectField);
+        cropping.$data_nativeWidth = anchw;
+        cropping.$data_nativeHeight = anchh;
+        cropping.$freeform_scale = viewScale;
+        cropping.$reeform_panX = anchx / viewScale;
+        cropping.$freeform_panY = anchy / viewScale;
+        cropping.$freeform_scale_min = viewScale;
+        cropping.$freeform_panX_min = anchx / viewScale;
+        cropping.$freeform_panX_max = anchw / viewScale;
+        cropping.$freeform_panY_min = anchy / viewScale;
+        cropping.$freeform_panY_max = anchh / viewScale;
         if (addCrop) {
             DocUtils.MakeLink(region, cropping, { link_relationship: 'cropped image' });
             cropping.x = NumCast(this.Document.x) + NumCast(this.layoutDoc._width);
diff --git a/src/client/views/nodes/KeyValueBox.tsx b/src/client/views/nodes/KeyValueBox.tsx
index 9795febbe..32c9efbd9 100644
--- a/src/client/views/nodes/KeyValueBox.tsx
+++ b/src/client/views/nodes/KeyValueBox.tsx
@@ -105,7 +105,7 @@ export class KeyValueBox extends ViewBoxBaseComponent<FieldViewProps>() {
                     if (setResult) setResult?.(value);
                     else target[key] = field;
                 };
-                const res = script.run({ this: Doc.Layout(doc), _setCacheResult_ }, console.log);
+                const res = script.run({ this: doc, _setCacheResult_ }, console.log);
                 if (!res.success) {
                     if (key) target[key] = script.originalScript;
                     return false;
diff --git a/src/client/views/nodes/LinkBox.tsx b/src/client/views/nodes/LinkBox.tsx
index d5dc256d9..8bf65b637 100644
--- a/src/client/views/nodes/LinkBox.tsx
+++ b/src/client/views/nodes/LinkBox.tsx
@@ -252,7 +252,7 @@ export class LinkBox extends ViewBoxBaseComponent<FieldViewProps>() {
                                     fontSize={fontSize}
                                     GetValue={() => linkDesc}
                                     SetValue={action(val => {
-                                        this.Document[DocData].link_description = val;
+                                        this.Document.$link_description = val;
                                         return true;
                                     })}
                                 />
@@ -262,8 +262,8 @@ export class LinkBox extends ViewBoxBaseComponent<FieldViewProps>() {
                                     background={color}
                                     color={fontColor || lightOrDark(DashColor(color).fade(0.5).toString())}
                                     type={Type.PRIM}
-                                    val={StrCast(this.Document[DocData].link_description)}
-                                    setVal={action(val => (this.Document[DocData].link_description = val))}
+                                    val={StrCast(this.Document.$link_description)}
+                                    setVal={action(val => (this.Document.$link_description = val))}
                                     fillWidth
                                 /> */}
                             </div>
diff --git a/src/client/views/nodes/LinkDescriptionPopup.tsx b/src/client/views/nodes/LinkDescriptionPopup.tsx
index ff95f8547..6bec9c53d 100644
--- a/src/client/views/nodes/LinkDescriptionPopup.tsx
+++ b/src/client/views/nodes/LinkDescriptionPopup.tsx
@@ -1,7 +1,6 @@
 import { action, makeObservable, observable, reaction } from 'mobx';
 import { observer } from 'mobx-react';
 import * as React from 'react';
-import { DocData } from '../../../fields/DocSymbols';
 import { StrCast } from '../../../fields/Types';
 import { LinkManager } from '../../util/LinkManager';
 import './LinkDescriptionPopup.scss';
@@ -48,7 +47,7 @@ export class LinkDescriptionPopup extends React.Component<{}> {
     onDismiss = (add: boolean) => {
         this.display = false;
         if (add) {
-            LinkManager.Instance.currentLink && (LinkManager.Instance.currentLink[DocData].link_description = this.description);
+            LinkManager.Instance.currentLink && (LinkManager.Instance.currentLink.$link_description = this.description);
         }
         this.description = '';
     };
diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx
index 06b75e243..1f72206fc 100644
--- a/src/client/views/nodes/PDFBox.tsx
+++ b/src/client/views/nodes/PDFBox.tsx
@@ -129,15 +129,14 @@ export class PDFBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
         cropping._width = anchw;
         cropping._height = anchh;
         cropping.onClick = undefined;
-        const croppingProto = cropping[DocData];
-        croppingProto.annotationOn = undefined;
-        croppingProto.isDataDoc = true;
-        croppingProto.proto = Cast(this.Document.proto, Doc, null)?.proto; // set proto of cropping's data doc to be IMAGE_PROTO
-        croppingProto.type = DocumentType.IMG;
-        croppingProto.layout = ImageBox.LayoutString('data');
-        croppingProto.data = new ImageField(ClientUtils.CorsProxy('http://www.cs.brown.edu/~bcz/noImage.png'));
-        croppingProto.data_nativeWidth = anchw;
-        croppingProto.data_nativeHeight = anchh;
+        cropping.$annotationOn = undefined;
+        cropping.$isDataDoc = true;
+        cropping.$proto = Cast(this.Document.proto, Doc, null)?.proto; // set proto of cropping's data doc to be IMAGE_PROTO
+        cropping.$type = DocumentType.IMG;
+        cropping.$layout = ImageBox.LayoutString('data');
+        cropping.$data = new ImageField(ClientUtils.CorsProxy('http://www.cs.brown.edu/~bcz/noImage.png'));
+        cropping.$data_nativeWidth = anchw;
+        cropping.$data_nativeHeight = anchh;
         if (addCrop) {
             DocUtils.MakeLink(region, cropping, { link_relationship: 'cropped image' });
         }
diff --git a/src/client/views/nodes/RecordingBox/RecordingBox.tsx b/src/client/views/nodes/RecordingBox/RecordingBox.tsx
index 7ba313e92..53783e8a3 100644
--- a/src/client/views/nodes/RecordingBox/RecordingBox.tsx
+++ b/src/client/views/nodes/RecordingBox/RecordingBox.tsx
@@ -3,7 +3,6 @@ import { observer } from 'mobx-react';
 import * as React from 'react';
 import { DateField } from '../../../../fields/DateField';
 import { Doc, DocListCast } from '../../../../fields/Doc';
-import { DocData } from '../../../../fields/DocSymbols';
 import { Id } from '../../../../fields/FieldSymbols';
 import { List } from '../../../../fields/List';
 import { BoolCast, DocCast } from '../../../../fields/Types';
@@ -99,7 +98,7 @@ export class RecordingBox extends ViewBoxBaseComponent<FieldViewProps>() {
                   });
         screengrabber.overlayX = 70; // was -400
         screengrabber.overlayY = 590; // was 0
-        screengrabber[DocData][Doc.LayoutFieldKey(screengrabber) + '_trackScreen'] = true;
+        screengrabber['$' + Doc.LayoutFieldKey(screengrabber) + '_trackScreen'] = true;
         Doc.AddToMyOverlay(screengrabber); // just adds doc to overlay
         DocumentView.addViewRenderedCb(screengrabber, docView => {
             RecordingBox.screengrabber = docView.ComponentView as RecordingBox;
diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx
index 9adee53e8..fa099178c 100644
--- a/src/client/views/nodes/VideoBox.tsx
+++ b/src/client/views/nodes/VideoBox.tsx
@@ -331,7 +331,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
         Doc.SetNativeHeight(imageSnapshot[DocData], Doc.NativeHeight(this.layoutDoc));
         this._props.addDocument?.(imageSnapshot);
         DocUtils.MakeLink(imageSnapshot, this.getAnchor(true), { link_relationship: 'video snapshot' });
-        // link && (DocCast(link.link_anchor_2)[DocData].timecodeToHide = NumCast(DocCast(link.link_anchor_2).timecodeToShow) + 3);  // do we need to set an end time? should default to +0.1
+        // link && (DocCast(link.link_anchor_2).$timecodeToHide = NumCast(DocCast(link.link_anchor_2).timecodeToShow) + 3);  // do we need to set an end time? should default to +0.1
         setTimeout(() => downX !== undefined && downY !== undefined && DocumentView.getFirstDocumentView(imageSnapshot)?.startDragging(downX, downY, dropActionType.move, true));
     };
 
@@ -918,11 +918,10 @@ export class VideoBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
     crop = (region: Doc | undefined, addCrop?: boolean) => {
         if (!region) return undefined;
         const cropping = Doc.MakeCopy(region, true);
-        const regionData = region[DocData];
-        regionData.backgroundColor = 'transparent';
-        regionData.lockedPosition = true;
-        regionData.title = 'region:' + this.Document.title;
-        regionData.followLinkToggle = true;
+        region.$backgroundColor = 'transparent';
+        region.$lockedPosition = true;
+        region.$title = 'region:' + this.Document.title;
+        region.$followLinkToggle = true;
         region._timecodeToHide = NumCast(region._timecodeToShow) + 0.0001;
         this.addDocument(region);
         const anchx = NumCast(cropping.x);
@@ -938,25 +937,24 @@ export class VideoBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
         cropping.timecodeToHide = undefined;
         cropping.timecodeToShow = undefined;
         cropping.onClick = undefined;
-        const croppingProto = cropping[DocData];
-        croppingProto.annotationOn = undefined;
-        croppingProto.isDataDoc = true;
-        croppingProto.proto = Cast(this.Document.proto, Doc, null)?.proto; // set proto of cropping's data doc to be IMAGE_PROTO
-        croppingProto.type = DocumentType.VID;
-        croppingProto.layout = VideoBox.LayoutString('data');
-        croppingProto.data = ObjectField.MakeCopy(this.dataDoc[this.fieldKey] as ObjectField);
-        croppingProto.data_nativeWidth = anchw;
-        croppingProto.data_nativeHeight = anchh;
-        croppingProto.videoCrop = true;
-        croppingProto.layout_currentTimecode = this.layoutDoc._layout_currentTimecode;
-        croppingProto.freeform_scale = viewScale;
-        croppingProto.freeform_scale_min = viewScale;
-        croppingProto.freeform_ = anchx / viewScale;
-        croppingProto.freeform_panY = anchy / viewScale;
-        croppingProto.freeform_panX_min = anchx / viewScale;
-        croppingProto.freeform_panX_max = anchw / viewScale;
-        croppingProto.freeform_panY_min = anchy / viewScale;
-        croppingProto.freeform_panY_max = anchh / viewScale;
+        cropping.$annotationOn = undefined;
+        cropping.$isDataDoc = true;
+        cropping.$proto = Cast(this.Document.proto, Doc, null)?.proto; // set proto of cropping's data doc to be IMAGE_PROTO
+        cropping.$type = DocumentType.VID;
+        cropping.$layout = VideoBox.LayoutString('data');
+        cropping.$data = ObjectField.MakeCopy(this.dataDoc[this.fieldKey] as ObjectField);
+        cropping.$data_nativeWidth = anchw;
+        cropping.$data_nativeHeight = anchh;
+        cropping.$videoCrop = true;
+        cropping.$layout_currentTimecode = this.layoutDoc._layout_currentTimecode;
+        cropping.$freeform_scale = viewScale;
+        cropping.$freeform_scale_min = viewScale;
+        cropping.$freeform_ = anchx / viewScale;
+        cropping.$freeform_panY = anchy / viewScale;
+        cropping.$freeform_panX_min = anchx / viewScale;
+        cropping.$freeform_panX_max = anchw / viewScale;
+        cropping.$freeform_panY_min = anchy / viewScale;
+        cropping.$freeform_panY_max = anchh / viewScale;
         if (addCrop) {
             DocUtils.MakeLink(region, cropping, { link_relationship: 'cropped image' });
         }
diff --git a/src/client/views/nodes/calendarBox/CalendarBox.tsx b/src/client/views/nodes/calendarBox/CalendarBox.tsx
index 1cbfd5fba..e3408696b 100644
--- a/src/client/views/nodes/calendarBox/CalendarBox.tsx
+++ b/src/client/views/nodes/calendarBox/CalendarBox.tsx
@@ -113,7 +113,7 @@ export class CalendarBox extends CollectionSubView() {
         if (!super.onInternalDrop(e, de)) return false;
         de.complete.docDragData?.droppedDocuments.forEach(doc => {
             const today = new Date().toISOString();
-            if (!doc.date_range) doc[DocData].date_range = `${today}|${today}`;
+            if (!doc.date_range) doc.$date_range = `${today}|${today}`;
         });
         return true;
     };
diff --git a/src/client/views/nodes/chatbot/chatboxcomponents/ChatBox.tsx b/src/client/views/nodes/chatbot/chatboxcomponents/ChatBox.tsx
index 6e9307d37..b023b1de6 100644
--- a/src/client/views/nodes/chatbot/chatboxcomponents/ChatBox.tsx
+++ b/src/client/views/nodes/chatbot/chatboxcomponents/ChatBox.tsx
@@ -733,9 +733,9 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
                     const x2 = parseFloat(values[2]) * Doc.NativeWidth(doc);
                     const y2 = parseFloat(values[3]) * Doc.NativeHeight(doc) + foundChunk.startPage * Doc.NativeHeight(doc);
 
-                    const annotationKey = Doc.LayoutFieldKey(doc) + '_annotations';
+                    const annotationKey = '$' + Doc.LayoutFieldKey(doc) + '_annotations';
 
-                    const existingDoc = DocListCast(doc[DocData][annotationKey]).find(d => d.citation_id === citation.citation_id);
+                    const existingDoc = DocListCast(doc[annotationKey]).find(d => d.citation_id === citation.citation_id);
                     const highlightDoc = existingDoc ?? this.createImageCitationHighlight(x1, y1, x2, y2, citation, annotationKey, doc);
 
                     DocumentManager.Instance.showDocument(highlightDoc, { willZoomCentered: true }, () => {});
@@ -779,7 +779,7 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
             _height: y2 - y1,
             backgroundColor: 'rgba(255, 255, 0, 0.5)',
         });
-        highlight_doc[DocData].citation_id = citation.citation_id;
+        highlight_doc.$citation_id = citation.citation_id;
         Doc.AddDocToList(pdfDoc[DocData], annotationKey, highlight_doc);
         highlight_doc.annotationOn = pdfDoc;
         Doc.SetContainer(highlight_doc, pdfDoc);
diff --git a/src/client/views/nodes/formattedText/EquationView.tsx b/src/client/views/nodes/formattedText/EquationView.tsx
index e0450b202..827db190a 100644
--- a/src/client/views/nodes/formattedText/EquationView.tsx
+++ b/src/client/views/nodes/formattedText/EquationView.tsx
@@ -6,7 +6,6 @@ import { EditorView } from 'prosemirror-view';
 import * as React from 'react';
 import * as ReactDOM from 'react-dom/client';
 import { Doc } from '../../../../fields/Doc';
-import { DocData } from '../../../../fields/DocSymbols';
 import { StrCast } from '../../../../fields/Types';
 import './DashFieldView.scss';
 import EquationEditor from './EquationEditor';
@@ -63,9 +62,9 @@ export class EquationViewInternal extends React.Component<IEquationViewInternal>
                 }}>
                 <EquationEditor
                     ref={this._ref}
-                    value={StrCast(this._textBoxDoc[DocData][this._fieldKey])}
+                    value={StrCast(this._textBoxDoc['$' + this._fieldKey])}
                     onChange={str => {
-                        this._textBoxDoc[DocData][this._fieldKey] = str;
+                        this._textBoxDoc['$' + this._fieldKey] = str;
                     }}
                     autoCommands="pi theta sqrt sum prod alpha beta gamma rho"
                     autoOperatorNames="sin cos tan"
diff --git a/src/client/views/nodes/imageEditor/ImageEditor.tsx b/src/client/views/nodes/imageEditor/ImageEditor.tsx
index 657e689bb..85bd95d15 100644
--- a/src/client/views/nodes/imageEditor/ImageEditor.tsx
+++ b/src/client/views/nodes/imageEditor/ImageEditor.tsx
@@ -24,8 +24,8 @@ import { PointerHandler } from './imageEditorUtils/PointerHandler';
 import { activeColor, bgColor, brushWidthOffset, canvasSize, eraserColor, freeformRenderSize, newCollectionSize, offsetDistanceY, offsetX } from './imageEditorUtils/imageEditorConstants';
 import { CutMode, CursorData, ImageDimensions, ImageEditTool, ImageToolType, Point } from './imageEditorUtils/imageEditorInterfaces';
 import { DocumentView } from '../DocumentView';
-import { DocData } from '../../../../fields/DocSymbols';
 import { SettingsManager } from '../../../util/SettingsManager';
+import { Upload } from '../../../../server/SharedMediaTypes';
 
 interface GenerativeFillProps {
     imageEditorOpen: boolean;
@@ -397,9 +397,8 @@ const ImageEditor = ({ imageEditorOpen, imageEditorSource, imageRootDoc, addDoc
             const newImgDoc = await createNewImgDoc(finalImg, firstDoc);
             if (newImgDoc) {
                 // set the image to transparent to remove the background / brushstrokes
-                const docData = newImgDoc[DocData];
-                docData.backgroundColor = 'transparent';
-                docData.disableMixBlend = true;
+                newImgDoc.$backgroundColor = 'transparent';
+                newImgDoc.$disableMixBlend = true;
                 if (firstDoc) setIsFirstDoc(false);
                 setEdits([...prevEdits, { url: finalImgURL, saveRes: undefined }]);
             }
@@ -476,7 +475,7 @@ const ImageEditor = ({ imageEditorOpen, imageEditorSource, imageRootDoc, addDoc
     const createNewImgDoc = async (img: HTMLImageElement, firstDoc: boolean /*, parent?: Doc */): Promise<Doc | undefined> => {
         if (!imageRootDoc) return undefined;
         const { src } = img;
-        const [result] = await Networking.PostToServer('/uploadRemoteImage', { sources: [src] });
+        const [result] = (await Networking.PostToServer('/uploadRemoteImage', { sources: [src] })) as Upload.ImageInformation[];
         const source = ClientUtils.prepend(result.accessPaths.agnostic.client);
 
         if (firstDoc) {
diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx
index ec97e067a..23155ebf3 100644
--- a/src/client/views/nodes/trails/PresBox.tsx
+++ b/src/client/views/nodes/trails/PresBox.tsx
@@ -532,11 +532,10 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
             const setData = bestTargetView?.ComponentView?.setData;
             if (setData) setData(activeItem.config_data);
             else {
-                const bestTargetData = bestTarget[DocData];
-                const current = bestTargetData[fkey];
-                const hash = bestTargetData[fkey] ? stringHash(Field.toString(bestTargetData[fkey] as FieldType)) : undefined;
-                if (hash) bestTargetData[fkey + '_' + hash] = current instanceof ObjectField ? current[Copy]() : current;
-                bestTargetData[fkey] = activeItem.config_data instanceof ObjectField ? activeItem.config_data[Copy]() : activeItem.config_data;
+                const current = bestTarget['$' + fkey];
+                const hash = bestTarget['$' + fkey] ? stringHash(Field.toString(bestTarget['$' + fkey] as FieldType)) : undefined;
+                if (hash) bestTarget['$' + fkey + '_' + hash] = current instanceof ObjectField ? current[Copy]() : current;
+                bestTarget['$' + fkey] = activeItem.config_data instanceof ObjectField ? activeItem.config_data[Copy]() : activeItem.config_data;
             }
             bestTarget[fkey + '_usePath'] = activeItem.config_usePath;
             setTimeout(() => {
diff --git a/src/client/views/smartdraw/SmartDrawHandler.tsx b/src/client/views/smartdraw/SmartDrawHandler.tsx
index 1cceabed3..2283ef965 100644
--- a/src/client/views/smartdraw/SmartDrawHandler.tsx
+++ b/src/client/views/smartdraw/SmartDrawHandler.tsx
@@ -10,9 +10,11 @@ import { INode, parse } from 'svgson';
 import { imageUrlToBase64, setupMoveUpEvents } from '../../../ClientUtils';
 import { unimplementedFunction } from '../../../Utils';
 import { Doc, DocListCast } from '../../../fields/Doc';
-import { DocData } from '../../../fields/DocSymbols';
 import { InkData, InkField, InkTool } from '../../../fields/InkField';
+import { List } from '../../../fields/List';
 import { BoolCast, ImageCast, NumCast, StrCast } from '../../../fields/Types';
+import { PointData } from '../../../pen-gestures/GestureTypes';
+import { Upload } from '../../../server/SharedMediaTypes';
 import { Networking } from '../../Network';
 import { GPTCallType, gptAPICall, gptDrawingColor } from '../../apis/gpt/GPT';
 import { DocumentType } from '../../documents/DocumentTypes';
@@ -26,9 +28,6 @@ import { MarqueeView } from '../collections/collectionFreeForm';
 import { ActiveInkArrowEnd, ActiveInkArrowStart, ActiveInkBezierApprox, ActiveInkColor, ActiveInkDash, ActiveInkFillColor, ActiveInkWidth, ActiveIsInkMask, DocumentView } from '../nodes/DocumentView';
 import { FireflyDimensionsMap, FireflyImageData, FireflyImageDimensions } from './FireflyConstants';
 import './SmartDrawHandler.scss';
-import { Upload } from '../../../server/SharedMediaTypes';
-import { PointData } from '../../../pen-gestures/GestureTypes';
-import { List } from '../../../fields/List';
 
 export interface DrawingOptions {
     text?: string;
@@ -153,9 +152,9 @@ export class SmartDrawHandler extends ObservableReactComponent<object> {
         this._display = false;
         this.ShowRegenerate = true;
         this._showEditBox = false;
-        const docData = this._selectedDocs[0][DocData];
-        this._lastResponse = StrCast(docData.drawingData);
-        this._lastInput = { text: StrCast(docData.ai_drawing_input), complexity: NumCast(docData.ai_drawing_complexity), size: NumCast(docData.ai_drawing_size), autoColor: BoolCast(docData.ai_drawing_colored), x: this._pageX, y: this._pageY };
+        const docData = this._selectedDocs[0];
+        this._lastResponse = StrCast(docData.$drawingData);
+        this._lastInput = { text: StrCast(docData.$ai_drawing_input), complexity: NumCast(docData.$ai_drawing_complexity), size: NumCast(docData.$ai_drawing_size), autoColor: BoolCast(docData.$ai_drawing_colored), x: this._pageX, y: this._pageY };
     };
 
     /**
@@ -404,7 +403,7 @@ export class SmartDrawHandler extends ObservableReactComponent<object> {
         const hrefComplete = `${hrefParts[0]}_o.${hrefParts[1]}`;
         try {
             const hrefBase64 = await imageUrlToBase64(hrefComplete);
-            const strokes = DocListCast(drawing[DocData].data);
+            const strokes = DocListCast(drawing.$data);
             const coords: string[] = [];
             strokes.forEach((stroke, i) => {
                 const inkingStroke = DocumentView.getDocumentView(stroke)?.ComponentView as InkingStroke;
@@ -423,14 +422,14 @@ export class SmartDrawHandler extends ObservableReactComponent<object> {
      */
     colorStrokes = undoable((res: string, drawing: Doc) => {
         const colorList = res.match(/\{.*?\}/g);
-        const strokes = DocListCast(drawing[DocData].data);
+        const strokes = DocListCast(drawing.$data);
         colorList?.forEach((colors, index) => {
             const strokeAndFill = colors.match(/#[0-9A-Fa-f]{6}/g);
             if (strokeAndFill && strokeAndFill.length == 2) {
-                strokes[index][DocData].color = strokeAndFill[0];
+                strokes[index].$color = strokeAndFill[0];
                 const inkStroke = DocumentView.getDocumentView(strokes[index])?.ComponentView as InkingStroke;
                 const { inkData } = inkStroke.inkScaledData();
-                InkingStroke.IsClosed(inkData) ? (strokes[index][DocData].fillColor = strokeAndFill[1]) : (strokes[index][DocData].fillColor = undefined);
+                InkingStroke.IsClosed(inkData) ? (strokes[index].$fillColor = strokeAndFill[1]) : (strokes[index].$fillColor = undefined);
             }
         });
     }, 'color strokes');
diff --git a/src/client/views/smartdraw/StickerPalette.tsx b/src/client/views/smartdraw/StickerPalette.tsx
index e3305851a..080a05d42 100644
--- a/src/client/views/smartdraw/StickerPalette.tsx
+++ b/src/client/views/smartdraw/StickerPalette.tsx
@@ -9,7 +9,6 @@ import ReactLoading from 'react-loading';
 import { returnEmptyFilter, returnFalse, returnTrue } from '../../../ClientUtils';
 import { emptyFunction, numberRange } from '../../../Utils';
 import { Doc, DocListCast, returnEmptyDoclist } from '../../../fields/Doc';
-import { DocData } from '../../../fields/DocSymbols';
 import { ImageCast, NumCast } from '../../../fields/Types';
 import { ImageField } from '../../../fields/URLField';
 import { DocumentType } from '../../documents/DocumentTypes';
@@ -133,7 +132,7 @@ export class StickerPalette extends ObservableReactComponent<StickerPaletteProps
         this._canInteract = true;
         this._opts = { text: '', complexity: 5, size: 200, autoColor: true, x: 0, y: 0 };
         this._gptRes = [];
-        this._props.Document[DocData].data = undefined;
+        this._props.Document.$data = undefined;
     });
 
     /**
@@ -143,8 +142,8 @@ export class StickerPalette extends ObservableReactComponent<StickerPaletteProps
     @undoBatch
     generateDrawings = action(() => {
         this._isLoading = true;
-        const prevDrawings = DocListCast(this._props.Document[DocData].data);
-        this._props.Document[DocData].data = undefined;
+        const prevDrawings = DocListCast(this._props.Document.$data);
+        this._props.Document.$data = undefined;
         SmartDrawHandler.Instance.AddDrawing = this.addDrawing;
         this._canInteract = false;
         Promise.all(
@@ -164,7 +163,7 @@ export class StickerPalette extends ObservableReactComponent<StickerPaletteProps
     @action
     addDrawing = (drawing: Doc, opts: DrawingOptions, gptRes: string) => {
         this._gptRes.push(gptRes);
-        drawing[DocData].freeform_fitContentsToBox = true;
+        drawing.$freeform_fitContentsToBox = true;
         Doc.AddDocToList(this._props.Document, 'data', drawing);
     };
 
@@ -176,17 +175,16 @@ export class StickerPalette extends ObservableReactComponent<StickerPaletteProps
     saveDrawing = () => {
         const cIndex = NumCast(this._props.Document.carousel_index);
         const focusedDrawing = DocListCast(this._props.Document.data)[cIndex];
-        const docData = focusedDrawing[DocData];
-        docData.title = this._opts.text?.match(/^(.*?)~~~.*$/)?.[1] || this._opts.text;
-        docData.ai_drawing_input = this._opts.text;
-        docData.ai_drawing_complexity = this._opts.complexity;
-        docData.ai_drawing_colored = this._opts.autoColor;
-        docData.ai_drawing_size = this._opts.size;
-        docData.ai_drawing_data = this._gptRes[cIndex];
-        docData.ai = 'gpt';
+        focusedDrawing.$title = this._opts.text?.match(/^(.*?)~~~.*$/)?.[1] || this._opts.text;
+        focusedDrawing.$ai_drawing_input = this._opts.text;
+        focusedDrawing.$ai_drawing_complexity = this._opts.complexity;
+        focusedDrawing.$ai_drawing_colored = this._opts.autoColor;
+        focusedDrawing.$ai_drawing_size = this._opts.size;
+        focusedDrawing.$ai_drawing_data = this._gptRes[cIndex];
+        focusedDrawing.$ai = 'gpt';
         focusedDrawing.width = this._opts.size;
-        docData.x = this._opts.x;
-        docData.y = this._opts.y;
+        focusedDrawing.x = this._opts.x;
+        focusedDrawing.y = this._opts.y;
         StickerPalette.addToPalette(focusedDrawing).then(() => this.resetPalette(true));
     };
 
diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts
index e2f708700..4bf04da5c 100644
--- a/src/fields/Doc.ts
+++ b/src/fields/Doc.ts
@@ -273,12 +273,12 @@ export class Doc extends RefField {
     public static AddToMyOverlay(doc: Doc)    { return Doc.ActiveDashboard ? Doc.AddDocToList(Doc.ActiveDashboard, 'myOverlayDocs', doc) : Doc.AddDocToList(DocCast(Doc.UserDoc().myOverlayDocs), undefined, doc); } // prettier-ignore
     public static RemFromMyOverlay(doc: Doc)  { return Doc.ActiveDashboard ? Doc.RemoveDocFromList(Doc.ActiveDashboard,'myOverlayDocs', doc) : Doc.RemoveDocFromList(DocCast(Doc.UserDoc().myOverlayDocs), undefined, doc); } // prettier-ignore
     public static AddToMyPublished(doc: Doc)  {
-        doc[DocData].title_custom = true;
-        doc[DocData].layout_showTitle = 'title'; 
+        doc.$title_custom = true;
+        doc.$layout_showTitle = 'title'; 
         Doc.ActiveDashboard ? Doc.AddDocToList(Doc.ActiveDashboard, 'myPublishedDocs', doc) : Doc.AddDocToList(DocCast(Doc.UserDoc().myPublishedDocs), undefined, doc); } // prettier-ignore
     public static RemFromMyPublished(doc: Doc){ 
-        doc[DocData].title_custom = false;
-        doc[DocData].layout_showTitle = undefined;
+        doc.$title_custom = false;
+        doc.$layout_showTitle = undefined;
         Doc.ActiveDashboard ? Doc.RemoveDocFromList(Doc.ActiveDashboard,'myPublishedDocs', doc) : Doc.RemoveDocFromList(DocCast(Doc.UserDoc().myPublishedDocs), undefined, doc); } // prettier-ignore
     public static IsComicStyle(doc?: Doc)     { return doc && Doc.ActiveDashboard && !Doc.IsSystem(doc) && Doc.UserDoc().renderStyle === 'comic' ; } // prettier-ignore
 
@@ -629,7 +629,7 @@ export namespace Doc {
      */
     export function RemoveDocFromList(listDoc: Doc, fieldKey: string | undefined, doc: Doc, ignoreProto = false) {
         const key = fieldKey || Doc.LayoutFieldKey(listDoc);
-        const list = Doc.Get(listDoc, key, ignoreProto) === undefined ? (listDoc[DocData][key] = new List<Doc>()) : Cast(listDoc[key], listSpec(Doc));
+        const list = Doc.Get(listDoc, key, ignoreProto) === undefined ? (listDoc['$' + key] = new List<Doc>()) : Cast(listDoc[key], listSpec(Doc));
         if (list) {
             const ind = list.indexOf(doc);
             if (ind !== -1) {
@@ -646,7 +646,7 @@ export namespace Doc {
      */
     export function AddDocToList(listDoc: Doc, fieldKey: string | undefined, doc: Doc, relativeTo?: Doc, before?: boolean, first?: boolean, allowDuplicates?: boolean, reversed?: boolean, ignoreProto?: boolean) {
         const key = fieldKey || Doc.LayoutFieldKey(listDoc);
-        const list = Doc.Get(listDoc, key, ignoreProto) === undefined ? (listDoc[DocData][key] = new List<Doc>()) : Cast(listDoc[key], listSpec(Doc));
+        const list = Doc.Get(listDoc, key, ignoreProto) === undefined ? (listDoc['$' + key] = new List<Doc>()) : Cast(listDoc[key], listSpec(Doc));
         if (list) {
             if (!allowDuplicates) {
                 const pind = list.findIndex(d => d instanceof Doc && d[Id] === doc[Id]);
@@ -691,7 +691,7 @@ export namespace Doc {
             Doc.SetLayout(embedding, Doc.MakeEmbedding(layout));
         }
         embedding.createdFrom = doc;
-        embedding.proto_embeddingId = doc[DocData].proto_embeddingId = Doc.GetEmbeddings(doc).length - 1;
+        embedding.proto_embeddingId = doc.$proto_embeddingId = Doc.GetEmbeddings(doc).length - 1;
         !Doc.GetT(embedding, 'title', 'string', true) && (embedding.title = ComputedField.MakeFunction(`renameEmbedding(this)`));
         embedding.author = ClientUtils.CurrentUserEmail();
 
@@ -699,9 +699,8 @@ export namespace Doc {
     }
 
     export function BestEmbedding(doc: Doc) {
-        const dataDoc = doc[DocData];
-        const availableEmbeddings = Doc.GetEmbeddings(dataDoc);
-        const bestEmbedding = [...(dataDoc !== doc ? [doc] : []), ...availableEmbeddings].find(d => !d.embedContainer && d.author === ClientUtils.CurrentUserEmail());
+        const availableEmbeddings = Doc.GetEmbeddings(doc);
+        const bestEmbedding = [...(doc[DocData] !== doc ? [doc] : []), ...availableEmbeddings].find(d => !d.embedContainer && d.author === ClientUtils.CurrentUserEmail());
         bestEmbedding && Doc.AddEmbedding(doc, doc);
         return bestEmbedding ?? Doc.MakeEmbedding(doc);
     }
@@ -1475,7 +1474,7 @@ export namespace Doc {
      * @returns
      */
     export function getDescription(doc: Doc) {
-        const curDescription = StrCast(doc[DocData][Doc.LayoutFieldKey(doc) + '_description']);
+        const curDescription = StrCast(doc['$' + Doc.LayoutFieldKey(doc) + '_description']);
         const docText = (async (tdoc:Doc) => {
             switch (tdoc.type) {
                 case DocumentType.PDF: return curDescription || StrCast(tdoc.text).split(/\s+/).slice(0, 50).join(' '); // first 50 words of pdf text
@@ -1484,7 +1483,7 @@ export namespace Doc {
                 case DocumentType.RTF: return RTFCast(tdoc[Doc.LayoutFieldKey(tdoc)]).Text;
                 default:               return StrCast(tdoc.title).startsWith("Untitled") ? "" : StrCast(tdoc.title);
         }}); // prettier-ignore
-        return docText(doc).then(text => (doc[DocData][Doc.LayoutFieldKey(doc) + '_description'] = text));
+        return docText(doc).then(text => (doc['$' + Doc.LayoutFieldKey(doc) + '_description'] = text));
     }
 
     // prettier-ignore
@@ -1737,7 +1736,7 @@ ScriptingGlobals.add(function idToDoc(id: string): Doc {
 });
 // eslint-disable-next-line prefer-arrow-callback
 ScriptingGlobals.add(function renameEmbedding(doc: Doc) {
-    return StrCast(doc[DocData].title).replace(/\([0-9]*\)/, '') + `(${doc.proto_embeddingId})`;
+    return StrCast(doc.$title).replace(/\([0-9]*\)/, '') + `(${doc.proto_embeddingId})`;
 });
 // eslint-disable-next-line prefer-arrow-callback
 ScriptingGlobals.add(function getProto(doc: Doc) {
diff --git a/src/fields/ScriptField.ts b/src/fields/ScriptField.ts
index b294ee8c6..6e2d7eb78 100644
--- a/src/fields/ScriptField.ts
+++ b/src/fields/ScriptField.ts
@@ -210,6 +210,7 @@ export class ComputedField extends ScriptField {
         this._lastComputedResult =
             this._cachedResult ??
             computedFn(() =>
+                ((val) => val instanceof Array ? new List<number>(val) : val)(
                 this.script.compiled &&
                 this.script.run(
                     {
@@ -220,7 +221,7 @@ export class ComputedField extends ScriptField {
                         _readOnly_: true,
                     },
                     console.log
-                ).result as FieldResult
+                ).result as FieldResult)
             )(); // prettier-ignore
         return this._lastComputedResult;
     };
-- 
cgit v1.2.3-70-g09d2


From 7d54c52528be4f5a4f7dd94acfd4d4bb67b81f74 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Sun, 23 Mar 2025 10:33:05 -0400
Subject: from last

---
 src/client/views/collections/CollectionMenu.tsx    | 6 +-----
 src/client/views/collections/TreeView.tsx          | 2 +-
 src/client/views/nodes/LinkDescriptionPopup.tsx    | 5 ++---
 src/client/views/nodes/PDFBox.tsx                  | 2 +-
 src/client/views/nodes/calendarBox/CalendarBox.tsx | 1 -
 5 files changed, 5 insertions(+), 11 deletions(-)

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

diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx
index 26aca458c..c79610595 100644
--- a/src/client/views/collections/CollectionMenu.tsx
+++ b/src/client/views/collections/CollectionMenu.tsx
@@ -1,5 +1,3 @@
-/* eslint-disable react/no-unused-class-component-methods */
-/* eslint-disable react/sort-comp */
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { Tooltip } from '@mui/material';
 import { Toggle, ToggleType, Type } from '@dash/components';
@@ -157,9 +155,7 @@ export class CollectionMenu extends AntimodeMenu<CollectionMenuProps> {
 }
 
 interface CollectionViewMenuProps {
-    // eslint-disable-next-line react/no-unused-prop-types
     type: CollectionViewType;
-    // eslint-disable-next-line react/no-unused-prop-types
     fieldKey: string;
     docView: DocumentView;
 }
@@ -184,7 +180,7 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewMenu
             let formatStr = source.length && Cast(source[0].text, RichTextField, null)?.Text;
             try {
                 formatStr && JSON.parse(formatStr);
-            } catch (e) {
+            } catch {
                 formatStr = '';
             }
             if (source.length === 1 && formatStr) {
diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx
index d6a19e88e..5ac283d22 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -834,7 +834,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
 
     @observable headerEleWidth = 0;
     @computed get titleButtons() {
-        const customHeaderButtons = this._props.styleProvider?.(this.Document, this.treeView._props, StyleProp.Decorations);
+        const customHeaderButtons = this._props.styleProvider?.(this.Document, this.treeView._props, StyleProp.Decorations) as JSX.Element;
         const color = SettingsManager.userColor;
         return this._props.treeViewHideHeaderFields() || this.Document.treeView_HideHeaderFields ? null : (
             <>
diff --git a/src/client/views/nodes/LinkDescriptionPopup.tsx b/src/client/views/nodes/LinkDescriptionPopup.tsx
index 6bec9c53d..9dff55bf1 100644
--- a/src/client/views/nodes/LinkDescriptionPopup.tsx
+++ b/src/client/views/nodes/LinkDescriptionPopup.tsx
@@ -7,18 +7,17 @@ import './LinkDescriptionPopup.scss';
 import { TaskCompletionBox } from './TaskCompletedBox';
 
 @observer
-export class LinkDescriptionPopup extends React.Component<{}> {
+export class LinkDescriptionPopup extends React.Component<object> {
     // eslint-disable-next-line no-use-before-define
     public static Instance: LinkDescriptionPopup;
     @observable public display: boolean = false;
-    // eslint-disable-next-line react/no-unused-class-component-methods
     @observable public showDescriptions: string = 'ON';
     @observable public popupX: number = 700;
     @observable public popupY: number = 350;
     @observable description: string = '';
     @observable popupRef = React.createRef<HTMLDivElement>();
 
-    constructor(props: any) {
+    constructor(props: object) {
         super(props);
         makeObservable(this);
         LinkDescriptionPopup.Instance = this;
diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx
index 1f72206fc..5484179be 100644
--- a/src/client/views/nodes/PDFBox.tsx
+++ b/src/client/views/nodes/PDFBox.tsx
@@ -156,7 +156,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
                 ClientUtils.convertDataUri(dataUrl, region[Id]).then(returnedfilename =>
                     setTimeout(
                         action(() => {
-                            croppingProto.data = new ImageField(returnedfilename);
+                            cropping.$data = new ImageField(returnedfilename);
                         }),
                         500
                     )
diff --git a/src/client/views/nodes/calendarBox/CalendarBox.tsx b/src/client/views/nodes/calendarBox/CalendarBox.tsx
index e3408696b..6f1f58a4c 100644
--- a/src/client/views/nodes/calendarBox/CalendarBox.tsx
+++ b/src/client/views/nodes/calendarBox/CalendarBox.tsx
@@ -8,7 +8,6 @@ import { observer } from 'mobx-react';
 import * as React from 'react';
 import { dateRangeStrToDates } from '../../../../ClientUtils';
 import { Doc } from '../../../../fields/Doc';
-import { DocData } from '../../../../fields/DocSymbols';
 import { Id } from '../../../../fields/FieldSymbols';
 import { BoolCast, NumCast, StrCast } from '../../../../fields/Types';
 import { DocServer } from '../../../DocServer';
-- 
cgit v1.2.3-70-g09d2


From 78ac87b8acf63079071e5e8805692ed8c30042ce Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Wed, 23 Apr 2025 22:02:36 -0400
Subject: lots of typechecking fixes.

---
 .../apis/google_docs/GooglePhotosClientUtils.ts    |  2 +-
 src/client/util/CalendarManager.tsx                |  2 +-
 src/client/util/DocumentManager.ts                 |  8 +++---
 src/client/util/LinkManager.ts                     |  3 +-
 src/client/util/ReplayMovements.ts                 |  6 ++--
 src/client/util/ScriptManager.ts                   |  9 ++----
 src/client/util/SearchUtil.ts                      |  5 ++--
 .../util/reportManager/ReportManagerComponents.tsx |  4 +--
 src/client/views/DashboardView.tsx                 | 28 +++++++++----------
 src/client/views/InkStrokeProperties.ts            |  8 +++---
 src/client/views/InkingStroke.tsx                  | 12 ++++----
 src/client/views/PropertiesButtons.tsx             | 23 ++++++++--------
 .../views/PropertiesDocBacklinksSelector.tsx       |  8 ++----
 src/client/views/PropertiesDocContextSelector.tsx  |  4 +--
 src/client/views/UndoStack.tsx                     |  5 +---
 src/client/views/animationtimeline/Region.tsx      | 32 ++++++++++------------
 src/client/views/animationtimeline/Track.tsx       | 24 ++++++++--------
 src/client/views/collections/CollectionMenu.tsx    |  4 +--
 .../collections/CollectionNoteTakingViewColumn.tsx |  2 +-
 .../views/collections/CollectionPileView.tsx       |  1 -
 .../collections/CollectionStackedTimeline.tsx      |  2 +-
 .../views/collections/CollectionTreeView.tsx       |  8 +++---
 .../views/collections/FlashcardPracticeUI.tsx      |  2 +-
 src/client/views/collections/TreeView.tsx          |  4 +--
 .../CollectionFreeFormLayoutEngines.tsx            |  2 +-
 .../collectionFreeForm/FaceCollectionBox.tsx       | 13 +++++----
 .../collectionSchema/SchemaColumnHeader.tsx        |  2 +-
 .../collectionSchema/SchemaTableCell.tsx           | 18 ++++++------
 src/client/views/linking/LinkMenuGroup.tsx         |  5 ++--
 src/client/views/linking/LinkMenuItem.tsx          |  4 +--
 .../views/newlightbox/ExploreView/ExploreView.tsx  |  4 +--
 src/client/views/newlightbox/NewLightboxView.tsx   |  7 ++---
 src/client/views/nodes/DataVizBox/DataVizBox.tsx   | 16 +++++------
 .../views/nodes/DataVizBox/SchemaCSVPopUp.tsx      |  6 ++--
 .../nodes/DataVizBox/components/Histogram.tsx      | 17 ++++++------
 .../nodes/DataVizBox/components/LineChart.tsx      | 25 +++++++++++------
 .../views/nodes/DataVizBox/components/TableBox.tsx |  2 +-
 src/client/views/nodes/EquationBox.tsx             |  1 -
 src/client/views/nodes/FieldView.tsx               |  7 +++--
 src/client/views/nodes/FunctionPlotBox.tsx         | 11 ++++----
 src/client/views/nodes/ImageBox.tsx                |  2 +-
 .../views/nodes/MapBox/DirectionsAnchorMenu.tsx    |  2 +-
 src/client/views/nodes/calendarBox/CalendarBox.tsx |  3 +-
 .../nodes/chatbot/chatboxcomponents/ChatBox.tsx    | 20 ++++++++------
 .../views/nodes/chatbot/tools/GetDocsTool.ts       |  5 +++-
 .../views/nodes/chatbot/vectorstore/Vectorstore.ts | 15 +++++-----
 .../views/nodes/formattedText/DailyJournal.tsx     |  2 +-
 src/client/views/nodes/scrapbook/ScrapbookBox.tsx  |  2 +-
 src/client/views/pdf/Annotation.tsx                |  7 +++--
 src/client/views/search/FaceRecognitionHandler.tsx |  6 ++--
 src/fields/Doc.ts                                  |  2 +-
 src/fields/Types.ts                                |  2 ++
 52 files changed, 207 insertions(+), 207 deletions(-)

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

diff --git a/src/client/apis/google_docs/GooglePhotosClientUtils.ts b/src/client/apis/google_docs/GooglePhotosClientUtils.ts
index 4b86a8341..15fd6313a 100644
--- a/src/client/apis/google_docs/GooglePhotosClientUtils.ts
+++ b/src/client/apis/google_docs/GooglePhotosClientUtils.ts
@@ -311,7 +311,7 @@ export namespace GooglePhotos {
             sources
                 .filter(source => ImageCast(Doc.GetProto(source).data))
                 .forEach(async source => {
-                    const data = ImageCast(Doc.GetProto(source).data);
+                    const data = ImageCast(Doc.GetProto(source).data)!;
                     const url = data.url.href;
                     const target = Doc.MakeEmbedding(source);
                     const description = parseDescription(target, descriptionKey);
diff --git a/src/client/util/CalendarManager.tsx b/src/client/util/CalendarManager.tsx
index 4e321a893..b50e39c02 100644
--- a/src/client/util/CalendarManager.tsx
+++ b/src/client/util/CalendarManager.tsx
@@ -162,7 +162,7 @@ export class CalendarManager extends ObservableReactComponent<object> {
 
             console.log('my calendars: ', Doc.MyCalendars);
             if (this.creationType === 'new-calendar') {
-                Doc.AddDocToList(Doc.MyCalendars, 'data', calendar); // add to new calendar to dashboard calendars
+                Doc.MyCalendars && Doc.AddDocToList(Doc.MyCalendars, 'data', calendar); // add to new calendar to dashboard calendars
             }
         }
     };
diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts
index ad57c2a62..3bae2881e 100644
--- a/src/client/util/DocumentManager.ts
+++ b/src/client/util/DocumentManager.ts
@@ -173,10 +173,10 @@ export class DocumentManager {
         while (
             containerDocContext.length &&
             DocCast(containerDocContext[0]?.embedContainer) &&
-            DocCast(containerDocContext[0].embedContainer)?._type_collection !== CollectionViewType.Docking &&
+            DocCast(containerDocContext[0].embedContainer)!._type_collection !== CollectionViewType.Docking &&
             (includeExistingViews || !DocumentManager.Instance.getDocumentView(containerDocContext[0]))
         ) {
-            containerDocContext = [Cast(containerDocContext[0].embedContainer, Doc, null), ...containerDocContext];
+            containerDocContext = [DocCast(containerDocContext[0].embedContainer)!, ...containerDocContext];
         }
         return containerDocContext;
     }
@@ -248,7 +248,7 @@ export class DocumentManager {
         finished?: (changed: boolean) => void // func called after focusing on target with flag indicating whether anything needed to be done.
     ) => {
         const options = optionsIn;
-        Doc.RemoveDocFromList(Doc.MyRecentlyClosed, undefined, targetDoc);
+        Doc.MyRecentlyClosed && Doc.RemoveDocFromList(Doc.MyRecentlyClosed, undefined, targetDoc);
         const docContextPath = DocumentManager.GetContextPath(targetDoc, true);
         if (docContextPath.some(doc => doc.hidden)) options.toggleTarget = false;
         let activatedTab = false;
@@ -272,7 +272,7 @@ export class DocumentManager {
             }));
         if (options.openLocation?.includes(OpenWhere.lightbox)) {
             // even if we found the document view, if the target is a lightbox, we try to open it in the lightbox to preserve lightbox semantics (eg, there's only one active doc in the lightbox)
-            const target = DocCast(targetDoc.annotationOn, targetDoc);
+            const target = DocCast(targetDoc.annotationOn, targetDoc)!;
             const compView = this.getDocumentView(DocCast(target.embedContainer))?.ComponentView;
             if ((compView?.addDocTab ?? compView?._props.addDocTab)?.(target, options.openLocation)) {
                 await new Promise<void>(waitres => {
diff --git a/src/client/util/LinkManager.ts b/src/client/util/LinkManager.ts
index 344e2e4c0..d8e0c4cbe 100644
--- a/src/client/util/LinkManager.ts
+++ b/src/client/util/LinkManager.ts
@@ -217,7 +217,8 @@ export class LinkManager {
     }
 
     // finds the opposite anchor of a given anchor in a link
-    public static getOppositeAnchor(linkDoc: Doc, anchor: Doc): Doc | undefined {
+    public static getOppositeAnchor(linkDoc: Doc | undefined, anchor: Doc | undefined): Doc | undefined {
+        if (!linkDoc || !anchor) return undefined;
         const id = LinkManager.anchorIndex(linkDoc, anchor);
         const a1 = DocCast(linkDoc.link_anchor_1);
         const a2 = DocCast(linkDoc.link_anchor_2);
diff --git a/src/client/util/ReplayMovements.ts b/src/client/util/ReplayMovements.ts
index 62a09a8bc..4f0423342 100644
--- a/src/client/util/ReplayMovements.ts
+++ b/src/client/util/ReplayMovements.ts
@@ -108,9 +108,11 @@ export class ReplayMovements {
 
         movements.forEach((movement, i) => {
             if (typeof movement.doc === 'string') {
-                movements[i].doc = IdToDoc(movement.doc);
-                if (!movements[i].doc) {
+                const doc = IdToDoc(movement.doc);
+                if (!doc) {
                     console.log('ERROR: tracked doc not found');
+                } else {
+                    movements[i].doc = doc;
                 }
             }
         });
diff --git a/src/client/util/ScriptManager.ts b/src/client/util/ScriptManager.ts
index 9158f6c0b..8c7f88bf6 100644
--- a/src/client/util/ScriptManager.ts
+++ b/src/client/util/ScriptManager.ts
@@ -1,7 +1,6 @@
-import { Doc, DocListCast } from '../../fields/Doc';
+import { Doc, DocListCast, StrListCast } from '../../fields/Doc';
 import { List } from '../../fields/List';
-import { listSpec } from '../../fields/Schema';
-import { Cast, StrCast } from '../../fields/Types';
+import { StrCast } from '../../fields/Types';
 import { Docs } from '../documents/Documents';
 import { ScriptingGlobals } from './ScriptingGlobals';
 
@@ -10,7 +9,6 @@ export class ScriptManager {
     // eslint-disable-next-line no-use-before-define
     private static _instance: ScriptManager;
     public static get Instance(): ScriptManager {
-        // eslint-disable-next-line no-return-assign
         return this._instance || (this._instance = new this());
     }
     private constructor() {
@@ -58,7 +56,7 @@ export class ScriptManager {
     public static addScriptToGlobals(scriptDoc: Doc): void {
         ScriptingGlobals.removeGlobal(StrCast(scriptDoc.name));
 
-        const params = Cast(scriptDoc['data-params'], listSpec('string'), []);
+        const params = StrListCast(scriptDoc['data-params']);
         const paramNames = params.reduce((o: string, p: string) => {
             let out = o;
             if (params.indexOf(p) === params.length - 1) {
@@ -69,7 +67,6 @@ export class ScriptManager {
             return out;
         }, '' as string);
 
-        // eslint-disable-next-line no-new-func
         const f = new Function(paramNames, StrCast(scriptDoc.script));
 
         Object.defineProperty(f, 'name', { value: StrCast(scriptDoc.name), writable: false });
diff --git a/src/client/util/SearchUtil.ts b/src/client/util/SearchUtil.ts
index e4adcaa7e..fc3bb99ab 100644
--- a/src/client/util/SearchUtil.ts
+++ b/src/client/util/SearchUtil.ts
@@ -13,7 +13,7 @@ export namespace SearchUtil {
         const blockedKeys = matchKeyNames
             ? []
             : Object.entries(DocOptions)
-                  .filter(([, info]: [string, FInfo]) => !info?.searchable())
+                  .filter(([, info]: [string, FieldType | FInfo | undefined]) => (info instanceof FInfo ? !info.searchable() : true))
                   .map(([key]) => key);
 
         const exact = queryIn.startsWith('=');
@@ -22,8 +22,7 @@ export namespace SearchUtil {
         const results = new ObservableMap<Doc, string[]>();
         if (collectionDoc) {
             const docs = DocListCast(collectionDoc[Doc.LayoutDataKey(collectionDoc)]);
-            // eslint-disable-next-line @typescript-eslint/ban-types
-            const docIDs: String[] = [];
+            const docIDs: string[] = [];
             SearchUtil.foreachRecursiveDoc(docs, (depth: number, doc: Doc) => {
                 const dtype = StrCast(doc.type) as DocumentType;
                 if (dtype && !blockedTypes.includes(dtype) && !docIDs.includes(doc[Id]) && depth >= 0) {
diff --git a/src/client/util/reportManager/ReportManagerComponents.tsx b/src/client/util/reportManager/ReportManagerComponents.tsx
index 92f877859..80653779e 100644
--- a/src/client/util/reportManager/ReportManagerComponents.tsx
+++ b/src/client/util/reportManager/ReportManagerComponents.tsx
@@ -1,5 +1,3 @@
-/* eslint-disable react/require-default-props */
-/* eslint-disable prefer-destructuring */
 /* eslint-disable no-use-before-define */
 import * as React from 'react';
 import ReactMarkdown from 'react-markdown';
@@ -299,7 +297,7 @@ export function IssueView({ issue }: IssueViewProps) {
                     </div>
                 </div>
             )}
-            <ReactMarkdown className="issue-content" remarkPlugins={[remarkGfm]} rehypePlugins={[rehypeRaw]}>
+            <ReactMarkdown remarkPlugins={[remarkGfm]} rehypePlugins={[rehypeRaw]}>
                 {issueBody}
             </ReactMarkdown>
         </div>
diff --git a/src/client/views/DashboardView.tsx b/src/client/views/DashboardView.tsx
index f61f6db18..3ceb23ffd 100644
--- a/src/client/views/DashboardView.tsx
+++ b/src/client/views/DashboardView.tsx
@@ -113,12 +113,12 @@ export class DashboardView extends ObservableReactComponent<object> {
 
     getDashboards = (whichGroup: DashboardGroup) => {
         if (whichGroup === DashboardGroup.MyDashboards) {
-            return DocListCast(Doc.MyDashboards.data).filter(dashboard => dashboard.$author === ClientUtils.CurrentUserEmail());
+            return DocListCast(Doc.MyDashboards?.data).filter(dashboard => dashboard.$author === ClientUtils.CurrentUserEmail());
         }
-        return DocListCast(Doc.MySharedDocs.data_dashboards).filter(doc => doc.dockingConfig);
+        return DocListCast(Doc.MySharedDocs?.data_dashboards).filter(doc => doc.dockingConfig);
     };
 
-    isUnviewedSharedDashboard = (dashboard: Doc) => !DocListCast(Doc.MySharedDocs.viewed).includes(dashboard);
+    isUnviewedSharedDashboard = (dashboard: Doc) => !DocListCast(Doc.MySharedDocs?.viewed).includes(dashboard);
 
     @undoBatch
     createNewDashboard = (name: string, background?: string) => {
@@ -155,7 +155,7 @@ export class DashboardView extends ObservableReactComponent<object> {
     @action
     openNewDashboardModal = () => {
         this.openModal = true;
-        this.setNewDashboardName(`Dashboard ${DocListCast(Doc.MyDashboards.data).length + 1}`);
+        this.setNewDashboardName(`Dashboard ${DocListCast(Doc.MyDashboards?.data).length + 1}`);
     };
 
     _downX: number = 0;
@@ -191,7 +191,7 @@ export class DashboardView extends ObservableReactComponent<object> {
                         <Button
                             text={'Shared Dashboards (' + this.getDashboards(DashboardGroup.SharedDashboards).length + ')'}
                             active={this.selectedDashboardGroup === DashboardGroup.SharedDashboards}
-                            color={this.getDashboards(DashboardGroup.SharedDashboards).some(dash => !DocListCast(Doc.MySharedDocs.viewed).includes(dash)) ? 'green' : color}
+                            color={this.getDashboards(DashboardGroup.SharedDashboards).some(dash => !DocListCast(Doc.MySharedDocs?.viewed).includes(dash)) ? 'green' : color}
                             align="flex-start"
                             onClick={() => this.selectDashboardGroup(DashboardGroup.SharedDashboards)}
                             fillWidth
@@ -275,7 +275,7 @@ export class DashboardView extends ObservableReactComponent<object> {
     }
 
     public static openSharedDashboard = (dashboard: Doc) => {
-        Doc.AddDocToList(Doc.MySharedDocs, 'viewed', dashboard);
+        Doc.MySharedDocs && Doc.AddDocToList(Doc.MySharedDocs, 'viewed', dashboard);
         DashboardView.openDashboard(Doc.BestEmbedding(dashboard));
     };
 
@@ -283,8 +283,8 @@ export class DashboardView extends ObservableReactComponent<object> {
     /// this also sets the readonly state of the dashboard based on the current mode of dash (from its url)
     public static openDashboard = (doc: Doc | undefined, fromHistory = false) => {
         if (!doc) return false;
-        Doc.AddDocToList(Doc.MyDashboards, 'data', doc);
-        Doc.RemoveDocFromList(Doc.MyRecentlyClosed, 'data', doc);
+        Doc.MyDashboards && Doc.AddDocToList(Doc.MyDashboards, 'data', doc);
+        Doc.MyRecentlyClosed && Doc.RemoveDocFromList(Doc.MyRecentlyClosed, 'data', doc);
 
         // this has the side-effect of setting the main container since we're assigning the active/guest dashboard
         Doc.UserDoc() ? (Doc.ActiveDashboard = doc) : (Doc.GuestDashboard = doc);
@@ -316,11 +316,11 @@ export class DashboardView extends ObservableReactComponent<object> {
     };
 
     public static removeDashboard = (dashboard: Doc) => {
-        const dashboards = DocListCast(Doc.MyDashboards.data).filter(dash => dash !== dashboard);
+        const dashboards = DocListCast(Doc.MyDashboards?.data).filter(dash => dash !== dashboard);
         undoable(() => {
             if (dashboard === Doc.ActiveDashboard) DashboardView.openDashboard(dashboards.lastElement());
-            Doc.RemoveDocFromList(Doc.MyDashboards, 'data', dashboard);
-            Doc.AddDocToList(Doc.MyRecentlyClosed, 'data', dashboard, undefined, true, true);
+            Doc.MyDashboards && Doc.RemoveDocFromList(Doc.MyDashboards, 'data', dashboard);
+            Doc.MyRecentlyClosed && Doc.AddDocToList(Doc.MyRecentlyClosed, 'data', dashboard, undefined, true, true);
             if (!dashboards.length) Doc.ActivePage = 'home';
         }, 'remove dashboard')();
     };
@@ -409,7 +409,7 @@ export class DashboardView extends ObservableReactComponent<object> {
     };
 
     public static createNewDashboard = (id?: string, name?: string, background?: string) => {
-        const dashboardCount = DocListCast(Doc.MyDashboards.data).length + 1;
+        const dashboardCount = DocListCast(Doc.MyDashboards?.data).length + 1;
         const freeformOptions: DocumentOptions = {
             x: 0,
             y: 400,
@@ -425,8 +425,8 @@ export class DashboardView extends ObservableReactComponent<object> {
         const freeformDoc = Doc.GuestTarget || Docs.Create.FreeformDocument([], freeformOptions);
         const dashboardDoc = DashboardView.StandardCollectionDockingDocument([{ doc: freeformDoc, initialWidth: 600 }], { title: title }, id, 'row');
 
-        Doc.AddDocToList(Doc.MyHeaderBar, 'data', freeformDoc, undefined, undefined, true);
-        Doc.AddDocToList(Doc.MyDashboards, 'data', dashboardDoc);
+        Doc.MyHeaderBar && Doc.AddDocToList(Doc.MyHeaderBar, 'data', freeformDoc, undefined, undefined, true);
+        Doc.MyDashboards && Doc.AddDocToList(Doc.MyDashboards, 'data', dashboardDoc);
         freeformDoc._embedContainer = dashboardDoc;
         dashboardDoc.$myPaneCount = 1;
         dashboardDoc.$myOverlayDocs = new List<Doc>();
diff --git a/src/client/views/InkStrokeProperties.ts b/src/client/views/InkStrokeProperties.ts
index 425f5b6bb..41f38c008 100644
--- a/src/client/views/InkStrokeProperties.ts
+++ b/src/client/views/InkStrokeProperties.ts
@@ -99,7 +99,7 @@ export class InkStrokeProperties {
             controls.splice(i, 4, ...splicepts.map(p => ({ X: p.x, Y: p.y })));
 
             // Updating the indices of the control points whose handle tangency has been broken.
-            doc.brokenInkIndices = new List(Cast(doc.brokenInkIndices, listSpec('number'), []).map(control => (control > i ? control + 4 : control)));
+            doc.brokenInkIndices = new List(NumListCast(doc.brokenInkIndices).map(control => (control > i ? control + 4 : control)));
             runInAction(() => {
                 this._currentPoint = -1;
             });
@@ -252,7 +252,7 @@ export class InkStrokeProperties {
             this.applyFunction(inkView, (view: DocumentView, ink: InkData) => {
                 const order = controlIndex % 4;
                 const closed = InkingStroke.IsClosed(ink);
-                const brokenIndices = Cast(inkView.Document.brokenInkIndices, listSpec('number'), []);
+                const brokenIndices = NumListCast(inkView.Document.brokenInkIndices);
                 if (origInk && this._currentPoint > 0 && this._currentPoint < ink.length - 1 && brokenIndices.findIndex(value => value === controlIndex) === -1) {
                     const cptBefore = ink[controlIndex];
                     const cpt = { X: cptBefore.X + deltaX, Y: cptBefore.Y + deltaY };
@@ -405,9 +405,9 @@ export class InkStrokeProperties {
         this.applyFunction(inkView, (view: DocumentView, ink: InkData) => {
             const doc = view.Document;
             const brokenIndices = Cast(doc.brokenInkIndices, listSpec('number'), []);
-            const ind = brokenIndices.findIndex(value => value === controlIndex);
+            const ind = brokenIndices?.findIndex(value => value === controlIndex) ?? -1;
             if (ind !== -1) {
-                brokenIndices.splice(ind, 1);
+                brokenIndices!.splice(ind, 1);
                 const [controlPoint, handleA, handleB] = [ink[controlIndex], ink[handleIndexA], ink[handleIndexB]];
                 const oppositeHandleA = this.rotatePoint(handleA, controlPoint, Math.PI);
                 const angleDifference = InkStrokeProperties.angleChange(handleB, oppositeHandleA, controlPoint);
diff --git a/src/client/views/InkingStroke.tsx b/src/client/views/InkingStroke.tsx
index 0a49ea28e..0136f6abe 100644
--- a/src/client/views/InkingStroke.tsx
+++ b/src/client/views/InkingStroke.tsx
@@ -26,8 +26,8 @@ import { observer } from 'mobx-react';
 import * as React from 'react';
 import { DashColor, returnFalse, setupMoveUpEvents } from '../../ClientUtils';
 import { Doc } from '../../fields/Doc';
-import { InkData, InkField } from '../../fields/InkField';
-import { BoolCast, Cast, NumCast, RTFCast, StrCast } from '../../fields/Types';
+import { InkData } from '../../fields/InkField';
+import { BoolCast, InkCast, NumCast, RTFCast, StrCast } from '../../fields/Types';
 import { TraceMobx } from '../../fields/util';
 import { Gestures } from '../../pen-gestures/GestureTypes';
 import { Docs } from '../documents/Documents';
@@ -35,6 +35,7 @@ import { DocumentType } from '../documents/DocumentTypes';
 import { InteractionUtils } from '../util/InteractionUtils';
 import { SnappingManager } from '../util/SnappingManager';
 import { UndoManager } from '../util/UndoManager';
+import { CollectionFreeFormView } from './collections/collectionFreeForm';
 import { ContextMenu } from './ContextMenu';
 import { ViewBoxAnnotatableComponent } from './DocComponent';
 import { Colors } from './global/globalEnums';
@@ -42,14 +43,13 @@ import { InkControlPtHandles, InkEndPtHandles } from './InkControlPtHandles';
 import './InkStroke.scss';
 import { InkStrokeProperties } from './InkStrokeProperties';
 import { InkTangentHandles } from './InkTangentHandles';
+import { InkTranscription } from './InkTranscription';
+import { DocumentView } from './nodes/DocumentView';
 import { FieldView, FieldViewProps } from './nodes/FieldView';
 import { FormattedTextBox, FormattedTextBoxProps } from './nodes/formattedText/FormattedTextBox';
 import { PinDocView, PinProps } from './PinFuncs';
 import { StyleProp } from './StyleProp';
 import { ViewBoxInterface } from './ViewBoxInterface';
-import { InkTranscription } from './InkTranscription';
-import { CollectionFreeFormView } from './collections/collectionFreeForm';
-import { DocumentView } from './nodes/DocumentView';
 
 // eslint-disable-next-line @typescript-eslint/no-require-imports
 const { INK_MASK_SIZE } = require('./global/globalCssVariables.module.scss'); // prettier-ignore
@@ -245,7 +245,7 @@ export class InkingStroke extends ViewBoxAnnotatableComponent<FieldViewProps>()
      * factor for converting between ink and screen space.
      */
     inkScaledData = () => {
-        const inkData = Cast(this.dataDoc[this.fieldKey], InkField, Cast(this.layoutDoc[this.fieldKey], InkField, null) ?? null)?.inkData ?? [];
+        const inkData = InkCast(this.dataDoc[this.fieldKey], InkCast(this.layoutDoc[this.fieldKey]) ?? null)?.inkData ?? [];
         const inkStrokeWidth = NumCast(this.layoutDoc.stroke_width, 1);
         const inkTop = Math.min(...inkData.map(p => p.Y)) - inkStrokeWidth / 2;
         const inkBottom = Math.max(...inkData.map(p => p.Y)) + inkStrokeWidth / 2;
diff --git a/src/client/views/PropertiesButtons.tsx b/src/client/views/PropertiesButtons.tsx
index 66936c64c..28566ba1d 100644
--- a/src/client/views/PropertiesButtons.tsx
+++ b/src/client/views/PropertiesButtons.tsx
@@ -385,18 +385,19 @@ export class PropertiesButtons extends React.Component {
             const followLoc = this.selectedDoc._followLinkLocation;
             const linkedToLightboxView = () => Doc.Links(this.selectedDoc).some(link => Doc.getOppositeAnchor(link, this.selectedDoc)?._isLightbox);
 
-            let active = false;
-            // prettier-ignore
-            switch (value[0]) {
-                case 'linkInPlace': active = linkButton && followLoc === OpenWhere.lightbox && !linkedToLightboxView();  break;
-                case 'linkOnRight': active = linkButton && followLoc === OpenWhere.addRight; break;
-                case 'enterPortal': active = linkButton && this.selectedDoc._followLinkLocation === OpenWhere.lightbox && linkedToLightboxView(); break;
-                case 'toggleDetail':active = ScriptCast(this.selectedDoc.onClick)?.script.originalScript.includes('toggleDetail'); break;
-                case 'nothing':     active = !linkButton && this.selectedDoc.onClick === undefined;break;
-                default:
-            }
+            const active = () => {
+                // prettier-ignore
+                switch (value[0]) {
+                    case 'linkInPlace': return linkButton && followLoc === OpenWhere.lightbox && !linkedToLightboxView();  break;
+                    case 'linkOnRight': return linkButton && followLoc === OpenWhere.addRight; break;
+                    case 'enterPortal': return linkButton && this.selectedDoc._followLinkLocation === OpenWhere.lightbox && linkedToLightboxView(); break;
+                    case 'toggleDetail':return ScriptCast(this.selectedDoc.onClick)?.script.originalScript.includes('toggleDetail'); break;
+                    case 'nothing':    return !linkButton && this.selectedDoc.onClick === undefined;break;
+                    default: return false;
+                }
+            };
             return (
-                <div className="list-item" key={`${value}`} style={{ backgroundColor: active ? Colors.LIGHT_BLUE : undefined }} onClick={click}>
+                <div className="list-item" key={`${value}`} style={{ backgroundColor: active() ? Colors.LIGHT_BLUE : undefined }} onClick={click}>
                     {value[1]}
                 </div>
             );
diff --git a/src/client/views/PropertiesDocBacklinksSelector.tsx b/src/client/views/PropertiesDocBacklinksSelector.tsx
index e30d14eae..5a00e6a89 100644
--- a/src/client/views/PropertiesDocBacklinksSelector.tsx
+++ b/src/client/views/PropertiesDocBacklinksSelector.tsx
@@ -1,18 +1,16 @@
-/* eslint-disable react/require-default-props */
-/* eslint-disable react/no-unused-prop-types */
 import { action } from 'mobx';
 import { observer } from 'mobx-react';
 import * as React from 'react';
 import { Doc } from '../../fields/Doc';
-import { Cast } from '../../fields/Types';
+import { DocCast } from '../../fields/Types';
 import { DocumentType } from '../documents/DocumentTypes';
 import { LinkManager } from '../util/LinkManager';
 import { SettingsManager } from '../util/SettingsManager';
 import './PropertiesDocBacklinksSelector.scss';
 import { CollectionDockingView } from './collections/CollectionDockingView';
 import { LinkMenu } from './linking/LinkMenu';
-import { OpenWhere } from './nodes/OpenWhere';
 import { DocumentView } from './nodes/DocumentView';
+import { OpenWhere } from './nodes/OpenWhere';
 
 type PropertiesDocBacklinksSelectorProps = {
     Document: Doc;
@@ -26,7 +24,7 @@ export class PropertiesDocBacklinksSelector extends React.Component<PropertiesDo
     getOnClick = action((link: Doc) => {
         const linkAnchor = this.props.Document;
         const other = Doc.getOppositeAnchor(link, linkAnchor);
-        const otherdoc = !other ? undefined : other.annotationOn && other.type !== DocumentType.RTF ? Cast(other.annotationOn, Doc, null) : other;
+        const otherdoc = !other ? undefined : other.annotationOn && other.type !== DocumentType.RTF ? DocCast(other.annotationOn) : other;
         LinkManager.Instance.currentLink = link;
         if (otherdoc) {
             otherdoc.hidden = false;
diff --git a/src/client/views/PropertiesDocContextSelector.tsx b/src/client/views/PropertiesDocContextSelector.tsx
index ee6486a9c..1aa956e16 100644
--- a/src/client/views/PropertiesDocContextSelector.tsx
+++ b/src/client/views/PropertiesDocContextSelector.tsx
@@ -3,7 +3,7 @@ import { observer } from 'mobx-react';
 import * as React from 'react';
 import { Doc } from '../../fields/Doc';
 import { Id } from '../../fields/FieldSymbols';
-import { Cast, StrCast } from '../../fields/Types';
+import { DocCast, StrCast } from '../../fields/Types';
 import { ObservableReactComponent } from './ObservableReactComponent';
 import './PropertiesDocContextSelector.scss';
 import { CollectionDockingView } from './collections/CollectionDockingView';
@@ -29,7 +29,7 @@ export class PropertiesDocContextSelector extends ObservableReactComponent<Prope
         const target = this._props.DocView.Document;
         const targetContext = this._props.DocView.containerViewPath?.().lastElement()?.Document;
         const embeddings = Doc.GetEmbeddings(target);
-        const containerProtos = embeddings.filter(embedding => embedding.embedContainer && embedding.embedContainer instanceof Doc).reduce((set, embedding) => set.add(Cast(embedding.embedContainer, Doc, null)), new Set<Doc>());
+        const containerProtos = embeddings.filter(embedding => DocCast(embedding.embedContainer)).reduce((set, embedding) => set.add(DocCast(embedding.embedContainer)!), new Set<Doc>());
         const containerSets = Array.from(containerProtos.keys()).map(container => (Doc.GetEmbeddings(container).length ? Doc.GetEmbeddings(container) : [container]));
         const containers = containerSets.reduce((p, set) => {
             set.map(s => p.add(s));
diff --git a/src/client/views/UndoStack.tsx b/src/client/views/UndoStack.tsx
index 32b97b31a..067020a62 100644
--- a/src/client/views/UndoStack.tsx
+++ b/src/client/views/UndoStack.tsx
@@ -7,9 +7,8 @@ import { SettingsManager } from '../util/SettingsManager';
 import { UndoManager } from '../util/UndoManager';
 import './UndoStack.scss';
 
-interface UndoStackProps {}
 @observer
-export class UndoStack extends React.Component<UndoStackProps> {
+export class UndoStack extends React.Component<object> {
     render() {
         const background = UndoManager.batchCounter.get() ? 'yellow' : SettingsManager.userVariantColor;
         const color = UndoManager.batchCounter.get() ? 'black' : SettingsManager.userColor;
@@ -34,7 +33,6 @@ export class UndoStack extends React.Component<UndoStackProps> {
                                     {Array.from(UndoManager.undoStackNames).map((name, i) => (
                                         <div
                                             className="undoStack-resultContainer"
-                                            // eslint-disable-next-line react/no-array-index-key
                                             key={i}
                                             onClick={() => {
                                                 const size = UndoManager.undoStackNames.length;
@@ -48,7 +46,6 @@ export class UndoStack extends React.Component<UndoStackProps> {
                                         .map((name, i) => (
                                             <div
                                                 className="undoStack-resultContainer"
-                                                // eslint-disable-next-line react/no-array-index-key
                                                 key={i}
                                                 onClick={() => {
                                                     for (let n = 0; n <= i; n++) UndoManager.Redo();
diff --git a/src/client/views/animationtimeline/Region.tsx b/src/client/views/animationtimeline/Region.tsx
index 99163f6c6..40fcb2bf6 100644
--- a/src/client/views/animationtimeline/Region.tsx
+++ b/src/client/views/animationtimeline/Region.tsx
@@ -12,6 +12,18 @@ import './Region.scss';
 import './Timeline.scss';
 import { TimelineMenu } from './TimelineMenu';
 
+export const RegionDataSchema = createSchema({
+    position: defaultSpec('number', 0),
+    duration: defaultSpec('number', 0),
+    keyframes: listSpec(Doc),
+    fadeIn: defaultSpec('number', 0),
+    fadeOut: defaultSpec('number', 0),
+    functions: listSpec(Doc),
+    hasData: defaultSpec('boolean', false),
+});
+export type RegionData = makeInterface<[typeof RegionDataSchema]>;
+export const RegionData = makeInterface(RegionDataSchema);
+
 /**
  * Useful static functions that you can use. Mostly for logic, but you can also add UI logic here also
  */
@@ -108,18 +120,6 @@ export namespace RegionHelpers {
     };
 }
 
-export const RegionDataSchema = createSchema({
-    position: defaultSpec('number', 0),
-    duration: defaultSpec('number', 0),
-    keyframes: listSpec(Doc),
-    fadeIn: defaultSpec('number', 0),
-    fadeOut: defaultSpec('number', 0),
-    functions: listSpec(Doc),
-    hasData: defaultSpec('boolean', false),
-});
-export type RegionData = makeInterface<[typeof RegionDataSchema]>;
-export const RegionData = makeInterface(RegionDataSchema);
-
 interface IProps {
     animatedDoc: Doc;
     RegionData: Doc;
@@ -184,7 +184,7 @@ export class Region extends ObservableReactComponent<IProps> {
         return RegionHelpers.convertPixelTime(this.regiondata.fadeOut, 'mili', 'pixel', this._props.tickSpacing, this._props.tickIncrement);
     }
 
-    constructor(props: any) {
+    constructor(props: IProps) {
         super(props);
         makeObservable(this);
     }
@@ -220,9 +220,7 @@ export class Region extends ObservableReactComponent<IProps> {
             }, 200);
             this._doubleClickEnabled = true;
             document.addEventListener('pointermove', this.onBarPointerMove);
-            document.addEventListener('pointerup', (e: PointerEvent) => {
-                document.removeEventListener('pointermove', this.onBarPointerMove);
-            });
+            document.addEventListener('pointerup', () => document.removeEventListener('pointermove', this.onBarPointerMove));
         }
     };
 
@@ -426,6 +424,7 @@ export class Region extends ObservableReactComponent<IProps> {
                         .map(region => ({ pos: NumCast(region.position), dur: NumCast(region.duration) }))
                         .forEach(({ pos, dur }) => {
                             if (pos !== this.regiondata.position) {
+                                // eslint-disable-next-line no-param-reassign
                                 val += this.regiondata.position;
                                 if (val < 0 || (val > pos && val < pos + dur)) {
                                     cannotMove = true;
@@ -483,7 +482,6 @@ export class Region extends ObservableReactComponent<IProps> {
      * this probably needs biggest change, since everyone expected all keyframes to have a circle (and draggable)
      */
     drawKeyframes = () => {
-        const keyframeDivs: JSX.Element[] = [];
         return DocListCast(this.regiondata.keyframes).map(kf => {
             return (
                 <>
diff --git a/src/client/views/animationtimeline/Track.tsx b/src/client/views/animationtimeline/Track.tsx
index 1e4ed74be..dea7b6aae 100644
--- a/src/client/views/animationtimeline/Track.tsx
+++ b/src/client/views/animationtimeline/Track.tsx
@@ -1,4 +1,4 @@
-import { action, computed, intercept, makeObservable, observable, reaction, runInAction } from 'mobx';
+import { action, computed, intercept, IReactionDisposer, makeObservable, observable, reaction, runInAction } from 'mobx';
 import { observer } from 'mobx-react';
 import * as React from 'react';
 import { Doc, DocListCast, DocListCastAsync, Opt } from '../../../fields/Doc';
@@ -6,7 +6,7 @@ import { Copy } from '../../../fields/FieldSymbols';
 import { List } from '../../../fields/List';
 import { ObjectField } from '../../../fields/ObjectField';
 import { listSpec } from '../../../fields/Schema';
-import { Cast, NumCast } from '../../../fields/Types';
+import { Cast, DocCast, NumCast } from '../../../fields/Types';
 import { Transform } from '../../util/Transform';
 import { ObservableReactComponent } from '../ObservableReactComponent';
 import { Region, RegionData, RegionHelpers } from './Region';
@@ -29,16 +29,16 @@ interface IProps {
 @observer
 export class Track extends ObservableReactComponent<IProps> {
     @observable private _inner = React.createRef<HTMLDivElement>();
-    @observable private _currentBarXReaction: any = undefined;
-    @observable private _timelineVisibleReaction: any = undefined;
-    @observable private _autoKfReaction: any = undefined;
+    @observable private _currentBarXReaction: IReactionDisposer | undefined = undefined;
+    @observable private _timelineVisibleReaction: IReactionDisposer | undefined = undefined;
+    @observable private _autoKfReaction: IReactionDisposer | undefined = undefined;
     @observable private _newKeyframe: boolean = false;
     private readonly MAX_TITLE_HEIGHT = 75;
     @observable private _trackHeight = 0;
     private primitiveWhitelist = ['x', 'y', '_freeform_panX', '_freeform_panY', '_width', '_height', '_rotation', 'opacity', '_layout_scrollTop'];
     private objectWhitelist = ['data'];
 
-    constructor(props: any) {
+    constructor(props: IProps) {
         super(props);
         makeObservable(this);
     }
@@ -101,11 +101,11 @@ export class Track extends ObservableReactComponent<IProps> {
         }
         const keyframes = Cast(this.saveStateRegion.keyframes, listSpec(Doc)) as List<Doc>;
         const kfIndex = keyframes.indexOf(this.saveStateKf);
-        const kf = keyframes[kfIndex] as Doc; //index in the keyframe
+        const kf = DocCast(keyframes[kfIndex]); //index in the keyframe
         if (this._newKeyframe) {
-            DocListCast(this.saveStateRegion.keyframes).forEach((kf, index) => {
-                this.copyDocDataToKeyFrame(kf);
-                kf.opacity = index === 0 || index === 3 ? 0.1 : 1;
+            DocListCast(this.saveStateRegion.keyframes).forEach((keyF, index) => {
+                this.copyDocDataToKeyFrame(keyF);
+                keyF.opacity = index === 0 || index === 3 ? 0.1 : 1;
             });
             this._newKeyframe = false;
         }
@@ -144,7 +144,7 @@ export class Track extends ObservableReactComponent<IProps> {
             () => {
                 return [...this.primitiveWhitelist.map(key => this._props.animatedDoc[key]), ...objects];
             },
-            (changed, reaction) => {
+            (/* changed, reaction */) => {
                 //check for region
                 const region = this.findRegion(this.time);
                 if (region !== undefined) {
@@ -374,7 +374,7 @@ export class Track extends ObservableReactComponent<IProps> {
 
     @action
     copyDocDataToKeyFrame = (doc: Doc) => {
-        var somethingChanged = false;
+        let somethingChanged = false;
         this.primitiveWhitelist.map(key => {
             const originalVal = this._props.animatedDoc[key];
             somethingChanged = somethingChanged || originalVal !== doc[key];
diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx
index 1576a8e4a..7f835938b 100644
--- a/src/client/views/collections/CollectionMenu.tsx
+++ b/src/client/views/collections/CollectionMenu.tsx
@@ -46,7 +46,7 @@ export class CollectionMenu extends AntimodeMenu<CollectionMenuProps> {
         makeObservable(this);
         CollectionMenu.Instance = this;
         this._canFade = false; // don't let the inking menu fade away
-        this.Pinned = Cast(Doc.UserDoc().menuCollections_pinned, 'boolean', true);
+        this.Pinned = BoolCast(Doc.UserDoc().menuCollections_pinned, true);
         this.jumpTo(300, 300);
     }
 
@@ -269,7 +269,7 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewMenu
         initialize: (button: Doc) => {
             const activeDash = Doc.ActiveDashboard;
             if (activeDash) {
-                button.target_childFilters = (Doc.MySearcher._childFilters || activeDash._childFilters) instanceof ObjectField ? ObjectField.MakeCopy((Doc.MySearcher._childFilters || activeDash._childFilters) as ObjectField) : undefined;
+                button.target_childFilters = (Doc.MySearcher?._childFilters || activeDash._childFilters) instanceof ObjectField ? ObjectField.MakeCopy((Doc.MySearcher?._childFilters || activeDash._childFilters) as ObjectField) : undefined;
                 button.target_searchFilterDocs = activeDash._searchFilterDocs instanceof ObjectField ? ObjectField.MakeCopy(activeDash._searchFilterDocs) : undefined;
             }
         },
diff --git a/src/client/views/collections/CollectionNoteTakingViewColumn.tsx b/src/client/views/collections/CollectionNoteTakingViewColumn.tsx
index f283b0abe..461689a70 100644
--- a/src/client/views/collections/CollectionNoteTakingViewColumn.tsx
+++ b/src/client/views/collections/CollectionNoteTakingViewColumn.tsx
@@ -155,7 +155,7 @@ export class CollectionNoteTakingViewColumn extends ObservableReactComponent<CSV
     // all docs are added to the column directly to the left.
     @undoBatch
     deleteColumn = () => {
-        const colHdrData = Array.from(Cast(this._props.Doc[this._props.fieldKey + '_columnHeaders'], listSpec(SchemaHeaderField), null));
+        const colHdrData = Array.from(Cast(this._props.Doc[this._props.fieldKey + '_columnHeaders'], listSpec(SchemaHeaderField), [])!);
         if (this._props.headingObject) {
             //          this._props.docList.forEach(d => (d['$'+this._props.pivotField] = undefined));
             colHdrData.splice(colHdrData.indexOf(this._props.headingObject), 1);
diff --git a/src/client/views/collections/CollectionPileView.tsx b/src/client/views/collections/CollectionPileView.tsx
index eea128803..5a85c8ee3 100644
--- a/src/client/views/collections/CollectionPileView.tsx
+++ b/src/client/views/collections/CollectionPileView.tsx
@@ -67,7 +67,6 @@ export class CollectionPileView extends CollectionSubView() {
         return (
             <div className="collectionPileView-innards" style={{ pointerEvents: this.contentEvents }}>
                 <CollectionFreeFormView
-                    // eslint-disable-next-line react/jsx-props-no-spreading
                     {...this._props} //
                     layoutEngine={this.layoutEngine}
                     addDocument={this.addPileDoc}
diff --git a/src/client/views/collections/CollectionStackedTimeline.tsx b/src/client/views/collections/CollectionStackedTimeline.tsx
index fd4bdf364..4e7e19548 100644
--- a/src/client/views/collections/CollectionStackedTimeline.tsx
+++ b/src/client/views/collections/CollectionStackedTimeline.tsx
@@ -435,7 +435,7 @@ export class CollectionStackedTimeline extends CollectionSubView<CollectionStack
         anchor['$' + endTag] = anchorEndTime;
         if (addAsAnnotation) {
             if (Cast(dataDoc[fieldKey], listSpec(Doc), null)) {
-                Cast(dataDoc[fieldKey], listSpec(Doc), []).push(anchor);
+                Cast(dataDoc[fieldKey], listSpec(Doc), [])!.push(anchor);
             } else {
                 dataDoc[fieldKey] = new List<Doc>([anchor]);
             }
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index 3497a62cb..bee5d016d 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -137,7 +137,7 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
         if (res && de.complete.docDragData) {
             if (this.Document !== Doc.MyRecentlyClosed)
                 de.complete.docDragData.droppedDocuments.forEach(doc => {
-                    if (this.Document !== Doc.MyRecentlyClosed) Doc.RemoveDocFromList(Doc.MyRecentlyClosed, undefined, doc);
+                    if (this.Document !== Doc.MyRecentlyClosed) Doc.MyRecentlyClosed && Doc.RemoveDocFromList(Doc.MyRecentlyClosed, undefined, doc);
                 });
         }
         return res;
@@ -193,7 +193,7 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
         res &&
             doclist.forEach(doc => {
                 Doc.SetContainer(doc, this.Document);
-                if (this.Document !== Doc.MyRecentlyClosed) Doc.RemoveDocFromList(Doc.MyRecentlyClosed, undefined, doc);
+                if (this.Document !== Doc.MyRecentlyClosed) Doc.MyRecentlyClosed && Doc.RemoveDocFromList(Doc.MyRecentlyClosed, undefined, doc);
             });
         return res;
     };
@@ -273,8 +273,8 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
         );
     }
     childContextMenuItems = () => {
-        const customScripts = Cast(this.Document.childContextMenuScripts, listSpec(ScriptField), []);
-        const customFilters = Cast(this.Document.childContextMenuFilters, listSpec(ScriptField), []);
+        const customScripts = Cast(this.Document.childContextMenuScripts, listSpec(ScriptField), [])!;
+        const customFilters = Cast(this.Document.childContextMenuFilters, listSpec(ScriptField), [])!;
         const icons = StrListCast(this.Document.childContextMenuIcons);
         return StrListCast(this.Document.childContextMenuLabels).map((label, i) => ({ script: customScripts[i], filter: customFilters[i], icon: icons[i], label }));
     };
diff --git a/src/client/views/collections/FlashcardPracticeUI.tsx b/src/client/views/collections/FlashcardPracticeUI.tsx
index f24a8acb7..2f46c00bd 100644
--- a/src/client/views/collections/FlashcardPracticeUI.tsx
+++ b/src/client/views/collections/FlashcardPracticeUI.tsx
@@ -60,7 +60,7 @@ export class FlashcardPracticeUI extends ObservableReactComponent<PracticeUIProp
 
     get practiceField() { return this._props.fieldKey + "_practice"; } // prettier-ignore
 
-    @computed get filterDoc() { return DocListCast(Doc.MyContextMenuBtns.data).find(doc => doc.title === 'Filter'); } // prettier-ignore
+    @computed get filterDoc() { return DocListCast(Doc.MyContextMenuBtns?.data).find(doc => doc.title === 'Filter'); } // prettier-ignore
     @computed get practiceMode() {  return this._props.allChildDocs().some(doc => doc._layout_flashcardType) ? StrCast(this._props.layoutDoc.practiceMode) : ''; } // prettier-ignore
 
     btnHeight = () => NumCast(this.filterDoc?.height);
diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx
index 4beb75074..fb2d0955f 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -70,7 +70,7 @@ export interface TreeViewProps {
     treeViewHideHeaderFields: () => boolean;
     renderedIds: string[]; // list of document ids rendered used to avoid unending expansion of items in a cycle
     onCheckedClick?: () => ScriptField;
-    onChildClick?: () => ScriptField;
+    onChildClick?: () => ScriptField | undefined;
     skipFields?: string[];
     firstLevel: boolean;
     // TODO: [AL] add these
@@ -1268,7 +1268,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
         treeViewHideHeaderFields: () => boolean,
         renderedIds: string[],
         onCheckedClick: undefined | (() => ScriptField),
-        onChildClick: undefined | (() => ScriptField),
+        onChildClick: undefined | (() => ScriptField | undefined),
         skipFields: string[] | undefined,
         firstLevel: boolean,
         whenChildContentsActiveChanged: (isActive: boolean) => void,
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx
index 158bac7ba..4d17dedfb 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx
@@ -108,7 +108,7 @@ export function computePassLayout(poolData: Map<string, PoolData>, pivotDoc: Doc
 }
 
 function toNumber(val: FieldResult<FieldType>) {
-    return val === undefined ? undefined : DateCast(val) ? DateCast(val).date.getTime() : NumCast(val, Number(StrCast(val)));
+    return val === undefined ? undefined : DateCast(val) ? DateCast(val)!.date.getTime() : NumCast(val, Number(StrCast(val)));
 }
 
 export function computeStarburstLayout(poolData: Map<string, PoolData>, pivotDoc: Doc, childPairs: { layout: Doc; data?: Doc }[], panelDim: number[], viewDefsToJSX: (views: ViewDefBounds[]) => ViewDefResult[] /* , engineProps: any */) {
diff --git a/src/client/views/collections/collectionFreeForm/FaceCollectionBox.tsx b/src/client/views/collections/collectionFreeForm/FaceCollectionBox.tsx
index 72485aa86..ad05a798b 100644
--- a/src/client/views/collections/collectionFreeForm/FaceCollectionBox.tsx
+++ b/src/client/views/collections/collectionFreeForm/FaceCollectionBox.tsx
@@ -106,7 +106,7 @@ export class UniqueFaceBox extends ViewBoxBaseComponent<FieldViewProps>() {
 
                     // assign the face in the image that's closest to the face collection's face
                     if (faceAnno) {
-                        faceAnno.face && FaceRecognitionHandler.UniqueFaceRemoveFaceImage(faceAnno, DocCast(faceAnno.face));
+                        DocCast(faceAnno.face) && FaceRecognitionHandler.UniqueFaceRemoveFaceImage(faceAnno, DocCast(faceAnno.face)!);
                         FaceRecognitionHandler.UniqueFaceAddFaceImage(faceAnno, this.Document);
                         faceAnno.$face = this.Document[DocData];
                     }
@@ -116,7 +116,7 @@ export class UniqueFaceBox extends ViewBoxBaseComponent<FieldViewProps>() {
             ?.filter(doc => DocCast(doc.face)?.type === DocumentType.UFACE)
             .forEach(faceAnno => {
                 const imgDoc = faceAnno;
-                faceAnno.face && FaceRecognitionHandler.UniqueFaceRemoveFaceImage(imgDoc, DocCast(faceAnno.face));
+                DocCast(faceAnno.face) && FaceRecognitionHandler.UniqueFaceRemoveFaceImage(imgDoc, DocCast(faceAnno.face)!);
                 FaceRecognitionHandler.UniqueFaceAddFaceImage(faceAnno, this.Document);
                 faceAnno.$face = this.Document[DocData];
             });
@@ -187,7 +187,7 @@ export class UniqueFaceBox extends ViewBoxBaseComponent<FieldViewProps>() {
                             ele?.addEventListener('wheel', this.onPassiveWheel, { passive: false });
                         })}>
                         {FaceRecognitionHandler.UniqueFaceImages(this.Document).map((doc, i) => {
-                            const [name, type] = ImageCastToNameType(doc[Doc.LayoutDataKey(doc)]) ?? ['-missing-', '.png'];
+                            const [name, type] = ImageCastToNameType(doc?.[Doc.LayoutDataKey(doc)]) ?? ['-missing-', '.png'];
                             return (
                                 <div
                                     className="image-wrapper"
@@ -197,7 +197,7 @@ export class UniqueFaceBox extends ViewBoxBaseComponent<FieldViewProps>() {
                                             this,
                                             e,
                                             () => {
-                                                const dragDoc = DocListCast(doc.data_annotations).find(a => a.face === this.Document[DocData]) ?? this.Document;
+                                                const dragDoc = DocListCast(doc?.data_annotations).find(a => a.face === this.Document[DocData]) ?? this.Document;
                                                 DragManager.StartDocumentDrag([e.target as HTMLElement], new DragManager.DocumentDragData([dragDoc], dropActionType.embed), e.clientX, e.clientY);
                                                 return true;
                                             },
@@ -205,7 +205,7 @@ export class UniqueFaceBox extends ViewBoxBaseComponent<FieldViewProps>() {
                                             emptyFunction
                                         )
                                     }>
-                                    <img onClick={() => DocumentView.showDocument(doc, { willZoomCentered: true })} style={{ maxWidth: '60px', margin: '10px' }} src={`${name}_o.${type}`} />
+                                    <img onClick={() => doc && DocumentView.showDocument(doc, { willZoomCentered: true })} style={{ maxWidth: '60px', margin: '10px' }} src={`${name}_o.${type}`} />
                                     <div className="remove-item">
                                         <IconButton tooltip={'Remove Doc From Face Collection'} onPointerDown={() => this.removeFaceImageFromUniqueFace(doc)} icon={'x'} style={{ width: '4px' }} size={Size.XSMALL} />
                                     </div>
@@ -239,11 +239,12 @@ export class FaceCollectionBox extends ViewBoxBaseComponent<FieldViewProps>() {
     }
 
     moveDocument = (doc: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (doc: Doc | Doc[]) => boolean): boolean => !!(this._props.removeDocument?.(doc) && addDocument?.(doc));
+    // eslint-disable-next-line @typescript-eslint/no-unused-vars
     addDocument = (doc: Doc | Doc[], annotationKey?: string) => {
         const uniqueFaceDoc = doc instanceof Doc ? doc : doc[0];
         const added = uniqueFaceDoc.type === DocumentType.UFACE;
         if (added) {
-            Doc.SetContainer(uniqueFaceDoc, Doc.MyFaceCollection);
+            Doc.MyFaceCollection && Doc.SetContainer(uniqueFaceDoc, Doc.MyFaceCollection);
             Doc.ActiveDashboard && Doc.AddDocToList(Doc.ActiveDashboard[DocData], 'myUniqueFaces', uniqueFaceDoc);
         }
         return added;
diff --git a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx
index 81a2d8e64..16d33eb93 100644
--- a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx
@@ -107,7 +107,7 @@ export class SchemaColumnHeader extends ObservableReactComponent<SchemaColumnHea
             focus: emptyFunction,
             addDocTab: SchemaTableCell.addFieldDoc,
             pinToPres: returnZero,
-            Document: DocCast(Document.rootDocument, Document),
+            Document: DocCast(Document.rootDocument, Document)!,
             fieldKey: fieldKey,
             PanelWidth: columnWidth,
             PanelHeight: props.rowHeight,
diff --git a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
index 8e1edc1ee..8b34b4139 100644
--- a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
@@ -106,7 +106,7 @@ export class SchemaTableCell extends ObservableReactComponent<SchemaTableCellPro
         const { Doc: Document, fieldKey, /* getFinfo,*/ columnWidth, isRowActive } = props;
         let protoCount = 0;
         const layoutDoc = fieldKey.startsWith('_') ? Document[DocLayout] : Document;
-        let doc = Document;
+        let doc: Doc | undefined = Document;
         while (doc) {
             if (Object.keys(doc).includes(fieldKey.replace(/^_/, ''))) break;
             protoCount++;
@@ -168,9 +168,11 @@ export class SchemaTableCell extends ObservableReactComponent<SchemaTableCellPro
         while ((matches = idPattern.exec(field)) !== null) {
             results.push([matches[0], matches[1].replace(/"/g, '')]);
         }
-        results.forEach(idFuncPair => {
-            modField = modField.replace(idFuncPair[0], 'd' + DocumentView.getDocViewIndex(IdToDoc(idFuncPair[1])).toString());
-        });
+        results
+            .filter(idFuncPair => IdToDoc(idFuncPair[1]))
+            .forEach(idFuncPair => {
+                modField = modField.replace(idFuncPair[0], 'd' + DocumentView.getDocViewIndex(IdToDoc(idFuncPair[1])!).toString());
+            });
 
         if (modField.endsWith(';')) modField = modField.substring(0, modField.length - 1);
 
@@ -328,7 +330,7 @@ export class SchemaImageCell extends ObservableReactComponent<SchemaTableCellPro
         const altpaths = alts
             .map(doc => Cast(doc[Doc.LayoutDataKey(doc)], ImageField, null)?.url)
             .filter(url => url)
-            .map(url => this.choosePath(url)); // access the primary layout data of the alternate documents
+            .map(url => this.choosePath(url!)); // access the primary layout data of the alternate documents
         const paths = field ? [this.choosePath(field.url), ...altpaths] : altpaths;
         // If there is a path, follow it; otherwise, follow a link to a default image icon
         const url = paths.length ? paths : [ClientUtils.CorsProxy('http://www.cs.brown.edu/~bcz/noImage.png')];
@@ -379,7 +381,7 @@ export class SchemaDateCell extends ObservableReactComponent<SchemaTableCellProp
     }
 
     @observable _pickingDate: boolean = false;
-    @computed get date(): DateField {
+    @computed get date(): DateField | undefined {
         // if the cell is a date field, cast then contents to a date. Otherrwwise, make the contents undefined.
         return DateCast(this._props.Doc[this._props.fieldKey]);
     }
@@ -399,7 +401,7 @@ export class SchemaDateCell extends ObservableReactComponent<SchemaTableCellProp
         return (
             <>
                 <div style={{ pointerEvents: 'none' }} tabIndex={1}>
-                    <DatePicker dateFormat="Pp" selected={this.date?.date ?? Date.now()} onChange={emptyFunction} />
+                    <DatePicker dateFormat="Pp" selected={this.date?.date ?? new Date()} onChange={emptyFunction} />
                 </div>
                 {pointerEvents === 'none' || !selectedCell(this._props) ? null : (
                     <Popup
@@ -410,7 +412,7 @@ export class SchemaDateCell extends ObservableReactComponent<SchemaTableCellProp
                         background={SnappingManager.userBackgroundColor}
                         popup={
                             <div style={{ width: 'fit-content', height: '200px' }}>
-                                <DatePicker open dateFormat="Pp" selected={this.date?.date ?? Date.now()} onChange={this.handleChange} />
+                                <DatePicker open dateFormat="Pp" selected={this.date?.date ?? new Date()} onChange={this.handleChange} />
                             </div>
                         }
                     />
diff --git a/src/client/views/linking/LinkMenuGroup.tsx b/src/client/views/linking/LinkMenuGroup.tsx
index c15508669..9eaf0e491 100644
--- a/src/client/views/linking/LinkMenuGroup.tsx
+++ b/src/client/views/linking/LinkMenuGroup.tsx
@@ -1,10 +1,9 @@
-/* eslint-disable react/require-default-props */
 import { action, observable } from 'mobx';
 import { observer } from 'mobx-react';
 import * as React from 'react';
 import { Doc, StrListCast } from '../../../fields/Doc';
 import { Id } from '../../../fields/FieldSymbols';
-import { Cast, DocCast } from '../../../fields/Types';
+import { DocCast } from '../../../fields/Types';
 import { DocumentType } from '../../documents/DocumentTypes';
 import { DocumentView } from '../nodes/DocumentView';
 import './LinkMenu.scss';
@@ -56,7 +55,7 @@ export class LinkMenuGroup extends React.Component<LinkMenuGroupProps> {
                   ? this.props.docView._props.LayoutTemplateString?.includes('link_anchor_1')
                       ? DocCast(linkDoc.link_anchor_2)
                       : DocCast(linkDoc.link_anchor_1)
-                  : Doc.getOppositeAnchor(linkDoc, sourceDoc) || Doc.getOppositeAnchor(linkDoc, Cast(linkDoc.link_anchor_2, Doc, null)?.annotationOn === sourceDoc ? Cast(linkDoc.link_anchor_2, Doc, null) : Cast(linkDoc.link_anchor_1, Doc, null));
+                  : Doc.getOppositeAnchor(linkDoc, sourceDoc) || Doc.getOppositeAnchor(linkDoc, DocCast(linkDoc.link_anchor_2)?.annotationOn === sourceDoc ? DocCast(linkDoc.link_anchor_2) : DocCast(linkDoc.link_anchor_1));
             return !destDoc || !sourceDoc ? null : (
                 <LinkMenuItem
                     key={linkDoc[Id]}
diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx
index 1c92c3b0d..c984a7053 100644
--- a/src/client/views/linking/LinkMenuItem.tsx
+++ b/src/client/views/linking/LinkMenuItem.tsx
@@ -68,8 +68,8 @@ export class LinkMenuItem extends ObservableReactComponent<LinkMenuItemProps> {
     @computed get sourceAnchor() {
         const ldoc = this._props.linkDoc;
         if (this._props.sourceDoc !== ldoc.link_anchor_1 && this._props.sourceDoc !== ldoc.link_anchor_2) {
-            if (Doc.AreProtosEqual(DocCast(DocCast(ldoc.link_anchor_1).annotationOn), this._props.sourceDoc)) return DocCast(ldoc.link_anchor_1);
-            if (Doc.AreProtosEqual(DocCast(DocCast(ldoc.link_anchor_2).annotationOn), this._props.sourceDoc)) return DocCast(ldoc.link_anchor_2);
+            if (Doc.AreProtosEqual(DocCast(DocCast(ldoc.link_anchor_1)?.annotationOn), this._props.sourceDoc)) return DocCast(ldoc.link_anchor_1);
+            if (Doc.AreProtosEqual(DocCast(DocCast(ldoc.link_anchor_2)?.annotationOn), this._props.sourceDoc)) return DocCast(ldoc.link_anchor_2);
         }
         return this._props.sourceDoc;
     }
diff --git a/src/client/views/newlightbox/ExploreView/ExploreView.tsx b/src/client/views/newlightbox/ExploreView/ExploreView.tsx
index f8c07cc43..7f9a13549 100644
--- a/src/client/views/newlightbox/ExploreView/ExploreView.tsx
+++ b/src/client/views/newlightbox/ExploreView/ExploreView.tsx
@@ -1,5 +1,3 @@
-/* eslint-disable jsx-a11y/no-static-element-interactions */
-/* eslint-disable jsx-a11y/click-events-have-key-events */
 import * as React from 'react';
 import { StrCast } from '../../../../fields/Types';
 import { NewLightboxView } from '../NewLightboxView';
@@ -19,7 +17,7 @@ export function ExploreView(props: IExploreView) {
                         const x = (rec.embedding.x / xBound) * 50;
                         const y = (rec.embedding.y / yBound) * 50;
                         return (
-                            <div className="exploreView-doc" onClick={() => {}} style={{ top: `calc(50% + ${y}%)`, left: `calc(50% + ${x}%)` }}>
+                            <div key={'' + x + ' ' + y} className="exploreView-doc" onClick={() => {}} style={{ top: `calc(50% + ${y}%)`, left: `calc(50% + ${x}%)` }}>
                                 {rec.title}
                             </div>
                         );
diff --git a/src/client/views/newlightbox/NewLightboxView.tsx b/src/client/views/newlightbox/NewLightboxView.tsx
index 87cef01d2..7ec45d0dd 100644
--- a/src/client/views/newlightbox/NewLightboxView.tsx
+++ b/src/client/views/newlightbox/NewLightboxView.tsx
@@ -5,7 +5,7 @@ import { returnEmptyFilter, returnTrue } from '../../../ClientUtils';
 import { emptyFunction } from '../../../Utils';
 import { CreateLinkToActiveAudio, Doc, DocListCast, Opt, returnEmptyDoclist } from '../../../fields/Doc';
 import { InkTool } from '../../../fields/InkField';
-import { Cast, NumCast, StrCast, toList } from '../../../fields/Types';
+import { Cast, DocCast, NumCast, StrCast, toList } from '../../../fields/Types';
 import { SnappingManager } from '../../util/SnappingManager';
 import { Transform } from '../../util/Transform';
 import { GestureOverlay } from '../GestureOverlay';
@@ -100,7 +100,7 @@ export class NewLightboxView extends React.Component<LightboxViewProps> {
             SnappingManager.SetExploreMode(false);
         } else {
             const l = CreateLinkToActiveAudio(() => doc).lastElement();
-            l && (Cast(l.link_anchor_2, Doc, null).backgroundColor = 'lightgreen');
+            DocCast(l?.link_anchor_2) && (DocCast(l!.link_anchor_2)!.backgroundColor = 'lightgreen');
             DocumentView.CurrentlyPlaying?.forEach(dv => dv.ComponentView?.Pause?.());
             // DocumentView.PinDoc(doc, { hidePresBox: true });
             this._history ? this._history.push({ doc, target }) : (this._history = [{ doc, target }]);
@@ -142,7 +142,7 @@ export class NewLightboxView extends React.Component<LightboxViewProps> {
         const targetDocView = target && DocumentView.getLightboxDocumentView(target);
         if (targetDocView && target) {
             const l = CreateLinkToActiveAudio(() => targetDocView.ComponentView?.getAnchor?.(true) || target).lastElement();
-            l && (Cast(l.link_anchor_2, Doc, null).backgroundColor = 'lightgreen');
+            DocCast(l?.link_anchor_2) && (DocCast(l!.link_anchor_2)!.backgroundColor = 'lightgreen');
             DocumentView.showDocument(target, { willZoomCentered: true, zoomScale: 0.9 });
             if (NewLightboxView._history?.lastElement().target !== target) NewLightboxView._history?.push({ doc, target });
         } else if (!target && NewLightboxView.path.length) {
@@ -326,7 +326,6 @@ export class NewLightboxView extends React.Component<LightboxViewProps> {
 }
 interface NewLightboxTourBtnProps {
     navBtn: (left: Opt<string | number>, bottom: Opt<number>, top: number, icon: string, display: () => string, click: (e: React.MouseEvent) => void, color?: string) => JSX.Element;
-    // eslint-disable-next-line react/no-unused-prop-types
     future: () => Opt<Doc[]>;
     stepInto: () => void;
 }
diff --git a/src/client/views/nodes/DataVizBox/DataVizBox.tsx b/src/client/views/nodes/DataVizBox/DataVizBox.tsx
index c80e8ebc1..9369ff98a 100644
--- a/src/client/views/nodes/DataVizBox/DataVizBox.tsx
+++ b/src/client/views/nodes/DataVizBox/DataVizBox.tsx
@@ -108,7 +108,7 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
     // all CSV records in the dataset (that aren't an empty row)
     @computed.struct get records() {
         try {
-            const records = DataVizBox.dataset.get(CsvCast(this.dataDoc[this.fieldKey]).url.href);
+            const records = DataVizBox.dataset.get(CsvCast(this.dataDoc[this.fieldKey])?.url.href ?? '');
             this._urlError = false;
             return records?.filter(record => Object.keys(record).some(key => record[key])) ?? [];
         } catch {
@@ -344,7 +344,7 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
     componentDidMount() {
         this._props.setContentViewBox?.(this);
         if (!this._urlError) {
-            if (!DataVizBox.dataset.has(CsvCast(this.dataDoc[this.fieldKey]).url.href)) this.fetchData();
+            if (!DataVizBox.dataset.has(CsvCast(this.dataDoc[this.fieldKey])?.url.href ?? '')) this.fetchData();
         }
         this._disposers.datavis = reaction(
             () => {
@@ -386,8 +386,8 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
                     this.layoutDoc._dataViz_schemaOG = loading;
                 }
                 const ogDoc = this.layoutDoc._dataViz_schemaOG as Doc;
-                const ogHref = CsvCast(ogDoc[this.fieldKey]) ? CsvCast(ogDoc[this.fieldKey]).url.href : undefined;
-                const { href } = CsvCast(this.Document[this.fieldKey]).url;
+                const ogHref = CsvCast(ogDoc[this.fieldKey]) ? CsvCast(ogDoc[this.fieldKey])!.url.href : undefined;
+                const { href } = CsvCast(this.Document[this.fieldKey])?.url ?? { href: '' };
                 if (ogHref && !DataVizBox.datasetSchemaOG.has(href)) {
                     // sets original dataset to the var
                     const lastRow = current.pop();
@@ -399,7 +399,7 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
             },
             current => {
                 if (current) {
-                    const { href } = CsvCast(this.Document[this.fieldKey]).url;
+                    const { href } = CsvCast(this.Document[this.fieldKey])?.url ?? { href: '' };
                     if (this.layoutDoc.dataViz_schemaLive) DataVizBox.dataset.set(href, current);
                     else DataVizBox.dataset.set(href, DataVizBox.datasetSchemaOG.get(href)!);
                 }
@@ -414,9 +414,9 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
 
     fetchData = () => {
         if (!this.Document.dataViz_asSchema) {
-            DataVizBox.dataset.set(CsvCast(this.dataDoc[this.fieldKey]).url.href, []); // assign temporary dataset as a lock to prevent duplicate server requests
+            DataVizBox.dataset.set(CsvCast(this.dataDoc[this.fieldKey])?.url.href ?? '', []); // assign temporary dataset as a lock to prevent duplicate server requests
             fetch('/csvData?uri=' + (this.dataUrl?.url.href ?? '')) //
-                .then(res => res.json().then(action(jsonRes => !jsonRes.errno && DataVizBox.dataset.set(CsvCast(this.dataDoc[this.fieldKey]).url.href, jsonRes))));
+                .then(res => res.json().then(action(jsonRes => !jsonRes.errno && DataVizBox.dataset.set(CsvCast(this.dataDoc[this.fieldKey])?.url.href ?? '', jsonRes))));
         }
     };
 
@@ -523,7 +523,7 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
         GPTPopup.Instance.createFilteredDoc = this.createFilteredDoc;
         GPTPopup.Instance.setDataJson('');
         GPTPopup.Instance.setMode(GPTPopupMode.DATA);
-        const csvdata = DataVizBox.dataset.get(CsvCast(this.dataDoc[this.fieldKey]).url.href);
+        const csvdata = DataVizBox.dataset.get(CsvCast(this.dataDoc[this.fieldKey])?.url.href ?? '');
         GPTPopup.Instance.setDataJson(JSON.stringify(csvdata));
         GPTPopup.Instance.generateDataAnalysis();
     });
diff --git a/src/client/views/nodes/DataVizBox/SchemaCSVPopUp.tsx b/src/client/views/nodes/DataVizBox/SchemaCSVPopUp.tsx
index 8ae29a88c..1e2a95d31 100644
--- a/src/client/views/nodes/DataVizBox/SchemaCSVPopUp.tsx
+++ b/src/client/views/nodes/DataVizBox/SchemaCSVPopUp.tsx
@@ -11,10 +11,8 @@ import { DragManager } from '../../../util/DragManager';
 import { DocumentView } from '../DocumentView';
 import './SchemaCSVPopUp.scss';
 
-interface SchemaCSVPopUpProps {}
-
 @observer
-export class SchemaCSVPopUp extends React.Component<SchemaCSVPopUpProps> {
+export class SchemaCSVPopUp extends React.Component<object> {
     // eslint-disable-next-line no-use-before-define
     static Instance: SchemaCSVPopUp;
 
@@ -23,7 +21,7 @@ export class SchemaCSVPopUp extends React.Component<SchemaCSVPopUpProps> {
     @observable public target: Doc | undefined = undefined;
     @observable public visible: boolean = false;
 
-    constructor(props: SchemaCSVPopUpProps) {
+    constructor(props: object) {
         super(props);
         makeObservable(this);
         SchemaCSVPopUp.Instance = this;
diff --git a/src/client/views/nodes/DataVizBox/components/Histogram.tsx b/src/client/views/nodes/DataVizBox/components/Histogram.tsx
index 5450d03b1..a7c4a00b0 100644
--- a/src/client/views/nodes/DataVizBox/components/Histogram.tsx
+++ b/src/client/views/nodes/DataVizBox/components/Histogram.tsx
@@ -5,10 +5,9 @@ import { IReactionDisposer, action, computed, makeObservable, observable, reacti
 import { observer } from 'mobx-react';
 import * as React from 'react';
 import { FaFillDrip } from 'react-icons/fa';
-import { Doc, NumListCast } from '../../../../../fields/Doc';
+import { Doc, NumListCast, StrListCast } from '../../../../../fields/Doc';
 import { List } from '../../../../../fields/List';
-import { listSpec } from '../../../../../fields/Schema';
-import { Cast, DocCast, StrCast } from '../../../../../fields/Types';
+import { DocCast, StrCast } from '../../../../../fields/Types';
 import { Docs } from '../../../../documents/Documents';
 import { undoable } from '../../../../util/UndoManager';
 import { ObservableReactComponent } from '../../../ObservableReactComponent';
@@ -108,13 +107,13 @@ export class Histogram extends ObservableReactComponent<HistogramProps> {
     }
 
     @computed get defaultBarColor() {
-        return Cast(this.layoutDoc.dataViz_histogram_defaultColor, 'string', '#69b3a2');
+        return StrCast(this.layoutDoc.dataViz_histogram_defaultColor, '#69b3a2')!;
     }
     @computed get barColors() {
-        return Cast(this.layoutDoc.dataViz_histogram_barColors, listSpec('string'), null);
+        return StrListCast(this.layoutDoc.dataViz_histogram_barColors);
     }
     @computed get selectedBins() {
-        return Cast(this.layoutDoc.dataViz_histogram_selectedBins, listSpec('number'), null);
+        return NumListCast(this.layoutDoc.dataViz_histogram_selectedBins);
     }
 
     @computed get rangeVals(): { xMin?: number; xMax?: number; yMin?: number; yMax?: number } {
@@ -129,7 +128,7 @@ export class Histogram extends ObservableReactComponent<HistogramProps> {
         // restore selected bars
         this._histogramSvg?.selectAll('rect').attr('class', dIn => {
             const d = dIn as HistogramData;
-            if (this.selectedBins.some(selBin => d[0] === selBin)) {
+            if (this.selectedBins?.some(selBin => d[0] === selBin)) {
                 this._selectedBars.push(d);
                 return 'histogram-bar hover';
             }
@@ -199,10 +198,10 @@ export class Histogram extends ObservableReactComponent<HistogramProps> {
                     const alreadySelected = this._selectedBars.findIndex(eachData => !Object.keys(d).some(key => d[key] !== eachData[key]));
                     if (alreadySelected !== -1) {
                         this._selectedBars.splice(alreadySelected, 1);
-                        this.selectedBins.splice(alreadySelected, 1);
+                        this.selectedBins?.splice(alreadySelected, 1);
                     } else {
                         this._selectedBars.push(d);
-                        this.selectedBins.push(d[0] as number);
+                        this.selectedBins?.push(d[0] as number);
                     }
                     const showSelectedLabel = (dataset: HistogramData[]) => {
                         const datum = dataset.lastElement();
diff --git a/src/client/views/nodes/DataVizBox/components/LineChart.tsx b/src/client/views/nodes/DataVizBox/components/LineChart.tsx
index 6b047546c..80fadf178 100644
--- a/src/client/views/nodes/DataVizBox/components/LineChart.tsx
+++ b/src/client/views/nodes/DataVizBox/components/LineChart.tsx
@@ -26,7 +26,7 @@ export interface LineChartProps {
     layoutDoc: Doc;
     axes: string[];
     titleCol: string;
-    records: { [key: string]: any }[];
+    records: { [key: string]: string }[];
     width: number;
     height: number;
     dataDoc: Doc;
@@ -47,7 +47,7 @@ export class LineChart extends ObservableReactComponent<LineChartProps> {
     @observable _currSelected: DataPoint | undefined = undefined;
 
     // TODO: nda - some sort of mapping that keeps track of the annotated points so we can easily remove when annotations list updates
-    constructor(props: any) {
+    constructor(props: LineChartProps) {
         super(props);
         makeObservable(this);
     }
@@ -79,7 +79,7 @@ export class LineChart extends ObservableReactComponent<LineChartProps> {
     @computed get incomingHighlited() {
         // return selected x and y axes
         // otherwise, use the selection of whatever is linked to us
-        const incomingVizBox = DocumentView.getFirstDocumentView(this.parentViz)?.ComponentView as DataVizBox;
+        const incomingVizBox = this.parentViz && (DocumentView.getFirstDocumentView(this.parentViz)?.ComponentView as DataVizBox);
         const highlitedRowIds = NumListCast(incomingVizBox?.layoutDoc?.dataViz_highlitedRows);
         return this._tableData.filter((record, i) => highlitedRowIds.includes(this._tableDataIds[i])); // get all the datapoints they have selected field set by incoming anchor
     }
@@ -170,8 +170,8 @@ export class LineChart extends ObservableReactComponent<LineChartProps> {
             }
         });
         if (!ptWasSelected) {
-            selectedDatapoints.push(d.x + ',' + d.y);
-            this._currSelected = selectedDatapoints.length > 1 ? undefined : d;
+            selectedDatapoints?.push(d.x + ',' + d.y);
+            this._currSelected = (selectedDatapoints?.length ?? 0 > 1) ? undefined : d;
         }
 
         // for filtering child dataviz docs
@@ -190,7 +190,14 @@ export class LineChart extends ObservableReactComponent<LineChartProps> {
         }
     }
 
-    drawDataPoints(data: DataPoint[], idx: number, xScale: d3.ScaleLinear<number, number, never>, yScale: d3.ScaleLinear<number, number, never>, higlightFocusPt: any, tooltip: any) {
+    drawDataPoints(
+        data: DataPoint[], //
+        idx: number,
+        xScale: d3.ScaleLinear<number, number, never>,
+        yScale: d3.ScaleLinear<number, number, never>,
+        higlightFocusPt: d3.Selection<SVGGElement, unknown, null, undefined>,
+        tooltip: d3.Selection<HTMLDivElement, unknown, null, undefined>
+    ) {
         if (this._lineChartSvg) {
             const circleClass = '.circle-' + idx;
             this._lineChartSvg
@@ -211,7 +218,7 @@ export class LineChart extends ObservableReactComponent<LineChartProps> {
                 .on('mouseleave', () => {
                     tooltip?.transition().duration(300).style('opacity', 0);
                 })
-                .on('click', (e: any) => {
+                .on('click', e => {
                     const d0 = { x: Number(e.target.getAttribute('data-x')), y: Number(e.target.getAttribute('data-y')) };
                     // find .circle-d1 with data-x = d0.x and data-y = d0.y
                     this.setCurrSelected(d0);
@@ -220,7 +227,7 @@ export class LineChart extends ObservableReactComponent<LineChartProps> {
         }
     }
 
-    drawChart = (dataSet: any[][], rangeVals: { xMin?: number; xMax?: number; yMin?: number; yMax?: number }, width: number, height: number) => {
+    drawChart = (dataSet: { x: number; y: number }[][], rangeVals: { xMin?: number; xMax?: number; yMin?: number; yMax?: number }, width: number, height: number) => {
         // clearing tooltip and the current chart
         d3.select(this._lineChartRef).select('svg').remove();
         d3.select(this._lineChartRef).select('.tooltip').remove();
@@ -277,7 +284,7 @@ export class LineChart extends ObservableReactComponent<LineChartProps> {
             svg.append('path').attr('stroke', 'red');
 
             // legend
-            const color: any = d3.scaleOrdinal().range(['black', 'blue']).domain([this._props.axes[1], this._props.axes[2]]);
+            const color = d3.scaleOrdinal().range(['black', 'blue']).domain([this._props.axes[1], this._props.axes[2]]);
             svg.selectAll('mydots')
                 .data([this._props.axes[1], this._props.axes[2]])
                 .enter()
diff --git a/src/client/views/nodes/DataVizBox/components/TableBox.tsx b/src/client/views/nodes/DataVizBox/components/TableBox.tsx
index b73123691..ad2731109 100644
--- a/src/client/views/nodes/DataVizBox/components/TableBox.tsx
+++ b/src/client/views/nodes/DataVizBox/components/TableBox.tsx
@@ -128,7 +128,7 @@ export class TableBox extends ObservableReactComponent<TableBoxProps> {
             selected.splice(selected.indexOf(rowId), 1);
         } else selected?.push(rowId);
         e.stopPropagation();
-        this.hasRowsToFilter = selected.length > 0;
+        this.hasRowsToFilter = (selected?.length ?? 0) > 0;
     };
 
     columnPointerDown = (e: React.PointerEvent, col: string) => {
diff --git a/src/client/views/nodes/EquationBox.tsx b/src/client/views/nodes/EquationBox.tsx
index dcc6e27ed..3cacb6692 100644
--- a/src/client/views/nodes/EquationBox.tsx
+++ b/src/client/views/nodes/EquationBox.tsx
@@ -1,7 +1,6 @@
 import { action, computed, makeObservable, reaction } from 'mobx';
 import { observer } from 'mobx-react';
 import * as React from 'react';
-import { Doc } from '../../../fields/Doc';
 import { NumCast, StrCast } from '../../../fields/Types';
 import { TraceMobx } from '../../../fields/util';
 import { DocUtils } from '../../documents/DocUtils';
diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx
index 34e3a5d76..a6872f8dc 100644
--- a/src/client/views/nodes/FieldView.tsx
+++ b/src/client/views/nodes/FieldView.tsx
@@ -6,16 +6,17 @@ import { DateField } from '../../../fields/DateField';
 import { Doc, Field, FieldType, Opt } from '../../../fields/Doc';
 import { List } from '../../../fields/List';
 import { ScriptField } from '../../../fields/ScriptField';
+import { WebField } from '../../../fields/URLField';
+import { DragManager } from '../../util/DragManager';
 import { dropActionType } from '../../util/DropActionTypes';
 import { Transform } from '../../util/Transform';
+import { ContextMenuProps } from '../ContextMenuItem';
 import { PinProps } from '../PinFuncs';
 import { ViewBoxInterface } from '../ViewBoxInterface';
 import { DocumentView } from './DocumentView';
 import { FocusViewOptions } from './FocusViewOptions';
-import { OpenWhere } from './OpenWhere';
-import { WebField } from '../../../fields/URLField';
-import { ContextMenuProps } from '../ContextMenuItem';
 import { FormattedTextBox } from './formattedText/FormattedTextBox';
+import { OpenWhere } from './OpenWhere';
 
 export type FocusFuncType = (doc: Doc, options: FocusViewOptions) => Opt<number>;
 export type StyleProviderFuncType = (
diff --git a/src/client/views/nodes/FunctionPlotBox.tsx b/src/client/views/nodes/FunctionPlotBox.tsx
index 91c351895..8e4b64851 100644
--- a/src/client/views/nodes/FunctionPlotBox.tsx
+++ b/src/client/views/nodes/FunctionPlotBox.tsx
@@ -2,10 +2,11 @@ import functionPlot, { Chart } from 'function-plot';
 import { action, computed, makeObservable, reaction } from 'mobx';
 import { observer } from 'mobx-react';
 import * as React from 'react';
-import { Doc, DocListCast } from '../../../fields/Doc';
+import { returnFalse, setupMoveUpEvents } from '../../../ClientUtils';
+import { emptyFunction } from '../../../Utils';
+import { Doc, DocListCast, NumListCast } from '../../../fields/Doc';
 import { List } from '../../../fields/List';
-import { listSpec } from '../../../fields/Schema';
-import { Cast, StrCast } from '../../../fields/Types';
+import { StrCast } from '../../../fields/Types';
 import { TraceMobx } from '../../../fields/util';
 import { DocUtils } from '../../documents/DocUtils';
 import { DocumentType } from '../../documents/DocumentTypes';
@@ -15,8 +16,6 @@ import { undoBatch } from '../../util/UndoManager';
 import { ViewBoxAnnotatableComponent } from '../DocComponent';
 import { PinDocView, PinProps } from '../PinFuncs';
 import { FieldView, FieldViewProps } from './FieldView';
-import { returnFalse, setupMoveUpEvents } from '../../../ClientUtils';
-import { emptyFunction } from '../../../Utils';
 
 @observer
 export class FunctionPlotBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
@@ -76,7 +75,7 @@ export class FunctionPlotBox extends ViewBoxAnnotatableComponent<FieldViewProps>
         this._plotEle = ele || this._plotEle;
         const width = this._props.PanelWidth();
         const height = this._props.PanelHeight();
-        const xrange = Cast(this.layoutDoc.xRange, listSpec('number'), [-10, 10]);
+        const xrange = NumListCast(this.layoutDoc.xRange, [-10, 10])!;
         try {
             this._plotEle?.children.length && this._plotEle.removeChild(this._plotEle.children[0]);
             this._plot = functionPlot({
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx
index 9c6b8e99c..999d7089b 100644
--- a/src/client/views/nodes/ImageBox.tsx
+++ b/src/client/views/nodes/ImageBox.tsx
@@ -212,7 +212,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
 
     drop = undoable(
         action((e: Event, de: DragManager.DropEvent) => {
-            if (de.complete.docDragData && this._props.rejectDrop?.(de.complete.docDragData?.draggedDocuments, this.DocumentView?.())) {
+            if (de.complete.docDragData && this._props.rejectDrop?.(de, this.DocumentView?.())) {
                 let added: boolean | undefined;
                 const hitDropTarget = (ele: HTMLElement, dropTarget: HTMLDivElement | null): boolean => {
                     if (!ele) return false;
diff --git a/src/client/views/nodes/MapBox/DirectionsAnchorMenu.tsx b/src/client/views/nodes/MapBox/DirectionsAnchorMenu.tsx
index 8784a709a..8bb7ddd9f 100644
--- a/src/client/views/nodes/MapBox/DirectionsAnchorMenu.tsx
+++ b/src/client/views/nodes/MapBox/DirectionsAnchorMenu.tsx
@@ -43,7 +43,7 @@ export class DirectionsAnchorMenu extends AntimodeMenu<AntimodeMenuProps> {
         return this._left > 0;
     }
 
-    constructor(props: Readonly<{}>) {
+    constructor(props: AntimodeMenuProps) {
         super(props);
 
         DirectionsAnchorMenu.Instance = this;
diff --git a/src/client/views/nodes/calendarBox/CalendarBox.tsx b/src/client/views/nodes/calendarBox/CalendarBox.tsx
index 6f1f58a4c..fa863e123 100644
--- a/src/client/views/nodes/calendarBox/CalendarBox.tsx
+++ b/src/client/views/nodes/calendarBox/CalendarBox.tsx
@@ -105,9 +105,10 @@ export class CalendarBox extends CollectionSubView() {
 
     // TODO: Return a different color based on the event type
     eventToColor = (event: Doc): string => {
-        return 'red';
+        return 'red' + event;
     };
 
+    // eslint-disable-next-line @typescript-eslint/no-unused-vars
     internalDocDrop = (e: Event, de: DragManager.DropEvent, docDragData: DragManager.DocumentDragData) => {
         if (!super.onInternalDrop(e, de)) return false;
         de.complete.docDragData?.droppedDocuments.forEach(doc => {
diff --git a/src/client/views/nodes/chatbot/chatboxcomponents/ChatBox.tsx b/src/client/views/nodes/chatbot/chatboxcomponents/ChatBox.tsx
index 528bcd05a..6c3da8977 100644
--- a/src/client/views/nodes/chatbot/chatboxcomponents/ChatBox.tsx
+++ b/src/client/views/nodes/chatbot/chatboxcomponents/ChatBox.tsx
@@ -196,7 +196,7 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
 
             // Add CSV details to linked files
             this._linked_csv_files.push({
-                filename: CsvCast(newLinkedDoc.data).url.pathname,
+                filename: CsvCast(newLinkedDoc.data)?.url.pathname ?? '',
                 id: csvId,
                 text: csvData,
             });
@@ -634,6 +634,7 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
     };
 
     getDirectMatchingSegmentStart = (doc: Doc, citationText: string, indexesOfSegments: string[]): number => {
+        // eslint-disable-next-line @typescript-eslint/no-explicit-any
         const originalSegments = JSON.parse(StrCast(doc.original_segments!)).map((segment: any, index: number) => ({
             index: index.toString(),
             text: segment.text,
@@ -877,7 +878,8 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
         return LinkManager.Instance.getAllRelatedLinks(this.Document)
             .map(d => DocCast(LinkManager.getOppositeAnchor(d, this.Document)))
             .map(d => DocCast(d?.annotationOn, d))
-            .filter(d => d);
+            .filter(d => d)
+            .map(d => d!);
     }
 
     /**
@@ -889,6 +891,7 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
             .map(d => DocCast(LinkManager.getOppositeAnchor(d, this.Document)))
             .map(d => DocCast(d?.annotationOn, d))
             .filter(d => d)
+            .map(d => d!)
             .filter(d => {
                 console.log(d.ai_doc_id);
                 return d.ai_doc_id;
@@ -905,15 +908,14 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
             LinkManager.Instance.getAllRelatedLinks(this.Document)
                 .map(d => DocCast(LinkManager.getOppositeAnchor(d, this.Document)))
                 .map(d => DocCast(d?.annotationOn, d))
-                .filter(d => d)
-                .filter(d => d.summary)
+                .filter(d => d?.summary)
                 .map((doc, index) => {
-                    if (PDFCast(doc.data)) {
-                        return `<summary file_name="${PDFCast(doc.data).url.pathname}" applicable_tools=["rag"]>${doc.summary}</summary>`;
-                    } else if (CsvCast(doc.data)) {
-                        return `<summary file_name="${CsvCast(doc.data).url.pathname}" applicable_tools=["dataAnalysis"]>${doc.summary}</summary>`;
+                    if (PDFCast(doc?.data)) {
+                        return `<summary file_name="${PDFCast(doc!.data)!.url.pathname}" applicable_tools=["rag"]>${doc!.summary}</summary>`;
+                    } else if (CsvCast(doc?.data)) {
+                        return `<summary file_name="${CsvCast(doc!.data)!.url.pathname}" applicable_tools=["dataAnalysis"]>${doc!.summary}</summary>`;
                     } else {
-                        return `${index + 1}) ${doc.summary}`;
+                        return `${index + 1}) ${doc?.summary}`;
                     }
                 })
                 .join('\n') + '\n'
diff --git a/src/client/views/nodes/chatbot/tools/GetDocsTool.ts b/src/client/views/nodes/chatbot/tools/GetDocsTool.ts
index 05482a66e..42a7747d3 100644
--- a/src/client/views/nodes/chatbot/tools/GetDocsTool.ts
+++ b/src/client/views/nodes/chatbot/tools/GetDocsTool.ts
@@ -40,7 +40,10 @@ export class GetDocsTool extends BaseTool<GetDocsToolParamsType> {
     }
 
     async execute(args: ParametersType<GetDocsToolParamsType>): Promise<Observation[]> {
-        const docs = args.document_ids.map(doc_id => DocCast(DocServer.GetCachedRefField(doc_id)));
+        const docs = args.document_ids
+            .map(doc_id => DocCast(DocServer.GetCachedRefField(doc_id)))
+            .filter(d => d)
+            .map(d => d!);
         const collection = Docs.Create.FreeformDocument(docs, { title: args.title });
         this._docView._props.addDocTab(collection, OpenWhere.addRight);
         return [{ type: 'text', text: `Collection created in Dash called ${args.title}` }];
diff --git a/src/client/views/nodes/chatbot/vectorstore/Vectorstore.ts b/src/client/views/nodes/chatbot/vectorstore/Vectorstore.ts
index c1915a398..6d524e40f 100644
--- a/src/client/views/nodes/chatbot/vectorstore/Vectorstore.ts
+++ b/src/client/views/nodes/chatbot/vectorstore/Vectorstore.ts
@@ -15,7 +15,6 @@ import { Networking } from '../../../../Network';
 import { AI_Document, CHUNK_TYPE, RAGChunk } from '../types/types';
 import OpenAI from 'openai';
 import { Embedding } from 'openai/resources';
-import { PineconeEnvironmentVarsNotSupportedError } from '@pinecone-database/pinecone/dist/errors';
 
 dotenv.config();
 
@@ -101,7 +100,7 @@ export class Vectorstore {
         } else {
             // Start processing the document.
             doc.ai_document_status = 'PROGRESS';
-            const local_file_path: string = CsvCast(doc.data)?.url?.pathname ?? PDFCast(doc.data)?.url?.pathname ?? VideoCast(doc.data)?.url?.pathname ?? AudioCast(doc.data)?.url?.pathname;
+            const local_file_path = CsvCast(doc.data)?.url?.pathname ?? PDFCast(doc.data)?.url?.pathname ?? VideoCast(doc.data)?.url?.pathname ?? AudioCast(doc.data)?.url?.pathname;
 
             if (!local_file_path) {
                 console.log('Invalid file path.');
@@ -112,13 +111,13 @@ export class Vectorstore {
             let result: AI_Document & { doc_id: string };
             if (isAudioOrVideo) {
                 console.log('Processing media file...');
-                const response = await Networking.PostToServer('/processMediaFile', { fileName: path.basename(local_file_path) });
+                const response = (await Networking.PostToServer('/processMediaFile', { fileName: path.basename(local_file_path) })) as { [key: string]: unknown };
                 const segmentedTranscript = response.condensed;
                 console.log(segmentedTranscript);
-                const summary = response.summary;
+                const summary = response.summary as string;
                 doc.summary = summary;
                 // Generate embeddings for each chunk
-                const texts = segmentedTranscript.map((chunk: any) => chunk.text);
+                const texts = (segmentedTranscript as { text: string }[])?.map(chunk => chunk.text);
 
                 try {
                     const embeddingsResponse = await this.openai.embeddings.create({
@@ -138,7 +137,7 @@ export class Vectorstore {
                         file_name: local_file_path,
                         num_pages: 0,
                         summary: '',
-                        chunks: segmentedTranscript.map((chunk: any, index: number) => ({
+                        chunks: (segmentedTranscript as { text: string; start: number; end: number; indexes: string[] }[]).map((chunk, index) => ({
                             id: uuidv4(),
                             values: (embeddingsResponse.data as Embedding[])[index].embedding, // Assign embedding
                             metadata: {
@@ -173,7 +172,7 @@ export class Vectorstore {
             } else {
                 // Existing document processing logic remains unchanged
                 console.log('Processing regular document...');
-                const { jobId } = await Networking.PostToServer('/createDocument', { file_path: local_file_path });
+                const { jobId } = (await Networking.PostToServer('/createDocument', { file_path: local_file_path })) as { jobId: string };
 
                 while (true) {
                     await new Promise(resolve => setTimeout(resolve, 2000));
@@ -297,7 +296,7 @@ export class Vectorstore {
                 encoding_format: 'float',
             });
 
-            let queryEmbedding = queryEmbeddingResponse.data[0].embedding;
+            const queryEmbedding = queryEmbeddingResponse.data[0].embedding;
 
             // Extract the embedding from the response.
 
diff --git a/src/client/views/nodes/formattedText/DailyJournal.tsx b/src/client/views/nodes/formattedText/DailyJournal.tsx
index 797a9b812..871c556e6 100644
--- a/src/client/views/nodes/formattedText/DailyJournal.tsx
+++ b/src/client/views/nodes/formattedText/DailyJournal.tsx
@@ -161,7 +161,7 @@ export class DailyJournal extends ViewBoxAnnotatableComponent<FieldViewProps>()
 
                         // Check if doc or selection changed
                         if (!prevState.doc.eq(state.doc) || !prevState.selection.eq(state.selection)) {
-                            let found = false;
+                            const found = false;
                             const textToRemove = this.predictiveText;
 
                             state.doc.descendants((node, pos) => {
diff --git a/src/client/views/nodes/scrapbook/ScrapbookBox.tsx b/src/client/views/nodes/scrapbook/ScrapbookBox.tsx
index b241b27d7..6cfe9a62c 100644
--- a/src/client/views/nodes/scrapbook/ScrapbookBox.tsx
+++ b/src/client/views/nodes/scrapbook/ScrapbookBox.tsx
@@ -1,6 +1,6 @@
 import { action, makeObservable, observable } from 'mobx';
 import * as React from 'react';
-import { Doc, DocListCast, StrListCast } from '../../../../fields/Doc';
+import { Doc, DocListCast } from '../../../../fields/Doc';
 import { List } from '../../../../fields/List';
 import { emptyFunction } from '../../../../Utils';
 import { Docs } from '../../../documents/Documents';
diff --git a/src/client/views/pdf/Annotation.tsx b/src/client/views/pdf/Annotation.tsx
index 1891cfd4c..e8a5235c9 100644
--- a/src/client/views/pdf/Annotation.tsx
+++ b/src/client/views/pdf/Annotation.tsx
@@ -50,7 +50,7 @@ interface IAnnotationProps extends FieldViewProps {
 }
 @observer
 export class Annotation extends ObservableReactComponent<IAnnotationProps> {
-    constructor(props: any) {
+    constructor(props: IAnnotationProps) {
         super(props);
         makeObservable(this);
     }
@@ -58,7 +58,7 @@ export class Annotation extends ObservableReactComponent<IAnnotationProps> {
     @computed get linkHighlighted() {
         const found = LinkManager.Instance.getAllDirectLinks(this._props.annoDoc).find(link => {
             const a1 = Doc.getOppositeAnchor(link, this._props.annoDoc);
-            return a1 && Doc.GetBrushStatus(DocCast(a1.annotationOn, a1));
+            return a1 && Doc.GetBrushStatus(DocCast(a1.annotationOn, a1)!);
         });
         return found;
     }
@@ -112,6 +112,7 @@ export class Annotation extends ObservableReactComponent<IAnnotationProps> {
     outline = () => (this.linkHighlighted ? 'solid 1px lightBlue' : undefined);
     background = () => (this._props.annoDoc[Highlight] ? 'orange' : StrCast(this._props.annoDoc.backgroundColor));
     render() {
+        // eslint-disable-next-line @typescript-eslint/no-unused-vars
         const forceRenderHack = [this.background(), this.outline(), this.opacity()]; // forces a re-render when these change -- because RegionAnnotation doesn't do this internally..
         return (
             <div style={{ display: this._props.annoDoc.textCopied && !Doc.GetBrushHighlightStatus(this._props.annoDoc) ? 'none' : undefined }}>
@@ -121,7 +122,7 @@ export class Annotation extends ObservableReactComponent<IAnnotationProps> {
                     .map(([x, y, width, height]) => (
                         <div
                             key={'' + x + y + width + height}
-                            style={{ pointerEvents: this._props.pointerEvents?.() as any }}
+                            style={{ pointerEvents: this._props.pointerEvents?.() as Property.PointerEvents }}
                             onPointerDown={this.onPointerDown}
                             onContextMenu={this.onContextMenu}
                             onPointerEnter={() => {
diff --git a/src/client/views/search/FaceRecognitionHandler.tsx b/src/client/views/search/FaceRecognitionHandler.tsx
index f60eb486e..cb837e3ab 100644
--- a/src/client/views/search/FaceRecognitionHandler.tsx
+++ b/src/client/views/search/FaceRecognitionHandler.tsx
@@ -162,7 +162,7 @@ export class FaceRecognitionHandler {
         });
         uniqueFaceDoc.$face = `Face${faceDocNum}`;
         uniqueFaceDoc.$face_annos = new List<Doc>();
-        Doc.SetContainer(uniqueFaceDoc, Doc.MyFaceCollection);
+        Doc.MyFaceCollection && Doc.SetContainer(uniqueFaceDoc, Doc.MyFaceCollection);
 
         Doc.ActiveDashboard && Doc.AddDocToList(Doc.ActiveDashboard[DocData], 'myUniqueFaces', uniqueFaceDoc);
         return uniqueFaceDoc;
@@ -208,9 +208,9 @@ export class FaceRecognitionHandler {
             setTimeout(() => this.classifyFacesInImage(imgDoc), 1000);
         } else {
             const imgUrl = ImageCast(imgDoc[Doc.LayoutDataKey(imgDoc)]);
-            if (imgUrl && !DocListCast(Doc.MyFaceCollection.examinedFaceDocs).includes(imgDoc[DocData])) {
+            if (imgUrl && !DocListCast(Doc.MyFaceCollection?.examinedFaceDocs).includes(imgDoc[DocData])) {
                 // only examine Docs that have an image and that haven't already been examined.
-                Doc.AddDocToList(Doc.MyFaceCollection, 'examinedFaceDocs', imgDoc[DocData]);
+                Doc.MyFaceCollection && Doc.AddDocToList(Doc.MyFaceCollection, 'examinedFaceDocs', imgDoc[DocData]);
                 FaceRecognitionHandler.loadImage(imgUrl).then(
                     // load image and analyze faces
                     img => faceapi
diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts
index 1c17dd369..ba94f0504 100644
--- a/src/fields/Doc.ts
+++ b/src/fields/Doc.ts
@@ -231,7 +231,7 @@ export class Doc extends RefField {
     public static AddLink: (link: Doc, checkExists?: boolean) => void;
     public static DeleteLink: (link: Doc) => void;
     public static Links: (link: Doc | undefined) => Doc[];
-    public static getOppositeAnchor: (linkDoc: Doc, anchor: Doc) => Doc | undefined;
+    public static getOppositeAnchor: (linkDoc: Doc | undefined, anchor: Doc | undefined) => Doc | undefined;
     // KeyValueBox SetField (defined there)
     public static SetField: (doc: Doc, key: string, value: string, forceOnDelegate?: boolean, setResult?: (value: FieldResult) => void) => boolean;
     // UserDoc "API"
diff --git a/src/fields/Types.ts b/src/fields/Types.ts
index e6755f828..ba2e9bb6f 100644
--- a/src/fields/Types.ts
+++ b/src/fields/Types.ts
@@ -1,5 +1,6 @@
 import { DateField } from './DateField';
 import { Doc, FieldType, FieldResult, Opt } from './Doc';
+import { InkField } from './InkField';
 import { List } from './List';
 import { ProxyField } from './Proxy';
 import { RefField } from './RefField';
@@ -99,6 +100,7 @@ export function VideoCast (field: FieldResult, defaultVal: VideoField | null = n
 export function AudioCast (field: FieldResult, defaultVal: AudioField | null = null)   { return Cast(field, AudioField, defaultVal); } // prettier-ignore
 export function PDFCast   (field: FieldResult, defaultVal: PdfField | null = null)     { return Cast(field, PdfField, defaultVal); } // prettier-ignore
 export function ImageCast (field: FieldResult, defaultVal: ImageField | null = null)   { return Cast(field, ImageField, defaultVal); } // prettier-ignore
+export function InkCast   (field: FieldResult, defaultVal: InkField | null = null)     { return Cast(field, InkField, defaultVal); } // prettier-ignore
 
 export function ImageCastToNameType(field: FieldResult, defaultVal: ImageField | null = null) {
     const href = ImageCast(field, defaultVal)?.url.href;
-- 
cgit v1.2.3-70-g09d2


From d993a3a389464773d04b31de5d427ec4eb5e3d5b Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Thu, 1 May 2025 15:32:10 -0400
Subject: cleaned up, a bit, how wheel events are blocked from propagating.

---
 src/client/views/collections/CollectionCardDeckView.tsx      | 10 +---------
 src/client/views/collections/CollectionCarousel3DView.tsx    |  9 ++-------
 src/client/views/collections/CollectionCarouselView.tsx      |  7 +------
 src/client/views/collections/CollectionStackingView.tsx      |  7 +------
 .../collectionFreeForm/CollectionFreeFormView.tsx            |  5 +----
 .../collections/collectionFreeForm/FaceCollectionBox.tsx     | 12 +-----------
 .../collections/collectionSchema/CollectionSchemaView.tsx    | 11 +----------
 src/client/views/nodes/DiagramBox.tsx                        | 12 +-----------
 src/client/views/nodes/calendarBox/CalendarBox.tsx           |  7 +------
 src/client/views/nodes/formattedText/FormattedTextBox.tsx    |  6 +-----
 10 files changed, 11 insertions(+), 75 deletions(-)

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

diff --git a/src/client/views/collections/CollectionCardDeckView.tsx b/src/client/views/collections/CollectionCardDeckView.tsx
index 50de7c601..d5edc3e0b 100644
--- a/src/client/views/collections/CollectionCardDeckView.tsx
+++ b/src/client/views/collections/CollectionCardDeckView.tsx
@@ -40,7 +40,6 @@ import { CollectionSubView, SubCollectionViewProps } from './CollectionSubView';
 export class CollectionCardView extends CollectionSubView() {
     private _dropDisposer?: DragManager.DragDropDisposer;
     private _disposers: { [key: string]: IReactionDisposer } = {};
-    private _oldWheel: HTMLElement | null = null;
     private _dropped = false; // set when a card doc has just moved and the drop method has been called - prevents the pointerUp method from hiding doc decorations (which needs to be done when clicking on a card to animate it to front/center)
     private _setCurDocScript = () => ScriptField.MakeScript('scriptContext.layoutDoc._card_curDoc=this', { scriptContext: 'any' })!;
     private _draggerRef = React.createRef<HTMLDivElement>();
@@ -56,13 +55,7 @@ export class CollectionCardView extends CollectionSubView() {
     }
     protected createDashEventsTarget = (ele: HTMLDivElement | null) => {
         this._dropDisposer?.();
-        if (ele) {
-            this._dropDisposer = DragManager.MakeDropTarget(ele, this.onInternalDrop.bind(this), this.layoutDoc);
-        }
-        this._oldWheel?.removeEventListener('wheel', this.onPassiveWheel);
-        this._oldWheel = ele;
-        // prevent wheel events from passively propagating up through containers and prevents containers from preventDefault which would block scrolling
-        ele?.addEventListener('wheel', this.onPassiveWheel, { passive: false });
+        this.fixWheelEvents(ele, this._props.isContentActive);
     };
     @computed get cardWidth() {
         return NumCast(this.layoutDoc._cardWidth, 50);
@@ -487,7 +480,6 @@ export class CollectionCardView extends CollectionSubView() {
             );
         });
     }
-    onPassiveWheel = (e: WheelEvent) => e.stopPropagation();
 
     contentScreenToLocalXf = () => this._props.ScreenToLocalTransform().scale(this._props.NativeDimScaling?.() || 1);
     docViewProps = (): DocumentViewProps => ({
diff --git a/src/client/views/collections/CollectionCarousel3DView.tsx b/src/client/views/collections/CollectionCarousel3DView.tsx
index 9c8ef5519..755e31925 100644
--- a/src/client/views/collections/CollectionCarousel3DView.tsx
+++ b/src/client/views/collections/CollectionCarousel3DView.tsx
@@ -25,7 +25,6 @@ const { CAROUSEL3D_CENTER_SCALE, CAROUSEL3D_SIDE_SCALE, CAROUSEL3D_TOP } = requi
 @observer
 export class CollectionCarousel3DView extends CollectionSubView() {
     private _dropDisposer?: DragManager.DragDropDisposer;
-    private _oldWheel: HTMLElement | null = null;
 
     constructor(props: SubCollectionViewProps) {
         super(props);
@@ -44,10 +43,7 @@ export class CollectionCarousel3DView extends CollectionSubView() {
         if (ele) {
             this._dropDisposer = DragManager.MakeDropTarget(ele, this.onInternalDrop.bind(this), this.layoutDoc);
         }
-        this._oldWheel?.removeEventListener('wheel', this.onPassiveWheel);
-        this._oldWheel = ele;
-        // prevent wheel events from passively propagating up through containers and prevents containers from preventDefault which would block scrolling
-        ele?.addEventListener('wheel', this.onPassiveWheel, { passive: false });
+        this.fixWheelEvents(ele, this._props.isContentActive);
     };
 
     @computed get scrollSpeed() {
@@ -101,7 +97,7 @@ export class CollectionCarousel3DView extends CollectionSubView() {
     focus = (anchor: Doc, options: FocusViewOptions): Opt<number> => {
         const docs = DocListCast(this.Document[this.fieldKey]);
         if (anchor.type === DocumentType.CONFIG || docs.includes(anchor)) {
-            const newIndex = anchor.config_carousel_index ?? docs.getIndex(DocCast(anchor.annotationOn, anchor));
+            const newIndex = anchor.config_carousel_index ?? docs.getIndex(DocCast(anchor.annotationOn, anchor)!);
             options.didMove = newIndex !== this.layoutDoc._carousel_index;
             options.didMove && (this.layoutDoc._carousel_index = newIndex);
         }
@@ -221,7 +217,6 @@ export class CollectionCarousel3DView extends CollectionSubView() {
         return this.panelWidth() * (1 - index);
     }
 
-    onPassiveWheel = (e: WheelEvent) => e.stopPropagation();
     curDoc = () => this.carouselItems[NumCast(this.layoutDoc._carousel_index)]?.layout;
     answered = (correct: boolean) => (!correct || !this.curDoc() || NumCast(this.layoutDoc._carousel_index) === this.carouselItems.length - 1) && this.changeSlide(1);
     docViewProps = () => ({
diff --git a/src/client/views/collections/CollectionCarouselView.tsx b/src/client/views/collections/CollectionCarouselView.tsx
index 975dc52fe..ac1981012 100644
--- a/src/client/views/collections/CollectionCarouselView.tsx
+++ b/src/client/views/collections/CollectionCarouselView.tsx
@@ -21,7 +21,6 @@ import { CollectionSubView, SubCollectionViewProps } from './CollectionSubView';
 export class CollectionCarouselView extends CollectionSubView() {
     private _dropDisposer?: DragManager.DragDropDisposer;
 
-    _oldWheel: HTMLElement | null = null;
     _fadeTimer: NodeJS.Timeout | undefined;
     @observable _last_index = this.carouselIndex;
     @observable _last_opacity = 1;
@@ -43,10 +42,7 @@ export class CollectionCarouselView extends CollectionSubView() {
         if (ele) {
             this._dropDisposer = DragManager.MakeDropTarget(ele, this.onInternalDrop.bind(this), this.layoutDoc);
         }
-        this._oldWheel?.removeEventListener('wheel', this.onPassiveWheel);
-        this._oldWheel = ele;
-        // prevent wheel events from passively propagating up through containers and prevents containers from preventDefault which would block scrolling
-        ele?.addEventListener('wheel', this.onPassiveWheel, { passive: false });
+        this.fixWheelEvents(ele, this._props.isContentActive);
     };
 
     @computed get captionMarginX(){ return NumCast(this.layoutDoc.caption_xMargin, 50); } // prettier-ignore
@@ -115,7 +111,6 @@ export class CollectionCarouselView extends CollectionSubView() {
               : this._props.childDocumentsActive?.() === false || this.Document.childDocumentsActive === false
                 ? false
                 : undefined; // prettier-ignore
-    onPassiveWheel = (e: WheelEvent) => e.stopPropagation();
 
     renderDoc = (doc: Doc, showCaptions: boolean, overlayFunc?: (r: DocumentView | null) => void) => {
         return (
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index f11e646cc..be570564b 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -55,7 +55,6 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection
     _docXfs: { height: () => number; width: () => number; stackedDocTransform: () => Transform }[] = [];
     // Doesn't look like this field is being used anywhere. Obsolete?
     _columnStart: number = 0;
-    _oldWheel: HTMLElement | null = null;
 
     @observable _refList: HTMLElement[] = [];
     // map of node headers to their heights. Used in Masonry
@@ -721,7 +720,6 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection
         return this._props.isContentActive() === false ? 'none' : undefined;
     }
 
-    onPassiveWheel = (e: WheelEvent) => this._props.isContentActive() && e.stopPropagation();
     render() {
         TraceMobx();
         const editableViewProps = {
@@ -744,10 +742,7 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection
                         ref={ele => {
                             this._masonryGridRef = ele;
                             this.createDashEventsTarget(ele); // so the whole grid is the drop target?
-                            this._oldWheel?.removeEventListener('wheel', this.onPassiveWheel);
-                            this._oldWheel = ele;
-                            // prevent wheel events from passively propagating up through containers and prevents containers from preventDefault which would block scrolling
-                            ele?.addEventListener('wheel', this.onPassiveWheel, { passive: false });
+                            this.fixWheelEvents(ele, this._props.isContentActive);
                         }}
                         style={{
                             overflowY: this.isContentActive() ? 'auto' : 'hidden',
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index c4971c204..2364fd74a 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -2268,10 +2268,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
                 id={this._paintedId}
                 ref={r => {
                     this.createDashEventsTarget(r);
-                    this._oldWheel?.removeEventListener('wheel', this.onPassiveWheel);
-                    this._oldWheel = r;
-                    // prevent wheel events from passivly propagating up through containers
-                    r?.addEventListener('wheel', this.onPassiveWheel, { passive: false });
+                    this.fixWheelEvents(r, this._props.isContentActive, this.onPassiveWheel);
                     r?.addEventListener('mouseleave', this.onMouseLeave);
                     r?.addEventListener('mouseenter', this.onMouseEnter);
                 }}
diff --git a/src/client/views/collections/collectionFreeForm/FaceCollectionBox.tsx b/src/client/views/collections/collectionFreeForm/FaceCollectionBox.tsx
index 624c85beb..142085e14 100644
--- a/src/client/views/collections/collectionFreeForm/FaceCollectionBox.tsx
+++ b/src/client/views/collections/collectionFreeForm/FaceCollectionBox.tsx
@@ -150,11 +150,6 @@ export class UniqueFaceBox extends ViewBoxBaseComponent<FieldViewProps>() {
         FaceRecognitionHandler.UniqueFaceRemoveFaceImage(imgDoc, this.Document);
     }, 'remove doc from face');
 
-    /**
-     * This stops scroll wheel events when they are used to scroll the face collection.
-     */
-    onPassiveWheel = (e: WheelEvent) => e.stopPropagation();
-
     render() {
         return (
             <div className="face-document-item" ref={ele => this.createDropTarget(ele!)}>
@@ -181,12 +176,7 @@ export class UniqueFaceBox extends ViewBoxBaseComponent<FieldViewProps>() {
                         style={{
                             pointerEvents: this._props.isContentActive() ? undefined : 'none',
                         }}
-                        ref={action((ele: HTMLDivElement | null) => {
-                            this._listRef?.removeEventListener('wheel', this.onPassiveWheel);
-                            this._listRef = ele;
-                            // prevent wheel events from passively propagating up through containers and prevents containers from preventDefault which would block scrolling
-                            ele?.addEventListener('wheel', this.onPassiveWheel, { passive: false });
-                        })}>
+                        ref={r => this.fixWheelEvents(r, this._props.isContentActive)}>
                         {FaceRecognitionHandler.UniqueFaceImages(this.Document).map((doc, i) => {
                             const [name, type] = ImageCastToNameType(doc?.[Doc.LayoutDataKey(doc)]) ?? ['-missing-', '.png'];
                             return (
diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
index 82ca96839..c06391f35 100644
--- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
+++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
@@ -1293,7 +1293,6 @@ export class CollectionSchemaView extends CollectionSubView() {
     isContentActive = () => this._props.isSelected() || this._props.isContentActive();
     screenToLocal = () => this.ScreenToLocalBoxXf().translate(-this.tableWidth, 0);
     previewWidthFunc = () => this.previewWidth;
-    onPassiveWheel = (e: WheelEvent) => e.stopPropagation();
     displayedDocsFunc = () => this.docsWithDrag.docs;
     render() {
         return (
@@ -1307,15 +1306,7 @@ export class CollectionSchemaView extends CollectionSubView() {
                     this.setColDrag(false);
                 }}>
                 <div ref={this._menuTarget} style={{ background: 'red', top: 0, left: 0, position: 'absolute', zIndex: 10000 }} />
-                <div
-                    className="schema-table"
-                    style={{ width: `calc(100% - ${this.previewWidth}px)` }}
-                    onWheel={e => this._props.isContentActive() && e.stopPropagation()}
-                    ref={ele => {
-                        // prevent wheel events from passively propagating up through containers and prevents containers from preventDefault which would block scrolling
-                        this._oldWheel?.removeEventListener('wheel', this.onPassiveWheel);
-                        (this._oldWheel = ele)?.addEventListener('wheel', this.onPassiveWheel, { passive: false });
-                    }}>
+                <div className="schema-table" style={{ width: `calc(100% - ${this.previewWidth}px)` }} onWheel={e => this._props.isContentActive() && e.stopPropagation()} ref={ele => this.fixWheelEvents(ele, this._props.isContentActive)}>
                     <div className="schema-header-row" style={{ height: this.rowHeightFunc() }}>
                         <div className="row-menu" style={{ width: CollectionSchemaView._rowMenuWidth }}>
                             <IconButton
diff --git a/src/client/views/nodes/DiagramBox.tsx b/src/client/views/nodes/DiagramBox.tsx
index 3b666bad5..7cfccf0dc 100644
--- a/src/client/views/nodes/DiagramBox.tsx
+++ b/src/client/views/nodes/DiagramBox.tsx
@@ -185,11 +185,6 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
         return '( )';
     };
 
-    /**
-     * This stops scroll wheel events when they are used to scroll the face collection.
-     */
-    onPassiveWheel = (e: WheelEvent) => e.stopPropagation();
-
     render() {
         return (
             <div
@@ -197,12 +192,7 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
                 style={{
                     pointerEvents: this._props.isContentActive() ? undefined : 'none',
                 }}
-                ref={action((ele: HTMLDivElement | null) => {
-                    this._boxRef?.removeEventListener('wheel', this.onPassiveWheel);
-                    this._boxRef = ele;
-                    // prevent wheel events from passively propagating up through containers and prevents containers from preventDefault which would block scrolling
-                    ele?.addEventListener('wheel', this.onPassiveWheel, { passive: false });
-                })}>
+                ref={r => this.fixWheelEvents(r, this._props.isContentActive)}>
                 <div className="DIYNodeBox-searchbar">
                     <input type="text" value={this._inputValue} onKeyDown={action(e => e.key === 'Enter' && this.generateMermaidCode())} onChange={action(e => (this._inputValue = e.target.value))} />
                     <button type="button" onClick={this.generateMermaidCode}>
diff --git a/src/client/views/nodes/calendarBox/CalendarBox.tsx b/src/client/views/nodes/calendarBox/CalendarBox.tsx
index fa863e123..2b20a666d 100644
--- a/src/client/views/nodes/calendarBox/CalendarBox.tsx
+++ b/src/client/views/nodes/calendarBox/CalendarBox.tsx
@@ -24,7 +24,6 @@ type CalendarView = 'multiMonth' | 'dayGridMonth' | 'timeGridWeek' | 'timeGridDa
 export class CalendarBox extends CollectionSubView() {
     _calendarRef: HTMLDivElement | null = null;
     _calendar: Calendar | undefined;
-    _oldWheel: HTMLElement | null = null;
     _observer: ResizeObserver | undefined;
     _eventsDisposer: IReactionDisposer | undefined;
     _selectDisposer: IReactionDisposer | undefined;
@@ -194,7 +193,6 @@ export class CalendarBox extends CollectionSubView() {
         setTimeout(() => cal?.view.calendar.select(this.dateSelect.start, this.dateSelect.end));
     };
 
-    onPassiveWheel = (e: WheelEvent) => e.stopPropagation();
     render() {
         return (
             <div
@@ -218,10 +216,7 @@ export class CalendarBox extends CollectionSubView() {
                 }}
                 ref={r => {
                     this.createDashEventsTarget(r);
-                    this._oldWheel?.removeEventListener('wheel', this.onPassiveWheel);
-                    this._oldWheel = r;
-                    // prevent wheel events from passively propagating up through containers and prevents containers from preventDefault which would block scrolling
-                    r?.addEventListener('wheel', this.onPassiveWheel, { passive: false });
+                    this.fixWheelEvents(r, this._props.isContentActive);
 
                     if (r) {
                         this._observer?.disconnect();
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index d6fa3172d..c51f6c38b 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -2120,11 +2120,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
         ) : styleFromLayout?.height === '0px' ? null : (
             <div
                 className="formattedTextBox"
-                ref={r => {
-                    this._oldWheel?.removeEventListener('wheel', this.onPassiveWheel);
-                    this._oldWheel = r;
-                    r?.addEventListener('wheel', this.onPassiveWheel, { passive: false });
-                }}
+                ref={r => this.fixWheelEvents(r, this._props.isContentActive, this.onPassiveWheel)}
                 style={{
                     ...(this._props.dontScale
                         ? {}
-- 
cgit v1.2.3-70-g09d2

