From ba42ca25ae828b6279f618dea87f7cd37a3b3814 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Thu, 25 Jun 2020 00:19:40 -0400
Subject: added link preview for blue buttons.

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

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

diff --git a/src/client/views/nodes/LinkDocPreview.tsx b/src/client/views/nodes/LinkDocPreview.tsx
new file mode 100644
index 000000000..126dc240a
--- /dev/null
+++ b/src/client/views/nodes/LinkDocPreview.tsx
@@ -0,0 +1,107 @@
+import { action, computed, observable, runInAction } from 'mobx';
+import { observer } from "mobx-react";
+import wiki from "wikijs";
+import { Doc, DocCastAsync, HeightSym, Opt, WidthSym } from "../../../fields/Doc";
+import { Cast, FieldValue, NumCast } from "../../../fields/Types";
+import { emptyFunction, emptyPath, returnEmptyFilter, returnFalse, returnOne, returnZero } from "../../../Utils";
+import { Docs } from "../../documents/Documents";
+import { DocumentManager } from "../../util/DocumentManager";
+import { Transform } from "../../util/Transform";
+import { ContentFittingDocumentView } from "./ContentFittingDocumentView";
+import React = require("react");
+import { DocumentView } from './DocumentView';
+
+interface Props {
+    linkDoc?: Doc;
+    linkSrc?: Doc;
+    href?: string;
+    backgroundColor: (doc: Doc) => string;
+    addDocTab: (document: Doc, where: string) => boolean;
+    location: number[];
+}
+@observer
+export class LinkDocPreview extends React.Component<Props> {
+    @observable public static LinkInfo: Opt<{ linkDoc?: Doc; addDocTab: (document: Doc, where: string) => boolean, linkSrc: Doc; href?: string; Location: number[] }>;
+    @observable _targetDoc: Opt<Doc>;
+    @observable _toolTipText = "";
+
+    componentDidUpdate() { this.updatePreview() }
+    componentDidMount() { this.updatePreview() }
+    async updatePreview() {
+        const linkDoc = this.props.linkDoc;
+        const linkSrc = this.props.linkSrc;
+        if (this.props.href) {
+            if (this.props.href.startsWith("https://en.wikipedia.org/wiki/")) {
+                wiki().page(this.props.href.replace("https://en.wikipedia.org/wiki/", "")).then(page => page.summary().then(action(summary => this._toolTipText = summary.substring(0, 500))));
+            } else {
+                runInAction(() => this._toolTipText = "external => " + this.props.href);
+            }
+        } else if (linkDoc && linkSrc) {
+            const anchor = FieldValue(Doc.AreProtosEqual(FieldValue(Cast(linkDoc.anchor1, Doc)), linkSrc) ? Cast(linkDoc.anchor2, Doc) : (Cast(linkDoc.anchor1, Doc)) || linkDoc);
+            const target = anchor?.annotationOn ? await DocCastAsync(anchor.annotationOn) : anchor;
+            runInAction(() => {
+                this._toolTipText = "";
+                this._targetDoc = target;
+                if (anchor !== this._targetDoc && anchor && this._targetDoc) {
+                    this._targetDoc._scrollY = NumCast(anchor?.y);
+                }
+            });
+        }
+    }
+    pointerDown = (e: React.PointerEvent) => {
+        if (this.props.linkDoc && this.props.linkSrc) {
+            DocumentManager.Instance.FollowLink(this.props.linkDoc, this.props.linkSrc,
+                (doc: Doc, followLinkLocation: string) => this.props.addDocTab(doc, e.ctrlKey ? "inTab" : followLinkLocation));
+        } else if (this.props.href) {
+            this.props.addDocTab(Docs.Create.WebDocument(this.props.href, { title: this.props.href, _width: 200, _height: 400, UseCors: true }), "onRight");
+        }
+    }
+    width = () => Math.min(350, NumCast(this._targetDoc?.[WidthSym](), 350));
+    height = () => Math.min(350, NumCast(this._targetDoc?.[HeightSym](), 350));
+    @computed get targetDocView() {
+        return !this._targetDoc ?
+            <div style={{ pointerEvents: "all", maxWidth: 350, maxHeight: 250, width: "100%", height: "100%", overflow: "hidden" }}>
+                <div style={{ width: "100%", height: "100%", textOverflow: "ellipsis", }} onPointerDown={this.pointerDown}>
+                    {this._toolTipText}
+                </div>
+            </div> :
+            <ContentFittingDocumentView
+                Document={this._targetDoc}
+                LibraryPath={emptyPath}
+                fitToBox={true}
+                backgroundColor={this.props.backgroundColor}
+                moveDocument={returnFalse}
+                rootSelected={returnFalse}
+                ScreenToLocalTransform={Transform.Identity}
+                parentActive={returnFalse}
+                addDocument={returnFalse}
+                removeDocument={returnFalse}
+                addDocTab={returnFalse}
+                pinToPres={returnFalse}
+                dontRegisterView={true}
+                docFilters={returnEmptyFilter}
+                ContainingCollectionDoc={undefined}
+                ContainingCollectionView={undefined}
+                renderDepth={0}
+                PanelWidth={this.width}
+                PanelHeight={this.height}
+                focus={emptyFunction}
+                whenActiveChanged={returnFalse}
+                bringToFront={returnFalse}
+                ContentScaling={returnOne}
+                NativeWidth={returnZero}
+                NativeHeight={returnZero}
+            />;
+    }
+
+    render() {
+        return <div className="linkDocPreview"
+            style={{
+                position: "absolute", left: this.props.location[0],
+                top: this.props.location[1], width: this.width(), height: this.height(),
+                boxShadow: "black 2px 2px 1em"
+            }}>
+            {this.targetDocView}
+        </div>;
+    }
+}
\ No newline at end of file
-- 
cgit v1.2.3-70-g09d2


