From 69de8c235a6580ac222ef3f5b31746f6bc144659 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Tue, 28 Apr 2020 10:48:16 -0400
Subject: rearranged text files

---
 .../formattedText/FormattedTextBoxComment.tsx      | 236 +++++++++++++++++++++
 1 file changed, 236 insertions(+)
 create mode 100644 src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx

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

diff --git a/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx b/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx
new file mode 100644
index 000000000..f9e4c5210
--- /dev/null
+++ b/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx
@@ -0,0 +1,236 @@
+import { Mark, ResolvedPos } from "prosemirror-model";
+import { EditorState, Plugin } from "prosemirror-state";
+import { EditorView } from "prosemirror-view";
+import * as ReactDOM from 'react-dom';
+import { Doc, DocCastAsync } from "../../../../new_fields/Doc";
+import { Cast, FieldValue, NumCast } from "../../../../new_fields/Types";
+import { emptyFunction, returnEmptyString, returnFalse, Utils, emptyPath } from "../../../../Utils";
+import { DocServer } from "../../../DocServer";
+import { DocumentManager } from "../../../util/DocumentManager";
+import { schema } from "./schema_rts";
+import { Transform } from "../../../util/Transform";
+import { ContentFittingDocumentView } from "../ContentFittingDocumentView";
+import { FormattedTextBox } from "./FormattedTextBox";
+import './FormattedTextBoxComment.scss';
+import React = require("react");
+import { Docs } from "../../../documents/Documents";
+import wiki from "wikijs";
+import { DocumentType } from "../../../documents/DocumentTypes";
+
+export let formattedTextBoxCommentPlugin = new Plugin({
+    view(editorView) { return new FormattedTextBoxComment(editorView); }
+});
+export function findOtherUserMark(marks: Mark[]): Mark | undefined {
+    return marks.find(m => m.attrs.userid && m.attrs.userid !== Doc.CurrentUserEmail);
+}
+export function findUserMark(marks: Mark[]): Mark | undefined {
+    return marks.find(m => m.attrs.userid);
+}
+export function findLinkMark(marks: Mark[]): Mark | undefined {
+    return marks.find(m => m.type === schema.marks.link);
+}
+export function findStartOfMark(rpos: ResolvedPos, view: EditorView, finder: (marks: Mark[]) => Mark | undefined) {
+    let before = 0;
+    let nbef = rpos.nodeBefore;
+    while (nbef && finder(nbef.marks)) {
+        before += nbef.nodeSize;
+        rpos = view.state.doc.resolve(rpos.pos - nbef.nodeSize);
+        rpos && (nbef = rpos.nodeBefore);
+    }
+    return before;
+}
+export function findEndOfMark(rpos: ResolvedPos, view: EditorView, finder: (marks: Mark[]) => Mark | undefined) {
+    let after = 0;
+    let naft = rpos.nodeAfter;
+    while (naft && finder(naft.marks)) {
+        after += naft.nodeSize;
+        rpos = view.state.doc.resolve(rpos.pos + naft.nodeSize);
+        rpos && (naft = rpos.nodeAfter);
+    }
+    return after;
+}
+
+
+export class FormattedTextBoxComment {
+    static tooltip: HTMLElement;
+    static tooltipText: HTMLElement;
+    static tooltipInput: HTMLInputElement;
+    static start: number;
+    static end: number;
+    static mark: Mark;
+    static textBox: FormattedTextBox | undefined;
+    static linkDoc: Doc | undefined;
+    constructor(view: any) {
+        if (!FormattedTextBoxComment.tooltip) {
+            const root = document.getElementById("root");
+            FormattedTextBoxComment.tooltipInput = document.createElement("input");
+            FormattedTextBoxComment.tooltipInput.type = "checkbox";
+            FormattedTextBoxComment.tooltip = document.createElement("div");
+            FormattedTextBoxComment.tooltipText = document.createElement("div");
+            FormattedTextBoxComment.tooltipText.style.width = "100%";
+            FormattedTextBoxComment.tooltipText.style.height = "100%";
+            FormattedTextBoxComment.tooltipText.style.textOverflow = "ellipsis";
+            FormattedTextBoxComment.tooltip.appendChild(FormattedTextBoxComment.tooltipText);
+            FormattedTextBoxComment.tooltip.className = "FormattedTextBox-tooltip";
+            FormattedTextBoxComment.tooltip.style.pointerEvents = "all";
+            FormattedTextBoxComment.tooltip.style.maxWidth = "350px";
+            FormattedTextBoxComment.tooltip.style.maxHeight = "250px";
+            FormattedTextBoxComment.tooltip.style.width = "100%";
+            FormattedTextBoxComment.tooltip.style.height = "100%";
+            FormattedTextBoxComment.tooltip.style.overflow = "hidden";
+            FormattedTextBoxComment.tooltip.style.display = "none";
+            FormattedTextBoxComment.tooltip.appendChild(FormattedTextBoxComment.tooltipInput);
+            FormattedTextBoxComment.tooltip.onpointerdown = (e: PointerEvent) => {
+                const keep = e.target && (e.target as any).type === "checkbox" ? true : false;
+                const textBox = FormattedTextBoxComment.textBox;
+                if (FormattedTextBoxComment.linkDoc && !keep && textBox) {
+                    if (FormattedTextBoxComment.linkDoc.type !== DocumentType.LINK) {
+                        textBox.props.addDocTab(FormattedTextBoxComment.linkDoc, e.ctrlKey ? "inTab" : "onRight");
+                    } else {
+                        DocumentManager.Instance.FollowLink(FormattedTextBoxComment.linkDoc, textBox.props.Document,
+                            (doc: Doc, followLinkLocation: string) => textBox.props.addDocTab(doc, e.ctrlKey ? "inTab" : followLinkLocation));
+                    }
+                } else if (textBox && (FormattedTextBoxComment.tooltipText as any).href) {
+                    textBox.props.addDocTab(Docs.Create.WebDocument((FormattedTextBoxComment.tooltipText as any).href, { title: (FormattedTextBoxComment.tooltipText as any).href, _width: 200, _height: 400 }), "onRight");
+                }
+                keep && textBox && FormattedTextBoxComment.start !== undefined && textBox.adoptAnnotation(
+                    FormattedTextBoxComment.start, FormattedTextBoxComment.end, FormattedTextBoxComment.mark);
+                e.stopPropagation();
+                e.preventDefault();
+            };
+            root && root.appendChild(FormattedTextBoxComment.tooltip);
+        }
+    }
+
+    public static Hide() {
+        FormattedTextBoxComment.textBox = undefined;
+        FormattedTextBoxComment.tooltip && (FormattedTextBoxComment.tooltip.style.display = "none");
+        ReactDOM.unmountComponentAtNode(FormattedTextBoxComment.tooltipText);
+    }
+    public static SetState(textBox: any, start: number, end: number, mark: Mark) {
+        FormattedTextBoxComment.textBox = textBox;
+        FormattedTextBoxComment.start = start;
+        FormattedTextBoxComment.end = end;
+        FormattedTextBoxComment.mark = mark;
+        FormattedTextBoxComment.tooltip && (FormattedTextBoxComment.tooltip.style.display = "");
+    }
+
+    static update(view: EditorView, lastState?: EditorState) {
+        const state = view.state;
+        // Don't do anything if the document/selection didn't change
+        if (lastState && lastState.doc.eq(state.doc) &&
+            lastState.selection.eq(state.selection)) {
+            return;
+        }
+        FormattedTextBoxComment.linkDoc = undefined;
+
+        const textBox = FormattedTextBoxComment.textBox;
+        if (!textBox || !textBox.props) {
+            return;
+        }
+        let set = "none";
+        let nbef = 0;
+        FormattedTextBoxComment.tooltipInput.style.display = "none";
+        FormattedTextBoxComment.tooltip.style.width = "";
+        FormattedTextBoxComment.tooltip.style.height = "";
+        (FormattedTextBoxComment.tooltipText as any).href = "";
+        FormattedTextBoxComment.tooltipText.style.whiteSpace = "";
+        FormattedTextBoxComment.tooltipText.style.overflow = "";
+        // this section checks to see if the insertion point is over text entered by a different user.  If so, it sets ths comment text to indicate the user and the modification date
+        if (state.selection.$from) {
+            nbef = findStartOfMark(state.selection.$from, view, findOtherUserMark);
+            const naft = findEndOfMark(state.selection.$from, view, findOtherUserMark);
+            const noselection = view.state.selection.$from === view.state.selection.$to;
+            let child: any = null;
+            state.doc.nodesBetween(state.selection.from, state.selection.to, (node: any, pos: number, parent: any) => !child && node.marks.length && (child = node));
+            const mark = child && findOtherUserMark(child.marks);
+            if (mark && child && (nbef || naft) && (!mark.attrs.opened || noselection)) {
+                FormattedTextBoxComment.SetState(FormattedTextBoxComment.textBox, state.selection.$from.pos - nbef, state.selection.$from.pos + naft, mark);
+            }
+            if (mark && child && ((nbef && naft) || !noselection)) {
+                FormattedTextBoxComment.tooltipText.textContent = mark.attrs.userid + " date=" + (new Date(mark.attrs.modified * 5000)).toDateString();
+                set = "";
+                FormattedTextBoxComment.tooltipInput.style.display = "";
+            }
+        }
+        // this checks if the selection is a hyperlink.  If so, it displays the target doc's text for internal links, and the url of the target for external links. 
+        if (set === "none" && state.selection.$from) {
+            nbef = findStartOfMark(state.selection.$from, view, findLinkMark);
+            const naft = findEndOfMark(state.selection.$from, view, findLinkMark);
+            let child: any = null;
+            state.doc.nodesBetween(state.selection.from, state.selection.to, (node: any, pos: number, parent: any) => !child && node.marks.length && (child = node));
+            const mark = child && findLinkMark(child.marks);
+            if (mark && child && nbef && naft && mark.attrs.showPreview) {
+                FormattedTextBoxComment.tooltipText.textContent = "external => " + mark.attrs.href;
+                (FormattedTextBoxComment.tooltipText as any).href = mark.attrs.href;
+                if (mark.attrs.href.startsWith("https://en.wikipedia.org/wiki/")) {
+                    wiki().page(mark.attrs.href.replace("https://en.wikipedia.org/wiki/", "")).then(page => page.summary().then(summary => FormattedTextBoxComment.tooltipText.textContent = summary.substring(0, 500)));
+                } else {
+                    FormattedTextBoxComment.tooltipText.style.whiteSpace = "pre";
+                    FormattedTextBoxComment.tooltipText.style.overflow = "hidden";
+                }
+                if (mark.attrs.href.indexOf(Utils.prepend("/doc/")) === 0) {
+                    FormattedTextBoxComment.tooltipText.textContent = "target not found...";
+                    (FormattedTextBoxComment.tooltipText as any).href = "";
+                    const docTarget = mark.attrs.href.replace(Utils.prepend("/doc/"), "").split("?")[0];
+                    try {
+                        ReactDOM.unmountComponentAtNode(FormattedTextBoxComment.tooltipText);
+                    } catch (e) { }
+                    docTarget && DocServer.GetRefField(docTarget).then(async linkDoc => {
+                        if (linkDoc instanceof Doc) {
+                            (FormattedTextBoxComment.tooltipText as any).href = mark.attrs.href;
+                            FormattedTextBoxComment.linkDoc = linkDoc;
+                            const anchor = FieldValue(Doc.AreProtosEqual(FieldValue(Cast(linkDoc.anchor1, Doc)), textBox.dataDoc) ? Cast(linkDoc.anchor2, Doc) : (Cast(linkDoc.anchor1, Doc)) || linkDoc);
+                            const target = anchor?.annotationOn ? await DocCastAsync(anchor.annotationOn) : anchor;
+                            if (anchor !== target && anchor && target) {
+                                target.scrollY = NumCast(anchor?.y);
+                            }
+                            if (target) {
+                                ReactDOM.render(<ContentFittingDocumentView
+                                    Document={target}
+                                    LibraryPath={emptyPath}
+                                    fitToBox={true}
+                                    moveDocument={returnFalse}
+                                    rootSelected={returnFalse}
+                                    getTransform={Transform.Identity}
+                                    active={returnFalse}
+                                    addDocument={returnFalse}
+                                    removeDocument={returnFalse}
+                                    addDocTab={returnFalse}
+                                    pinToPres={returnFalse}
+                                    dontRegisterView={true}
+                                    renderDepth={1}
+                                    PanelWidth={() => Math.min(350, NumCast(target._width, 350))}
+                                    PanelHeight={() => Math.min(250, NumCast(target._height, 250))}
+                                    focus={emptyFunction}
+                                    whenActiveChanged={returnFalse}
+                                />, FormattedTextBoxComment.tooltipText);
+                                FormattedTextBoxComment.tooltip.style.width = NumCast(target.width) ? `${NumCast(target.width)}` : "100%";
+                                FormattedTextBoxComment.tooltip.style.height = NumCast(target.height) ? `${NumCast(target.height)}` : "100%";
+                            }
+                            // let ext = (target && target.type !== DocumentType.PDFANNO && Doc.fieldExtensionDoc(target, "data")) || target; // try guessing that the target doc's data is in the 'data' field.  probably need an 'overviewLayout' and then just display the target Document ....
+                            // let text = ext && StrCast(ext.text);
+                            // ext && (FormattedTextBoxComment.tooltipText.textContent = (target && target.type === DocumentType.PDFANNO ? "Quoted from " : "") + "=> " + (text || StrCast(ext.title)));
+                        }
+                    });
+                }
+                set = "";
+            }
+        }
+        if (set !== "none") {
+            // These are in screen coordinates
+            // let start = view.coordsAtPos(state.selection.from), end = view.coordsAtPos(state.selection.to);
+            const start = view.coordsAtPos(state.selection.from - nbef), end = view.coordsAtPos(state.selection.from - nbef);
+            // The box in which the tooltip is positioned, to use as base
+            const box = (document.getElementsByClassName("mainView-container") as any)[0].getBoundingClientRect();
+            // Find a center-ish x position from the selection endpoints (when
+            // crossing lines, end may be more to the left)
+            const left = Math.max((start.left + end.left) / 2, start.left + 3);
+            FormattedTextBoxComment.tooltip.style.left = (left - box.left) + "px";
+            FormattedTextBoxComment.tooltip.style.bottom = (box.bottom - start.top) + "px";
+        }
+        FormattedTextBoxComment.tooltip && (FormattedTextBoxComment.tooltip.style.display = set);
+    }
+
+    destroy() { }
+}
-- 
cgit v1.2.3-70-g09d2