From 99d2b19dba130353ac3b021bc7eab079bb125408 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Sat, 27 Jun 2020 02:21:24 -0400
Subject: fixed icon button of document deoratins. cleaned up several compile
 errors and warnings

---
 package-lock.json                                  | 57 ++++++++++------------
 package.json                                       |  1 +
 src/client/documents/Documents.ts                  | 17 ++-----
 src/client/util/LinkManager.ts                     |  2 +-
 src/client/views/DocumentButtonBar.tsx             |  2 +-
 src/client/views/DocumentDecorations.scss          |  9 ++--
 src/client/views/DocumentDecorations.tsx           |  7 +--
 src/client/views/nodes/DocumentView.tsx            |  2 +-
 src/client/views/nodes/LinkDocPreview.tsx          |  4 +-
 .../formattedText/ProsemirrorExampleTransfer.ts    |  2 +-
 src/fields/List.ts                                 |  7 +--
 src/fields/ObjectField.ts                          |  4 +-
 src/fields/Schema.ts                               |  5 +-
 13 files changed, 55 insertions(+), 64 deletions(-)

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

diff --git a/package-lock.json b/package-lock.json
index 67d572ee2..928c59df4 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -637,6 +637,14 @@
                 "@types/node": "*"
             }
         },
+        "@types/google-maps": {
+            "version": "3.2.2",
+            "resolved": "https://registry.npmjs.org/@types/google-maps/-/google-maps-3.2.2.tgz",
+            "integrity": "sha512-/XPVfS28VzUdE/HlmBRoe5ii1nNMyWujyRfRY08bD/JgmPlWSiY8enB2dqTe9mlc3kULq7LfFa1wcupM+lQfqA==",
+            "requires": {
+                "@types/googlemaps": "*"
+            }
+        },
         "@types/google-maps-react": {
             "version": "2.0.5",
             "resolved": "https://registry.npmjs.org/@types/google-maps-react/-/google-maps-react-2.0.5.tgz",
@@ -646,6 +654,11 @@
                 "google-maps-react": "*"
             }
         },