From ff7c7d40b1fcdf74b539c7d97f36707ff1521d2e Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Fri, 1 May 2020 01:46:07 -0400
Subject: fixed presentations to allow drag and drop.  fixed pres box to use
 RenderData instead of modifying presentation elements with unnecessary info
 like their containing PresBox and their presentation index position. 
 COnverted COntentFIttingDocumentView to use DocumentView's props

---
 src/client/documents/Documents.ts                  |  1 +
 src/client/views/MainView.tsx                      |  4 +-
 src/client/views/SearchDocBox.tsx                  | 10 ++++-
 .../views/collections/CollectionCarouselView.tsx   |  8 +++-
 .../views/collections/CollectionSchemaView.tsx     | 14 ++++---
 .../views/collections/CollectionStackingView.tsx   | 15 ++++---
 .../views/collections/CollectionTreeView.tsx       | 20 +++++----
 src/client/views/collections/CollectionView.tsx    | 14 ++++---
 .../collectionFreeForm/CollectionFreeFormView.tsx  |  3 +-
 .../CollectionMulticolumnView.tsx                  | 14 ++++---
 .../CollectionMultirowView.tsx                     | 14 ++++---
 .../views/nodes/CollectionFreeFormDocumentView.tsx |  8 ++--
 .../views/nodes/ContentFittingDocumentView.tsx     | 49 ++++------------------
 src/client/views/nodes/DocumentBox.tsx             | 15 ++++---
 src/client/views/nodes/DocumentView.tsx            | 20 ++++-----
 src/client/views/nodes/FieldView.tsx               |  1 +
 src/client/views/nodes/PresBox.tsx                 | 21 ++++------
 .../formattedText/FormattedTextBoxComment.tsx      | 12 ++++--
 .../views/nodes/formattedText/RichTextMenu.scss    |  3 ++
 .../views/presentationview/PresElementBox.tsx      | 25 +++++++----
 src/client/views/search/SearchItem.tsx             | 12 ++++--
 src/new_fields/documentSchemas.ts                  |  2 +-
 .../authentication/models/current_user_utils.ts    |  2 +-
 23 files changed, 150 insertions(+), 137 deletions(-)

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

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 2e81d5fa6..228a6af97 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -81,6 +81,7 @@ export interface DocumentOptions {
     author?: string;
     dropAction?: dropActionType;
     childDropAction?: dropActionType;
+    targetDropAction?: dropActionType;
     layoutKey?: string;
     type?: string;
     title?: string;
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 65e4eb036..a29a6baac 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -597,8 +597,8 @@ export class MainView extends React.Component {
             {// TO VIEW SNAP LINES
                 <div className="snapLines" style={{ position: "absolute", top: 0, left: 0, width: "100%", height: "100%", pointerEvents: "none" }}>
                     <svg style={{ width: "100%", height: "100%" }}>
-                        {this._hLines?.map(l => <line x1="0" y1={l} x2="2000" y2={l} stroke="black" opacity={0.3} strokeWidth={0.5} strokeDasharray={"1 1"} />)}
-                        {this._vLines?.map(l => <line y1="0" x1={l} y2="2000" x2={l} stroke="black" opacity={0.3} strokeWidth={0.5} strokeDasharray={"1 1"} />)}
+                        {this._hLines?.map((l: any) => <line x1="0" y1={l} x2="2000" y2={l} stroke="black" opacity={0.3} strokeWidth={0.5} strokeDasharray={"1 1"} />)}
+                        {this._vLines?.map((l: any) => <line y1="0" x1={l} y2="2000" x2={l} stroke="black" opacity={0.3} strokeWidth={0.5} strokeDasharray={"1 1"} />)}
                     </svg>
                 </div>}
             <TimelineMenu />
diff --git a/src/client/views/SearchDocBox.tsx b/src/client/views/SearchDocBox.tsx
index 799fa9d85..7bd689b19 100644
--- a/src/client/views/SearchDocBox.tsx
+++ b/src/client/views/SearchDocBox.tsx
@@ -6,7 +6,7 @@ import { observer } from "mobx-react";
 import { Doc, DocListCast } from "../../new_fields/Doc";
 import { Id } from "../../new_fields/FieldSymbols";
 import { BoolCast, Cast, NumCast, StrCast } from "../../new_fields/Types";
-import { returnFalse } from "../../Utils";
+import { returnFalse, returnZero } from "../../Utils";
 import { Docs } from "../documents/Documents";
 import { SearchUtil } from "../util/SearchUtil";
 import { EditableView } from "./EditableView";
@@ -399,7 +399,13 @@ export class SearchDocBox extends React.Component<FieldViewProps> {
                 <ContentFittingDocumentView {...this.props}
                     Document={this.content}
                     rootSelected={returnFalse}
-                    getTransform={this.props.ScreenToLocalTransform}>
+                    bringToFront={returnFalse}
+                    ContainingCollectionDoc={undefined}
+                    ContainingCollectionView={undefined}
+                    NativeWidth={returnZero}
+                    NativeHeight={returnZero}
+                    parentActive={this.props.active}
+                    ScreenToLocalTransform={this.props.ScreenToLocalTransform}>
                 </ContentFittingDocumentView>
                 <div
                     style={{
diff --git a/src/client/views/collections/CollectionCarouselView.tsx b/src/client/views/collections/CollectionCarouselView.tsx
index eda8e5684..bfb7134b2 100644
--- a/src/client/views/collections/CollectionCarouselView.tsx
+++ b/src/client/views/collections/CollectionCarouselView.tsx
@@ -14,6 +14,7 @@ import { Doc } from '../../../new_fields/Doc';
 import { FormattedTextBox } from '../nodes/formattedText/FormattedTextBox';
 import { ContextMenu } from '../ContextMenu';
 import { ObjectField } from '../../../new_fields/ObjectField';
+import { returnFalse } from '../../../Utils';
 
 type CarouselDocument = makeInterface<[typeof documentSchema,]>;
 const CarouselDocument = makeInterface(documentSchema);
@@ -49,9 +50,12 @@ export class CollectionCarouselView extends CollectionSubView(CarouselDocument)
                     <ContentFittingDocumentView {...this.props}
                         renderDepth={this.props.renderDepth + 1}
                         Document={this.childLayoutPairs[index].layout}
-                        DataDocument={this.childLayoutPairs[index].data}
+                        DataDoc={this.childLayoutPairs[index].data}
                         PanelHeight={this.panelHeight}
-                        getTransform={this.props.ScreenToLocalTransform} />
+                        ScreenToLocalTransform={this.props.ScreenToLocalTransform}
+                        bringToFront={returnFalse}
+                        parentActive={this.props.active}
+                    />
                 </div>
                 <div className="collectionCarouselView-caption" key="caption"
                     style={{
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 380d91d2f..c0024293f 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -27,7 +27,7 @@ import "./CollectionSchemaView.scss";
 import { CollectionSubView } from "./CollectionSubView";
 import { CollectionView } from "./CollectionView";
 import { ContentFittingDocumentView } from "../nodes/ContentFittingDocumentView";
-import { setupMoveUpEvents, emptyFunction, returnZero, returnOne } from "../../../Utils";
+import { setupMoveUpEvents, emptyFunction, returnZero, returnOne, returnFalse } from "../../../Utils";
 import { DocumentView } from "../nodes/DocumentView";
 
 library.add(faCog, faPlus, faSortUp, faSortDown);
@@ -121,7 +121,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
             {!this.previewDocument ? (null) :
                 <ContentFittingDocumentView
                     Document={this.previewDocument}
-                    DataDocument={undefined}
+                    DataDoc={undefined}
                     NativeHeight={returnZero}
                     NativeWidth={returnZero}
                     fitToBox={true}
@@ -132,16 +132,18 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
                     rootSelected={this.rootSelected}
                     PanelWidth={this.previewWidth}
                     PanelHeight={this.previewHeight}
-                    getTransform={this.getPreviewTransform}
-                    CollectionDoc={this.props.CollectionView?.props.Document}
-                    CollectionView={this.props.CollectionView}
+                    ScreenToLocalTransform={this.getPreviewTransform}
+                    ContainingCollectionDoc={this.props.CollectionView?.props.Document}
+                    ContainingCollectionView={this.props.CollectionView}
                     moveDocument={this.props.moveDocument}
                     addDocument={this.props.addDocument}
                     removeDocument={this.props.removeDocument}
-                    active={this.props.active}
+                    parentActive={this.props.active}
                     whenActiveChanged={this.props.whenActiveChanged}
                     addDocTab={this.props.addDocTab}
                     pinToPres={this.props.pinToPres}
+                    bringToFront={returnFalse}
+                    ContentScaling={returnOne}
                 />}
         </div>;
     }
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index 556d7df5c..6c230d5b1 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -11,7 +11,7 @@ import { listSpec } from "../../../new_fields/Schema";
 import { SchemaHeaderField } from "../../../new_fields/SchemaHeaderField";
 import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from "../../../new_fields/Types";
 import { TraceMobx } from "../../../new_fields/util";
-import { Utils, setupMoveUpEvents, emptyFunction, returnZero, returnOne } from "../../../Utils";
+import { Utils, setupMoveUpEvents, emptyFunction, returnZero, returnOne, returnFalse } from "../../../Utils";
 import { DragManager, dropActionType } from "../../util/DragManager";
 import { Transform } from "../../util/Transform";
 import { undoBatch } from "../../util/UndoManager";
@@ -165,12 +165,13 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
         const height = () => this.getDocHeight(doc);
         return <ContentFittingDocumentView
             Document={doc}
-            DataDocument={dataDoc || (doc[DataSym] !== doc && doc[DataSym])}
+            DataDoc={dataDoc || (doc[DataSym] !== doc && doc[DataSym])}
             backgroundColor={this.props.backgroundColor}
             LayoutDoc={this.props.childLayoutTemplate}
             LibraryPath={this.props.LibraryPath}
             FreezeDimensions={this.props.freezeChildDimensions}
             renderDepth={this.props.renderDepth + 1}
+            RenderData={this.props.RenderData}
             PanelWidth={width}
             PanelHeight={height}
             NativeHeight={returnZero}
@@ -180,16 +181,18 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
             dropAction={StrCast(this.props.Document.childDropAction) as dropActionType}
             onClick={this.onChildClickHandler}
             onDoubleClick={this.onChildDoubleClickHandler}
-            getTransform={dxf}
+            ScreenToLocalTransform={dxf}
             focus={this.props.focus}
-            CollectionDoc={this.props.CollectionView?.props.Document}
-            CollectionView={this.props.CollectionView}
+            ContainingCollectionDoc={this.props.CollectionView?.props.Document}
+            ContainingCollectionView={this.props.CollectionView}
             addDocument={this.props.addDocument}
             moveDocument={this.props.moveDocument}
             removeDocument={this.props.removeDocument}
-            active={this.props.active}
+            parentActive={this.props.active}
             whenActiveChanged={this.props.whenActiveChanged}
             addDocTab={this.addDocTab}
+            bringToFront={returnFalse}
+            ContentScaling={returnOne}
             pinToPres={this.props.pinToPres}
         />;
     }
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index d938bd7ad..71358a8ec 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -353,27 +353,31 @@ class TreeView extends React.Component<TreeViewProps> {
             return <div ref={this._dref} style={{ display: "inline-block", height: panelHeight() }} key={this.props.document[Id] + this.props.document.title}>
                 <ContentFittingDocumentView
                     Document={layoutDoc}
-                    DataDocument={this.templateDataDoc}
+                    DataDoc={this.templateDataDoc}
                     LibraryPath={emptyPath}
                     renderDepth={this.props.renderDepth + 1}
                     rootSelected={returnTrue}
                     backgroundColor={this.props.backgroundColor}
                     fitToBox={this.boundsOfCollectionDocument !== undefined}
                     FreezeDimensions={true}
-                    NativeWidth={layoutDoc.type === DocumentType.RTF ? this.rtfWidth : undefined}
-                    NativeHeight={layoutDoc.type === DocumentType.RTF ? this.rtfHeight : undefined}
+                    NativeWidth={layoutDoc.type === DocumentType.RTF ? this.rtfWidth : returnZero}
+                    NativeHeight={layoutDoc.type === DocumentType.RTF ? this.rtfHeight : returnZero}
                     PanelWidth={panelWidth}
                     PanelHeight={panelHeight}
-                    getTransform={this.docTransform}
-                    CollectionDoc={this.props.containingCollection}
-                    CollectionView={undefined}
+                    focus={returnFalse}
+                    ScreenToLocalTransform={this.docTransform}
+                    ContainingCollectionDoc={this.props.containingCollection}
+                    ContainingCollectionView={undefined}
                     addDocument={returnFalse}
                     moveDocument={this.props.moveDocument}
                     removeDocument={returnFalse}
-                    active={this.props.active}
+                    parentActive={this.props.active}
                     whenActiveChanged={emptyFunction}
                     addDocTab={this.props.addDocTab}
-                    pinToPres={this.props.pinToPres} />
+                    pinToPres={this.props.pinToPres}
+                    bringToFront={returnFalse}
+                    ContentScaling={returnOne}
+                />
             </div>;
         }
     }
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index 8d8c321e8..561226de5 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -113,12 +113,16 @@ export class CollectionView extends Touchable<FieldViewProps> {
 
     @action.bound
     addDocument(doc: Doc): boolean {
-        const targetDataDoc = this.props.Document[DataSym];
-        const docList = DocListCast(targetDataDoc[this.props.fieldKey]);
-        !docList.includes(doc) && (targetDataDoc[this.props.fieldKey] = new List<Doc>([...docList, doc]));  // DocAddToList may write to targetdataDoc's parent ... we don't want this. should really change GetProto to GetDataDoc and test for resolvedDataDoc there
-        // Doc.AddDocToList(targetDataDoc, this.props.fieldKey, doc);
+        if (this.props.addDocument) {
+            this.props.addDocument(doc);
+        } else {
+            const targetDataDoc = this.props.Document[DataSym];
+            const docList = DocListCast(targetDataDoc[this.props.fieldKey]);
+            !docList.includes(doc) && (targetDataDoc[this.props.fieldKey] = new List<Doc>([...docList, doc]));  // DocAddToList may write to targetdataDoc's parent ... we don't want this. should really change GetProto to GetDataDoc and test for resolvedDataDoc there
+            // Doc.AddDocToList(targetDataDoc, this.props.fieldKey, doc);
+            targetDataDoc[this.props.fieldKey + "-lastModified"] = new DateField(new Date(Date.now()));
+        }
         doc.context = this.props.Document;
-        targetDataDoc[this.props.fieldKey + "-lastModified"] = new DateField(new Date(Date.now()));
         Doc.GetProto(doc).lastOpened = new DateField;
         return true;
     }
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 763a6c605..b4eb22444 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -877,6 +877,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
             onDoubleClick: this.onChildDoubleClickHandler,
             ScreenToLocalTransform: childLayout.z ? this.getTransformOverlay : this.getTransform,
             renderDepth: this.props.renderDepth + 1,
+            RenderData: this.props.RenderData,
             PanelWidth: childLayout[WidthSym],
             PanelHeight: childLayout[HeightSym],
             ContentScaling: returnOne,
@@ -1176,7 +1177,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
     }
     onPointerOver = (e: React.PointerEvent) => {
         if (SelectionManager.GetIsDragging()) {
-            this.setupDragLines(e);
+            this.setupDragLines();
         }
         e.stopPropagation();
     }
diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx
index 66d441115..b3a6a9deb 100644
--- a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx
+++ b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx
@@ -14,7 +14,7 @@ import "./collectionMulticolumnView.scss";
 import ResizeBar from './MulticolumnResizer';
 import WidthLabel from './MulticolumnWidthLabel';
 import { List } from '../../../../new_fields/List';
-import { returnZero } from '../../../../Utils';
+import { returnZero, returnFalse, returnOne } from '../../../../Utils';
 
 type MulticolumnDocument = makeInterface<[typeof documentSchema]>;
 const MulticolumnDocument = makeInterface(documentSchema);
@@ -216,7 +216,7 @@ export class CollectionMulticolumnView extends CollectionSubView(MulticolumnDocu
     getDisplayDoc(layout: Doc, dxf: () => Transform, width: () => number, height: () => number) {
         return <ContentFittingDocumentView
             Document={layout}
-            DataDocument={layout.resolvedDataDoc as Doc}
+            DataDoc={layout.resolvedDataDoc as Doc}
             backgroundColor={this.props.backgroundColor}
             LayoutDoc={this.props.childLayoutTemplate}
             LibraryPath={this.props.LibraryPath}
@@ -231,17 +231,19 @@ export class CollectionMulticolumnView extends CollectionSubView(MulticolumnDocu
             dropAction={StrCast(this.props.Document.childDropAction) as dropActionType}
             onClick={this.onChildClickHandler}
             onDoubleClick={this.onChildDoubleClickHandler}
-            getTransform={dxf}
+            ScreenToLocalTransform={dxf}
             focus={this.props.focus}
-            CollectionDoc={this.props.CollectionView?.props.Document}
-            CollectionView={this.props.CollectionView}
+            ContainingCollectionDoc={this.props.CollectionView?.props.Document}
+            ContainingCollectionView={this.props.CollectionView}
             addDocument={this.props.addDocument}
             moveDocument={this.props.moveDocument}
             removeDocument={this.props.removeDocument}
-            active={this.props.active}
+            parentActive={this.props.active}
             whenActiveChanged={this.props.whenActiveChanged}
             addDocTab={this.addDocTab}
             pinToPres={this.props.pinToPres}
+            bringToFront={returnFalse}
+            ContentScaling={returnOne}
         />;
     }
     /**
diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx b/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx
index 615efdb39..0fb29ca61 100644
--- a/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx
+++ b/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx
@@ -6,7 +6,7 @@ import * as React from "react";
 import { Doc } from '../../../../new_fields/Doc';
 import { NumCast, StrCast, BoolCast, ScriptCast } from '../../../../new_fields/Types';
 import { ContentFittingDocumentView } from '../../nodes/ContentFittingDocumentView';
-import { Utils, returnZero } from '../../../../Utils';
+import { Utils, returnZero, returnFalse, returnOne } from '../../../../Utils';
 import "./collectionMultirowView.scss";
 import { computed, trace, observable, action } from 'mobx';
 import { Transform } from '../../../util/Transform';
@@ -215,7 +215,7 @@ export class CollectionMultirowView extends CollectionSubView(MultirowDocument)
     getDisplayDoc(layout: Doc, dxf: () => Transform, width: () => number, height: () => number) {
         return <ContentFittingDocumentView
             Document={layout}
-            DataDocument={layout.resolvedDataDoc as Doc}
+            DataDoc={layout.resolvedDataDoc as Doc}
             backgroundColor={this.props.backgroundColor}
             LayoutDoc={this.props.childLayoutTemplate}
             LibraryPath={this.props.LibraryPath}
@@ -230,17 +230,19 @@ export class CollectionMultirowView extends CollectionSubView(MultirowDocument)
             dropAction={StrCast(this.props.Document.childDropAction) as dropActionType}
             onClick={this.onChildClickHandler}
             onDoubleClick={this.onChildDoubleClickHandler}
-            getTransform={dxf}
+            ScreenToLocalTransform={dxf}
             focus={this.props.focus}
-            CollectionDoc={this.props.CollectionView?.props.Document}
-            CollectionView={this.props.CollectionView}
+            ContainingCollectionDoc={this.props.CollectionView?.props.Document}
+            ContainingCollectionView={this.props.CollectionView}
             addDocument={this.props.addDocument}
             moveDocument={this.props.moveDocument}
             removeDocument={this.props.removeDocument}
-            active={this.props.active}
+            parentActive={this.props.active}
             whenActiveChanged={this.props.whenActiveChanged}
             addDocTab={this.addDocTab}
             pinToPres={this.props.pinToPres}
+            bringToFront={returnFalse}
+            ContentScaling={returnOne}
         />;
     }
     /**
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index 1c7d116c5..24468dcc1 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -115,13 +115,11 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
                     PanelWidth={this.panelWidth}
                     PanelHeight={this.panelHeight} />
                 : <ContentFittingDocumentView {...this.props}
-                    CollectionDoc={this.props.ContainingCollectionDoc}
-                    DataDocument={this.props.DataDoc}
-                    getTransform={this.getTransform}
+                    ContainingCollectionDoc={this.props.ContainingCollectionDoc}
+                    DataDoc={this.props.DataDoc}
+                    ScreenToLocalTransform={this.getTransform}
                     NativeHeight={this.NativeHeight}
                     NativeWidth={this.NativeWidth}
-                    active={this.props.parentActive}
-                    focus={this.focusDoc}
                     PanelWidth={this.panelWidth}
                     PanelHeight={this.panelHeight}
                 />}
diff --git a/src/client/views/nodes/ContentFittingDocumentView.tsx b/src/client/views/nodes/ContentFittingDocumentView.tsx
index d0b0c8ee6..637fd5acc 100644
--- a/src/client/views/nodes/ContentFittingDocumentView.tsx
+++ b/src/client/views/nodes/ContentFittingDocumentView.tsx
@@ -3,51 +3,16 @@ import { computed } from "mobx";
 import { observer } from "mobx-react";
 import "react-table/react-table.css";
 import { Doc, Opt, WidthSym, HeightSym } from "../../../new_fields/Doc";
-import { ScriptField } from "../../../new_fields/ScriptField";
 import { NumCast, StrCast } from "../../../new_fields/Types";
 import { TraceMobx } from "../../../new_fields/util";
 import { emptyFunction, returnOne } from "../../../Utils";
-import { Transform } from "../../util/Transform";
-import { CollectionView } from "../collections/CollectionView";
 import '../DocumentDecorations.scss';
-import { DocumentView } from "../nodes/DocumentView";
+import { DocumentView, DocumentViewProps } from "../nodes/DocumentView";
 import "./ContentFittingDocumentView.scss";
-import { dropActionType } from "../../util/DragManager";
 
-interface ContentFittingDocumentViewProps {
-    Document: Doc;
-    DataDocument?: Doc;
-    LayoutDoc?: () => Opt<Doc>;
-    NativeWidth?: () => number;
-    NativeHeight?: () => number;
-    FreezeDimensions?: boolean;
-    LibraryPath: Doc[];
-    renderDepth: number;
-    fitToBox?: boolean;
-    layoutKey?: string;
-    dropAction?: dropActionType;
-    PanelWidth: () => number;
-    PanelHeight: () => number;
-    focus?: (doc: Doc) => void;
-    CollectionView?: CollectionView;
-    CollectionDoc?: Doc;
-    onClick?: ScriptField;
-    onDoubleClick?: ScriptField;
-    backgroundColor?: (doc: Doc) => string | undefined;
-    getTransform: () => Transform;
-    addDocument?: (document: Doc) => boolean;
-    moveDocument?: (document: Doc, target: Doc | undefined, addDoc: ((doc: Doc) => boolean)) => boolean;
-    removeDocument?: (document: Doc) => boolean;
-    active: (outsideReaction: boolean) => boolean;
-    whenActiveChanged: (isActive: boolean) => void;
-    addDocTab: (document: Doc, where: string) => boolean;
-    pinToPres: (document: Doc) => void;
-    dontRegisterView?: boolean;
-    rootSelected: (outsideReaction?: boolean) => boolean;
-}
 
 @observer
-export class ContentFittingDocumentView extends React.Component<ContentFittingDocumentViewProps>{
+export class ContentFittingDocumentView extends React.Component<DocumentViewProps>{
     public get displayName() { return "DocumentView(" + this.props.Document?.title + ")"; } // this makes mobx trace() statements more descriptive
     private get layoutDoc() { return this.props.LayoutDoc?.() || Doc.Layout(this.props.Document); }
     @computed get freezeDimensions() { return this.props.FreezeDimensions; }
@@ -68,7 +33,7 @@ export class ContentFittingDocumentView extends React.Component<ContentFittingDo
     @computed get panelWidth() { return this.nativeWidth && !this.props.Document._fitWidth ? this.nativeWidth() * this.contentScaling() : this.props.PanelWidth(); }
     @computed get panelHeight() { return this.nativeHeight && !this.props.Document._fitWidth ? this.nativeHeight() * this.contentScaling() : this.props.PanelHeight(); }
 
-    private getTransform = () => this.props.getTransform().translate(-this.centeringOffset, -this.centeringYOffset).scale(1 / this.contentScaling());
+    private getTransform = () => this.props.ScreenToLocalTransform().translate(-this.centeringOffset, -this.centeringYOffset).scale(1 / this.contentScaling());
     private get centeringOffset() { return this.nativeWidth() && !this.props.Document._fitWidth ? (this.props.PanelWidth() - this.nativeWidth() * this.contentScaling()) / 2 : 0; }
     private get centeringYOffset() { return Math.abs(this.centeringOffset) < 0.001 ? (this.props.PanelHeight() - this.nativeHeight() * this.contentScaling()) / 2 : 0; }
 
@@ -90,7 +55,7 @@ export class ContentFittingDocumentView extends React.Component<ContentFittingDo
                     }}>
                     <DocumentView {...this.props}
                         Document={this.props.Document}
-                        DataDoc={this.props.DataDocument}
+                        DataDoc={this.props.DataDoc}
                         LayoutDoc={this.props.LayoutDoc}
                         LibraryPath={this.props.LibraryPath}
                         NativeWidth={this.nativeWidth}
@@ -107,11 +72,11 @@ export class ContentFittingDocumentView extends React.Component<ContentFittingDo
                         removeDocument={this.props.removeDocument}
                         moveDocument={this.props.moveDocument}
                         whenActiveChanged={this.props.whenActiveChanged}
-                        ContainingCollectionView={this.props.CollectionView}
-                        ContainingCollectionDoc={this.props.CollectionDoc}
+                        ContainingCollectionView={this.props.ContainingCollectionView}
+                        ContainingCollectionDoc={this.props.ContainingCollectionDoc}
                         addDocTab={this.props.addDocTab}
                         pinToPres={this.props.pinToPres}
-                        parentActive={this.props.active}
+                        parentActive={this.props.parentActive}
                         ScreenToLocalTransform={this.getTransform}
                         renderDepth={this.props.renderDepth}
                         focus={this.props.focus || emptyFunction}
diff --git a/src/client/views/nodes/DocumentBox.tsx b/src/client/views/nodes/DocumentBox.tsx
index d4d997120..88eeb1137 100644
--- a/src/client/views/nodes/DocumentBox.tsx
+++ b/src/client/views/nodes/DocumentBox.tsx
@@ -6,7 +6,7 @@ import { documentSchema } from "../../../new_fields/documentSchemas";
 import { makeInterface } from "../../../new_fields/Schema";
 import { ComputedField } from "../../../new_fields/ScriptField";
 import { Cast, NumCast, StrCast } from "../../../new_fields/Types";
-import { emptyPath } from "../../../Utils";
+import { emptyPath, returnFalse, returnOne, returnZero } from "../../../Utils";
 import { ContextMenu } from "../ContextMenu";
 import { ContextMenuProps } from "../ContextMenuItem";
 import { ViewBoxAnnotatableComponent } from "../DocComponent";
@@ -114,9 +114,10 @@ export class DocHolderBox extends ViewBoxAnnotatableComponent<FieldViewProps, Do
         }
         const contents = !(containedDoc instanceof Doc) ? (null) : <ContentFittingDocumentView
             Document={containedDoc}
-            DataDocument={undefined}
+            DataDoc={undefined}
             LibraryPath={emptyPath}
-            CollectionView={this as any} // bcz: hack!  need to pass a prop that can be used to select the container (ie, 'this') when the up selector in document decorations is clicked.  currently, the up selector allows only a containing collection to be selected
+            ContainingCollectionView={this as any} // bcz: hack!  need to pass a prop that can be used to select the container (ie, 'this') when the up selector in document decorations is clicked.  currently, the up selector allows only a containing collection to be selected
+            ContainingCollectionDoc={undefined}
             fitToBox={true}
             layoutKey={childTemplateName ? "layout_" + childTemplateName : "layout"}
             rootSelected={this.props.isSelected}
@@ -125,14 +126,18 @@ export class DocHolderBox extends ViewBoxAnnotatableComponent<FieldViewProps, Do
             removeDocument={this.props.removeDocument}
             addDocTab={this.props.addDocTab}
             pinToPres={this.props.pinToPres}
-            getTransform={this.getTransform}
+            ScreenToLocalTransform={this.getTransform}
             renderDepth={this.props.renderDepth + 1}
+            NativeHeight={returnZero}
+            NativeWidth={returnZero}
             PanelWidth={this.pwidth}
             PanelHeight={this.pheight}
             focus={this.props.focus}
-            active={this.props.active}
+            parentActive={this.props.active}
             dontRegisterView={!this.isSelectionLocked()}
             whenActiveChanged={this.props.whenActiveChanged}
+            bringToFront={returnFalse}
+            ContentScaling={returnOne}
         />;
         return contents;
     }
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 085637440..f555d6eef 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -77,6 +77,7 @@ export interface DocumentViewProps {
     setupDragLines?: () => void;
     renderDepth: number;
     ContentScaling: () => number;
+    RenderData?: () => Doc;
     PanelWidth: () => number;
     PanelHeight: () => number;
     pointerEvents?: boolean;
@@ -992,6 +993,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
                 LayoutDoc={this.props.LayoutDoc}
                 makeLink={this.makeLink}
                 rootSelected={this.rootSelected}
+                RenderData={this.props.RenderData}
                 dontRegisterView={this.props.dontRegisterView}
                 fitToBox={this.props.fitToBox}
                 LibraryPath={this.props.LibraryPath}
@@ -1112,17 +1114,13 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
             Doc.makeCustomViewClicked(this.props.Document, Docs.Create.StackingDocument, layout, undefined);
         }
     }
-    @observable _animate = 0;
+    @observable _animateScalingTo = 0;
     switchViews = action((custom: boolean, view: string) => {
-        SelectionManager.SetIsDragging(true);
-        this._animate = 0.1;
+        this._animateScalingTo = 0.1;  // shrink doc
         setTimeout(action(() => {
             this.setCustomView(custom, view);
-            this._animate = 1;
-            setTimeout(action(() => {
-                this._animate = 0;
-                SelectionManager.SetIsDragging(false);
-            }), 400);
+            this._animateScalingTo = 1; // expand it
+            setTimeout(action(() => this._animateScalingTo = 0), 400);
         }), 400);
     });
 
@@ -1156,9 +1154,9 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
                 !entered && Doc.UnBrushDoc(this.props.Document);
             })}
             style={{
-                transformOrigin: this._animate ? "center center" : undefined,
-                transform: this._animate ? `scale(${this._animate})` : undefined,
-                transition: !this._animate ? StrCast(this.Document.transition) : this._animate < 1 ? "transform 0.5s ease-in" : "transform 0.5s ease-out",
+                transformOrigin: this._animateScalingTo ? "center center" : undefined,
+                transform: this._animateScalingTo ? `scale(${this._animateScalingTo})` : undefined,
+                transition: !this._animateScalingTo ? StrCast(this.Document.transition) : this._animateScalingTo < 1 ? "transform 0.5s ease-in" : "transform 0.5s ease-out",
                 pointerEvents: this.ignorePointerEvents ? "none" : undefined,
                 color: StrCast(this.layoutDoc.color, "inherit"),
                 outline: highlighting && !borderRounding ? `${highlightColors[fullDegree]} ${highlightStyles[fullDegree]} ${localScale}px` : "solid 0px",
diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx
index 0b9edbcd3..1efee4f5a 100644
--- a/src/client/views/nodes/FieldView.tsx
+++ b/src/client/views/nodes/FieldView.tsx
@@ -56,6 +56,7 @@ export interface FieldViewProps {
     width?: number;
     background?: string;
     color?: string;
+    RenderData?: () => Doc;
 }
 
 @observer
diff --git a/src/client/views/nodes/PresBox.tsx b/src/client/views/nodes/PresBox.tsx
index f91a809bb..3fcc97473 100644
--- a/src/client/views/nodes/PresBox.tsx
+++ b/src/client/views/nodes/PresBox.tsx
@@ -16,6 +16,7 @@ import { FieldView, FieldViewProps } from './FieldView';
 import "./PresBox.scss";
 import { ViewBoxBaseComponent } from "../DocComponent";
 import { makeInterface } from "../../../new_fields/Schema";
+import { List } from "../../../new_fields/List";
 
 type PresBoxSchema = makeInterface<[typeof documentSchema]>;
 const PresBoxDocument = makeInterface(documentSchema);
@@ -23,20 +24,15 @@ const PresBoxDocument = makeInterface(documentSchema);
 @observer
 export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>(PresBoxDocument) {
     public static LayoutString(fieldKey: string) { return FieldView.LayoutString(PresBox, fieldKey); }
-    private _childReaction: IReactionDisposer | undefined;
     @observable _isChildActive = false;
     @computed get childDocs() { return DocListCast(this.dataDoc[this.fieldKey]); }
     @computed get currentIndex() { return NumCast(this.rootDoc._itemIndex); }
 
     componentDidMount() {
+        this.rootDoc.presBox = this.rootDoc;
         this.rootDoc._forceRenderEngine = "timeline";
         this.rootDoc._replacedChrome = "replaced";
-        this._childReaction = reaction(() => this.childDocs.slice(), (children) => children.forEach((child, i) => child.presentationIndex = i), { fireImmediately: true });
     }
-    componentWillUnmount() {
-        this._childReaction?.();
-    }
-
     updateCurrentPresentation = () => Doc.UserDoc().activePresentation = this.rootDoc;
 
     @undoBatch
@@ -247,16 +243,12 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
 
     initializeViewAliases = (docList: Doc[], viewtype: CollectionViewType) => {
         const hgt = (viewtype === CollectionViewType.Tree) ? 50 : 46;
-        docList.forEach(doc => {
-            doc.presBox = this.rootDoc; // give contained documents a reference to the presentation
-            doc.presCollapsedHeight = hgt;  //  set the collpased height for documents based on the type of view (Tree or Stack) they will be displaye din
-        });
+        this.rootDoc.presCollapsedHeight = hgt;
     }
 
     addDocument = (doc: Doc) => {
-        const newPinDoc = Doc.MakeAlias(doc);
-        newPinDoc.presentationTargetDoc = doc;
-        return Doc.AddDocToList(this.dataDoc, this.fieldKey, newPinDoc);
+        doc.presentationTargetDoc = doc.aliasOf;
+        return Doc.AddDocToList(this.dataDoc, this.fieldKey, doc);
     }
 
     removeDocument = (doc: Doc) => Doc.RemoveDocFromList(this.dataDoc, this.fieldKey, doc);
@@ -280,8 +272,10 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
         this.updateMinimize(e, this.rootDoc._viewType = viewType);
     });
 
+    returnSelf = () => this.rootDoc;
     childLayoutTemplate = () => this.rootDoc._viewType === CollectionViewType.Stacking ? Cast(Doc.UserDoc()["template-presentation"], Doc, null) : undefined;
     render() {
+        this.rootDoc.presOrderedDocs = new List<Doc>(this.childDocs.map((child, i) => child));
         const mode = StrCast(this.rootDoc._viewType) as CollectionViewType;
         this.initializeViewAliases(this.childDocs, mode);
         return <div className="presBox-cont" style={{ minWidth: this.layoutDoc.inOverlay ? 240 : undefined }} >
@@ -314,6 +308,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
                         childLayoutTemplate={this.childLayoutTemplate}
                         addDocument={this.addDocument}
                         removeDocument={returnFalse}
+                        RenderData={this.returnSelf}
                         focus={this.selectElement}
                         ScreenToLocalTransform={this.getTransform} />
                     : (null)
diff --git a/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx b/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx
index f9e4c5210..9ad5aafb8 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx
@@ -4,7 +4,7 @@ import { EditorView } from "prosemirror-view";
 import * as ReactDOM from 'react-dom';
 import { Doc, DocCastAsync } from "../../../../new_fields/Doc";
 import { Cast, FieldValue, NumCast } from "../../../../new_fields/Types";
-import { emptyFunction, returnEmptyString, returnFalse, Utils, emptyPath } from "../../../../Utils";
+import { emptyFunction, returnEmptyString, returnFalse, Utils, emptyPath, returnZero, returnOne } from "../../../../Utils";
 import { DocServer } from "../../../DocServer";
 import { DocumentManager } from "../../../util/DocumentManager";
 import { schema } from "./schema_rts";
@@ -192,18 +192,24 @@ export class FormattedTextBoxComment {
                                     fitToBox={true}
                                     moveDocument={returnFalse}
                                     rootSelected={returnFalse}
-                                    getTransform={Transform.Identity}
-                                    active={returnFalse}
+                                    ScreenToLocalTransform={Transform.Identity}
+                                    parentActive={returnFalse}
                                     addDocument={returnFalse}
                                     removeDocument={returnFalse}
                                     addDocTab={returnFalse}
                                     pinToPres={returnFalse}
                                     dontRegisterView={true}
+                                    ContainingCollectionDoc={undefined}
+                                    ContainingCollectionView={undefined}
                                     renderDepth={1}
                                     PanelWidth={() => Math.min(350, NumCast(target._width, 350))}
                                     PanelHeight={() => Math.min(250, NumCast(target._height, 250))}
                                     focus={emptyFunction}
                                     whenActiveChanged={returnFalse}
+                                    bringToFront={returnFalse}
+                                    ContentScaling={returnOne}
+                                    NativeWidth={returnZero}
+                                    NativeHeight={returnZero}
                                 />, FormattedTextBoxComment.tooltipText);
                                 FormattedTextBoxComment.tooltip.style.width = NumCast(target.width) ? `${NumCast(target.width)}` : "100%";
                                 FormattedTextBoxComment.tooltip.style.height = NumCast(target.height) ? `${NumCast(target.height)}` : "100%";
diff --git a/src/client/views/nodes/formattedText/RichTextMenu.scss b/src/client/views/nodes/formattedText/RichTextMenu.scss
index 3a16171de..7a0718c16 100644
--- a/src/client/views/nodes/formattedText/RichTextMenu.scss
+++ b/src/client/views/nodes/formattedText/RichTextMenu.scss
@@ -55,6 +55,9 @@
         color: black;
     }
 
+}
+
+.richTextMenu {
     select {
         background-color: #323232;
         color: white;
diff --git a/src/client/views/presentationview/PresElementBox.tsx b/src/client/views/presentationview/PresElementBox.tsx
index 66f251b93..1887c8d45 100644
--- a/src/client/views/presentationview/PresElementBox.tsx
+++ b/src/client/views/presentationview/PresElementBox.tsx
@@ -1,12 +1,12 @@
 import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
 import { action, computed, IReactionDisposer, reaction } from "mobx";
 import { observer } from "mobx-react";
-import { Doc, DataSym } from "../../../new_fields/Doc";
+import { Doc, DataSym, DocListCast } from "../../../new_fields/Doc";
 import { documentSchema } from '../../../new_fields/documentSchemas';
 import { Id } from "../../../new_fields/FieldSymbols";
 import { createSchema, makeInterface } from '../../../new_fields/Schema';
 import { Cast, NumCast } from "../../../new_fields/Types";
-import { emptyFunction, emptyPath, returnFalse, returnTrue } from "../../../Utils";
+import { emptyFunction, emptyPath, returnFalse, returnTrue, returnOne, returnZero } from "../../../Utils";
 import { Transform } from "../../util/Transform";
 import { CollectionViewType } from '../collections/CollectionView';
 import { ViewBoxBaseComponent } from '../DocComponent';
@@ -38,13 +38,14 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps, PresDoc
     public static LayoutString(fieldKey: string) { return FieldView.LayoutString(PresElementBox, fieldKey); }
 
     _heightDisposer: IReactionDisposer | undefined;
-    @computed get indexInPres() { return NumCast(this.rootDoc.presentationIndex); }
-    @computed get presBoxDoc() { return Cast(this.rootDoc.presBox, Doc) as Doc; }
+    @computed get indexInPres() { return DocListCast(this.presBoxDoc.presOrderedDocs).findIndex(d => d === this.rootDoc); }
+    @computed get presBoxDoc() { return Cast(this.props.RenderData?.().presBox, Doc) as Doc; }
     @computed get targetDoc() { return this.rootDoc.presentationTargetDoc as Doc; }
     @computed get currentIndex() { return NumCast(this.presBoxDoc?._itemIndex); }
+    @computed get collapsedHeight() { return NumCast(this.presBoxDoc?.presCollapsedHeight); }
 
     componentDidMount() {
-        this._heightDisposer = reaction(() => [this.rootDoc.presExpandInlineButton, this.rootDoc.presCollapsedHeight],
+        this._heightDisposer = reaction(() => [this.rootDoc.presExpandInlineButton, this.collapsedHeight],
             params => this.layoutDoc._height = NumCast(params[1]) + (Number(params[0]) ? 100 : 0), { fireImmediately: true });
     }
     componentWillUnmount() {
@@ -147,7 +148,7 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps, PresDoc
      */
     ScreenToLocalListTransform = (xCord: number, yCord: number) => [xCord, yCord];
 
-    embedHeight = () => Math.min(this.props.PanelWidth() - 20, this.props.PanelHeight() - NumCast(this.rootDoc.presCollapsedHeight));
+    embedHeight = () => Math.min(this.props.PanelWidth() - 20, this.props.PanelHeight() - this.collapsedHeight);
     embedWidth = () => this.props.PanelWidth() - 20;
     /**
      * The function that is responsible for rendering the a preview or not for this
@@ -158,7 +159,7 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps, PresDoc
             <div className="presElementBox-embedded" style={{ height: this.embedHeight(), width: this.embedWidth() }}>
                 <ContentFittingDocumentView
                     Document={this.targetDoc}
-                    DataDocument={this.targetDoc[DataSym] !== this.targetDoc && this.targetDoc[DataSym]}
+                    DataDoc={this.targetDoc[DataSym] !== this.targetDoc && this.targetDoc[DataSym]}
                     LibraryPath={emptyPath}
                     fitToBox={true}
                     rootSelected={returnTrue}
@@ -168,12 +169,18 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps, PresDoc
                     pinToPres={returnFalse}
                     PanelWidth={this.embedWidth}
                     PanelHeight={this.embedHeight}
-                    getTransform={Transform.Identity}
-                    active={this.props.active}
+                    ScreenToLocalTransform={Transform.Identity}
+                    parentActive={this.props.active}
                     moveDocument={this.props.moveDocument!}
                     renderDepth={this.props.renderDepth + 1}
                     focus={emptyFunction}
                     whenActiveChanged={returnFalse}
+                    bringToFront={returnFalse}
+                    ContainingCollectionView={undefined}
+                    ContainingCollectionDoc={undefined}
+                    ContentScaling={returnOne}
+                    NativeHeight={returnZero}
+                    NativeWidth={returnZero}
                 />
                 <div className="presElementBox-embeddedMask" />
             </div>;
diff --git a/src/client/views/search/SearchItem.tsx b/src/client/views/search/SearchItem.tsx
index fe2000700..96f43e931 100644
--- a/src/client/views/search/SearchItem.tsx
+++ b/src/client/views/search/SearchItem.tsx
@@ -7,7 +7,7 @@ import { observer } from "mobx-react";
 import { Doc } from "../../../new_fields/Doc";
 import { Id } from "../../../new_fields/FieldSymbols";
 import { Cast, NumCast, StrCast } from "../../../new_fields/Types";
-import { emptyFunction, emptyPath, returnFalse, Utils, returnTrue } from "../../../Utils";
+import { emptyFunction, emptyPath, returnFalse, Utils, returnTrue, returnOne, returnZero } from "../../../Utils";
 import { DocumentType } from "../../documents/DocumentTypes";
 import { DocumentManager } from "../../util/DocumentManager";
 import { DragManager, SetupDrag } from "../../util/DragManager";
@@ -164,14 +164,20 @@ export class SearchItem extends React.Component<SearchItemProps> {
                     removeDocument={returnFalse}
                     addDocTab={returnFalse}
                     pinToPres={returnFalse}
-                    getTransform={Transform.Identity}
+                    ContainingCollectionDoc={undefined}
+                    ContainingCollectionView={undefined}
+                    ScreenToLocalTransform={Transform.Identity}
                     renderDepth={1}
                     PanelWidth={returnXDimension}
                     PanelHeight={returnYDimension}
+                    NativeWidth={returnZero}
+                    NativeHeight={returnZero}
                     focus={emptyFunction}
                     moveDocument={returnFalse}
-                    active={returnFalse}
+                    parentActive={returnFalse}
                     whenActiveChanged={returnFalse}
+                    bringToFront={returnFalse}
+                    ContentScaling={returnOne}
                 />
             </div>;
             return docview;
diff --git a/src/new_fields/documentSchemas.ts b/src/new_fields/documentSchemas.ts
index 5ca0d681e..cd4b9d591 100644
--- a/src/new_fields/documentSchemas.ts
+++ b/src/new_fields/documentSchemas.ts
@@ -9,7 +9,7 @@ export const documentSchema = createSchema({
     layoutKey: "string",        // holds the field key for the field that actually holds the current lyoat
     title: "string",            // document title (can be on either data document or layout)
     dropAction: "string",       // override specifying what should happen when this document is dropped (can be "alias", "copy", "move")
-    targetDropAction: "string",  // allows the target of a drop event to specify the dropAction ("alias", "copy", "move")
+    targetDropAction: "string", // allows the target of a drop event to specify the dropAction ("alias", "copy", "move")
     childDropAction: "string",  // specify the override for what should happen when the child of a collection is dragged from it and dropped (can be "alias" or "copy")
     _autoHeight: "boolean",     // whether the height of the document should be computed automatically based on its contents
     _nativeWidth: "number",     // native width of document which determines how much document contents are scaled when the document's width is set
diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts
index d7cc1e6bf..f37538252 100644
--- a/src/server/authentication/models/current_user_utils.ts
+++ b/src/server/authentication/models/current_user_utils.ts
@@ -578,7 +578,7 @@ export class CurrentUserUtils {
         }
         if (doc.activePresentation === undefined) {
             doc.activePresentation = Docs.Create.PresDocument(new List<Doc>(), {
-                title: "Presentation", _viewType: CollectionViewType.Stacking,
+                title: "Presentation", _viewType: CollectionViewType.Stacking, targetDropAction: "alias",
                 _LODdisable: true, _chromeStatus: "replaced", _showTitle: "title", boxShadow: "0 0"
             });
         }
-- 
cgit v1.2.3-70-g09d2