+        "@types/googlemaps": {
+            "version": "3.39.8",
+            "resolved": "https://registry.npmjs.org/@types/googlemaps/-/googlemaps-3.39.8.tgz",
+            "integrity": "sha512-z03u79t1v8QIktoUXypWD06Fzl499/hA162hurA+eCDlWXxFynuU+hMZIaferILF5Gzr4PMX1ShHszT666sUHQ=="
+        },
         "@types/jquery": {
             "version": "3.5.0",
             "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.0.tgz",
@@ -2922,8 +2935,7 @@
                         },
                         "ansi-regex": {
                             "version": "2.1.1",
-                            "bundled": true,
-                            "optional": true
+                            "bundled": true
                         },
                         "aproba": {
                             "version": "1.2.0",
@@ -2941,13 +2953,11 @@
                         },
                         "balanced-match": {
                             "version": "1.0.0",
-                            "bundled": true,
-                            "optional": true
+                            "bundled": true
                         },
                         "brace-expansion": {
                             "version": "1.1.11",
                             "bundled": true,
-                            "optional": true,
                             "requires": {
                                 "balanced-match": "^1.0.0",
                                 "concat-map": "0.0.1"
@@ -2960,18 +2970,15 @@
                         },
                         "code-point-at": {
                             "version": "1.1.0",
-                            "bundled": true,
-                            "optional": true
+                            "bundled": true
                         },
                         "concat-map": {
                             "version": "0.0.1",
-                            "bundled": true,
-                            "optional": true
+                            "bundled": true
                         },
                         "console-control-strings": {
                             "version": "1.1.0",
-                            "bundled": true,
-                            "optional": true
+                            "bundled": true
                         },
                         "core-util-is": {
                             "version": "1.0.2",
@@ -3074,8 +3081,7 @@
                         },
                         "inherits": {
                             "version": "2.0.4",
-                            "bundled": true,
-                            "optional": true
+                            "bundled": true
                         },
                         "ini": {
                             "version": "1.3.5",
@@ -3085,7 +3091,6 @@
                         "is-fullwidth-code-point": {
                             "version": "1.0.0",
                             "bundled": true,
-                            "optional": true,
                             "requires": {
                                 "number-is-nan": "^1.0.0"
                             }
@@ -3098,20 +3103,17 @@
                         "minimatch": {
                             "version": "3.0.4",
                             "bundled": true,
-                            "optional": true,
                             "requires": {
                                 "brace-expansion": "^1.1.7"
                             }
                         },
                         "minimist": {
                             "version": "1.2.5",
-                            "bundled": true,
-                            "optional": true
+                            "bundled": true
                         },
                         "minipass": {
                             "version": "2.9.0",
                             "bundled": true,
-                            "optional": true,
                             "requires": {
                                 "safe-buffer": "^5.1.2",
                                 "yallist": "^3.0.0"
@@ -3128,7 +3130,6 @@
                         "mkdirp": {
                             "version": "0.5.3",
                             "bundled": true,
-                            "optional": true,
                             "requires": {
                                 "minimist": "^1.2.5"
                             }
@@ -3184,8 +3185,7 @@
                         },
                         "npm-normalize-package-bin": {
                             "version": "1.0.1",
-                            "bundled": true,
-                            "optional": true
+                            "bundled": true
                         },
                         "npm-packlist": {
                             "version": "1.4.8",
@@ -3210,8 +3210,7 @@
                         },
                         "number-is-nan": {
                             "version": "1.0.1",
-                            "bundled": true,
-                            "optional": true
+                            "bundled": true
                         },
                         "object-assign": {
                             "version": "4.1.1",
@@ -3221,7 +3220,6 @@
                         "once": {
                             "version": "1.4.0",
                             "bundled": true,
-                            "optional": true,
                             "requires": {
                                 "wrappy": "1"
                             }
@@ -3290,8 +3288,7 @@
                         },
                         "safe-buffer": {
                             "version": "5.1.2",
-                            "bundled": true,
-                            "optional": true
+                            "bundled": true
                         },
                         "safer-buffer": {
                             "version": "2.1.2",
@@ -3321,7 +3318,6 @@
                         "string-width": {
                             "version": "1.0.2",
                             "bundled": true,
-                            "optional": true,
                             "requires": {
                                 "code-point-at": "^1.0.0",
                                 "is-fullwidth-code-point": "^1.0.0",
@@ -3339,7 +3335,6 @@
                         "strip-ansi": {
                             "version": "3.0.1",
                             "bundled": true,
-                            "optional": true,
                             "requires": {
                                 "ansi-regex": "^2.0.0"
                             }
@@ -3378,13 +3373,11 @@
                         },
                         "wrappy": {
                             "version": "1.0.2",
-                            "bundled": true,
-                            "optional": true
+                            "bundled": true
                         },
                         "yallist": {
                             "version": "3.1.1",
-                            "bundled": true,
-                            "optional": true
+                            "bundled": true
                         }
                     }
                 }
diff --git a/package.json b/package.json
index 79c33bd99..683f181c3 100644
--- a/package.json
+++ b/package.json
@@ -118,6 +118,7 @@
         "@hig/flyout": "^1.2.1",
         "@hig/theme-context": "^2.1.3",
         "@hig/theme-data": "^2.16.1",
+        "@types/google-maps": "^3.2.2",
         "@types/webscopeio__react-textarea-autocomplete": "^4.6.1",
         "@webscopeio/react-textarea-autocomplete": "^4.7.0",
         "adm-zip": "^0.4.16",
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 0fc58c39d..d5b7f07b5 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -13,28 +13,23 @@ import { Cast, NumCast, StrCast } from "../../fields/Types";
 import { AudioField, ImageField, PdfField, VideoField, WebField, YoutubeField } from "../../fields/URLField";
 import { MessageStore } from "../../server/Message";
 import { OmitKeys, Utils } from "../../Utils";
+import { YoutubeBox } from "../apis/youtube/YoutubeBox";
 import { DocServer } from "../DocServer";
+import { DocumentManager } from "../util/DocumentManager";
 import { dropActionType } from "../util/DragManager";
+import { DirectoryImportBox } from "../util/Import & Export/DirectoryImportBox";
 import { LinkManager } from "../util/LinkManager";
 import { Scripting } from "../util/Scripting";
 import { UndoManager } from "../util/UndoManager";
-import { DocumentType } from "./DocumentTypes";
 import { CollectionDockingView } from "../views/collections/CollectionDockingView";
 import { CollectionView, CollectionViewType } from "../views/collections/CollectionView";
 import { ContextMenu } from "../views/ContextMenu";
 import { ContextMenuProps } from "../views/ContextMenuItem";
-import { ActiveInkBezierApprox, ActiveInkColor, ActiveInkWidth, InkingStroke } from "../views/InkingStroke";
+import { ActiveArrowEnd, ActiveArrowStart, ActiveDash, ActiveFillColor, ActiveInkBezierApprox, ActiveInkColor, ActiveInkWidth, InkingStroke } from "../views/InkingStroke";
 import { AudioBox } from "../views/nodes/AudioBox";
 import { ColorBox } from "../views/nodes/ColorBox";
 import { ComparisonBox } from "../views/nodes/ComparisonBox";
 import { DocHolderBox } from "../views/nodes/DocHolderBox";
-import { InkingStroke, ActiveInkColor, ActiveInkWidth, ActiveInkBezierApprox, ActiveFillColor, ActiveArrowStart, ActiveArrowEnd, ActiveDash } from "../views/InkingStroke";
-import { InkField } from "../../fields/InkField";
-import { RichTextField } from "../../fields/RichTextField";
-import { extname } from "path";
-import { MessageStore } from "../../server/Message";
-import { ContextMenuProps } from "../views/ContextMenuItem";
-import { ContextMenu } from "../views/ContextMenu";
 import { FontIconBox } from "../views/nodes/FontIconBox";
 import { FormattedTextBox } from "../views/nodes/formattedText/FormattedTextBox";
 import { ImageBox } from "../views/nodes/ImageBox";
@@ -52,9 +47,7 @@ import { WebBox } from "../views/nodes/WebBox";
 import { PresElementBox } from "../views/presentationview/PresElementBox";
 import { RecommendationsBox } from "../views/RecommendationsBox";
 import { DashWebRTCVideo } from "../views/webcam/DashWebRTCVideo";
-import { YoutubeBox } from "../apis/youtube/YoutubeBox";
-import { DocumentManager } from "../util/DocumentManager";
-import { DirectoryImportBox } from "../util/Import & Export/DirectoryImportBox";
+import { DocumentType } from "./DocumentTypes";
 const path = require('path');
 
 export interface DocumentOptions {
diff --git a/src/client/util/LinkManager.ts b/src/client/util/LinkManager.ts
index 438f3eb9b..0aec81ab0 100644
--- a/src/client/util/LinkManager.ts
+++ b/src/client/util/LinkManager.ts
@@ -72,7 +72,7 @@ export class LinkManager {
         });
         DocListCast(anchor[Doc.LayoutFieldKey(anchor) + "-annotations"]).map(anno => {
             related.push(...LinkManager.Instance.getAllRelatedLinks(anno));
-        })
+        });
         return related;
     }
 
diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx
index fcaea0f0b..c05ca33fb 100644
--- a/src/client/views/DocumentButtonBar.tsx
+++ b/src/client/views/DocumentButtonBar.tsx
@@ -271,7 +271,7 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
         const considerPush = isText && this.considerGoogleDocsPush;
         return <div className="documentButtonBar">
             <div className="documentButtonBar-button">
-                <DocumentLinksButton View={this.view0!} AlwaysOn={true} />
+                <DocumentLinksButton View={this.view0} AlwaysOn={true} />
             </div>
             <div className="documentButtonBar-button">
                 {this.templateButton}
diff --git a/src/client/views/DocumentDecorations.scss b/src/client/views/DocumentDecorations.scss
index c8347165d..5948ada88 100644
--- a/src/client/views/DocumentDecorations.scss
+++ b/src/client/views/DocumentDecorations.scss
@@ -193,10 +193,10 @@ $linkGap : 3px;
 .documentDecorations-iconifyButton {
     opacity: 1;
     grid-column-start: 4;
-    grid-column-end: 6;
+    grid-column-end: 5;
     pointer-events: all;
     text-align: center;
-    left: -20px;
+    left: -25px;
     top: -2px;
     cursor: pointer;
     position: absolute;
@@ -207,10 +207,13 @@ $linkGap : 3px;
 .documentDecorations-closeButton {
     opacity: 1;
     grid-column-start: 4;
-    grid-column-end: 6;
+    grid-column-end: 5;
     pointer-events: all;
     text-align: center;
     cursor: pointer;
+    width: 15px;
+    margin-left: -8px;
+    margin-top: auto;
 }
 
 .documentDecorations-minimizeButton {
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 6e8eed287..f5454216a 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -603,9 +603,10 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
             }}>
                 {maximizeIcon}
                 {titleArea}
-                <div className="documentDecorations-iconifyButton" title={`${seldoc.finalLayoutKey.includes("icon") ? "De" : ""}Iconify Document`} onPointerDown={this.onIconifyDown}>
-                    {"_"}
-                </div>
+                {SelectionManager.SelectedDocuments().length !== 1 || seldoc.Document.type === DocumentType.INK ? (null) :
+                    <div className="documentDecorations-iconifyButton" title={`${seldoc.finalLayoutKey.includes("icon") ? "De" : ""}Iconify Document`} onPointerDown={this.onIconifyDown}>
+                        {"_"}
+                    </div>}
                 <div className="documentDecorations-closeButton" title="Open Document in Tab" onPointerDown={this.onMaximizeDown}>
                     {SelectionManager.SelectedDocuments().length === 1 ? DocumentDecorations.DocumentIcon(StrCast(seldoc.props.Document.layout, "...")) : "..."}
                 </div>
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 8f139e39e..a2bb9700e 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -742,7 +742,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
         this.props.contextMenuItems?.().forEach(item =>
             cm.addItem({ description: item.label, event: () => item.script.script.run({ this: this.layoutDoc, self: this.rootDoc }), icon: "sticky-note" }));
 
-        let options = cm.findByDescription("Options...");
+        const options = cm.findByDescription("Options...");
         const optionItems: ContextMenuProps[] = options && "subitems" in options ? options.subitems : [];
         const templateDoc = Cast(this.props.Document[StrCast(this.props.Document.layoutKey)], Doc, null);
         templateDoc && optionItems.push({ description: "Open Template   ", event: () => this.props.addDocTab(templateDoc, "onRight"), icon: "eye" });
diff --git a/src/client/views/nodes/LinkDocPreview.tsx b/src/client/views/nodes/LinkDocPreview.tsx
index 126dc240a..92b443d3b 100644
--- a/src/client/views/nodes/LinkDocPreview.tsx
+++ b/src/client/views/nodes/LinkDocPreview.tsx
@@ -25,8 +25,8 @@ export class LinkDocPreview extends React.Component<Props> {
     @observable _targetDoc: Opt<Doc>;
     @observable _toolTipText = "";
 
-    componentDidUpdate() { this.updatePreview() }
-    componentDidMount() { this.updatePreview() }
+    componentDidUpdate() { this.updatePreview(); }
+    componentDidMount() { this.updatePreview(); }
     async updatePreview() {
         const linkDoc = this.props.linkDoc;
         const linkSrc = this.props.linkSrc;
diff --git a/src/client/views/nodes/formattedText/ProsemirrorExampleTransfer.ts b/src/client/views/nodes/formattedText/ProsemirrorExampleTransfer.ts
index 0abaf3df6..1bbcb9fa8 100644
--- a/src/client/views/nodes/formattedText/ProsemirrorExampleTransfer.ts
+++ b/src/client/views/nodes/formattedText/ProsemirrorExampleTransfer.ts
@@ -175,7 +175,7 @@ export default function buildKeymap<S extends Schema<any>>(schema: S, props: any
         }
     });
 
-    var backspace = chainCommands(deleteSelection, joinBackward, selectNodeBackward);
+    // backspace = chainCommands(deleteSelection, joinBackward, selectNodeBackward);
     bind("Backspace", (state: EditorState<S>, dispatch: (tx: Transaction<Schema<any, any>>) => void) => {
         if (!deleteSelection(state, (tx: Transaction<Schema<any, any>>) => {
             dispatch(updateBullets(tx, schema));
diff --git a/src/fields/List.ts b/src/fields/List.ts
index fdabea365..a9da75abb 100644
--- a/src/fields/List.ts
+++ b/src/fields/List.ts
@@ -291,9 +291,10 @@ class ListImpl<T extends Field> extends ObjectField {
         this.___fields = value;
         for (const key in value) {
             const field = value[key];
-            if (!(field instanceof ObjectField)) continue;
-            (field as ObjectField)[Parent] = this[Self];
-            (field as ObjectField)[OnUpdate] = updateFunction(this[Self], key, field, this[SelfProxy]);
+            if (field instanceof ObjectField) {
+                field[Parent] = this[Self];
+                field[OnUpdate] = updateFunction(this[Self], key, field, this[SelfProxy]);
+            }
         }
     }
 
diff --git a/src/fields/ObjectField.ts b/src/fields/ObjectField.ts
index 9aa1c9b04..92b2cfa60 100644
--- a/src/fields/ObjectField.ts
+++ b/src/fields/ObjectField.ts
@@ -3,8 +3,8 @@ import { OnUpdate, Parent, Copy, ToScriptString, ToString } from "./FieldSymbols
 import { Scripting } from "../client/util/Scripting";
 
 export abstract class ObjectField {
-    protected [OnUpdate](diff?: any) { }
-    private [Parent]?: RefField | ObjectField;
+    public [OnUpdate](diff?: any) { }
+    public [Parent]?: RefField | ObjectField;
     abstract [Copy](): ObjectField;
 
     abstract [ToScriptString](): string;
diff --git a/src/fields/Schema.ts b/src/fields/Schema.ts
index 72bce283d..98ef3e087 100644
--- a/src/fields/Schema.ts
+++ b/src/fields/Schema.ts
@@ -65,9 +65,8 @@ export function makeInterface<T extends Interface[]>(...schemas: T): InterfaceFu
         return obj;
     };
     return function (doc?: Doc | Doc[]) {
-        doc = doc || new Doc;
-        if (doc instanceof Doc) {
-            return fn(doc);
+        if (doc instanceof Doc || doc === undefined) {
+            return fn(doc || new Doc);
         } else {
             return doc.map(fn);
         }
-- 
cgit v1.2.3-70-g09d2

