From 3ca56576e187e2f3cc87770b0fbdf8aa6cae73f3 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Wed, 14 Apr 2021 23:12:19 -0400
Subject: fixed image templates to set/use the appropriate nativewidth/height.
 fixed carousel views and style provider to better support properties for
 components of a document view.  fixed menus to show text options when
 captions and other sub text components are focused.

---
 src/client/views/nodes/formattedText/FormattedTextBox.tsx | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

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

diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index c2860af76..9203207d7 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -1,6 +1,6 @@
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { isEqual } from "lodash";
-import { action, computed, IReactionDisposer, reaction, runInAction } from "mobx";
+import { action, computed, IReactionDisposer, reaction, runInAction, observable } from "mobx";
 import { observer } from "mobx-react";
 import { baseKeymap, selectAll } from "prosemirror-commands";
 import { history } from "prosemirror-history";
@@ -1132,6 +1132,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
     }
 
     componentWillUnmount() {
+        FormattedTextBox.Focused === this && (FormattedTextBox.Focused = undefined);
         Object.values(this._disposers).forEach(disposer => disposer?.());
         this.endUndoTypingBatch();
         this.unhighlightSearchTerms();
@@ -1236,8 +1237,10 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
     @action
     onFocused = (e: React.FocusEvent): void => {
         //applyDevTools.applyDevTools(this._editorView);
+        FormattedTextBox.Focused = this;
         this._editorView && RichTextMenu.Instance?.updateMenu(this._editorView, undefined, this.props);
     }
+    @observable public static Focused: FormattedTextBox | undefined;
 
     onClick = (e: React.MouseEvent): void => {
         if (Math.abs(e.clientX - this._downX) > 4 || Math.abs(e.clientY - this._downY) > 4) {
@@ -1340,6 +1343,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
         return wasUndoing;
     }
     onBlur = (e: any) => {
+        FormattedTextBox.Focused === this && (FormattedTextBox.Focused = undefined);
         if (RichTextMenu.Instance?.view === this._editorView && !this.props.isSelected(true)) {
             RichTextMenu.Instance?.updateMenu(undefined, undefined, undefined);
         }
-- 
cgit v1.2.3-70-g09d2


From 4334a553fdfdf44b1d1c609290fe2a874a408967 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Thu, 15 Apr 2021 00:04:18 -0400
Subject: fixed up carousels to work with templated documents

---
 .../views/collections/CollectionCarousel3DView.tsx | 40 +++++++++++++++++-----
 .../views/collections/CollectionCarouselView.tsx   | 32 +++++++++++++----
 src/client/views/collections/CollectionMenu.tsx    |  2 +-
 .../views/nodes/formattedText/FormattedTextBox.tsx |  1 +
 4 files changed, 59 insertions(+), 16 deletions(-)

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

diff --git a/src/client/views/collections/CollectionCarousel3DView.tsx b/src/client/views/collections/CollectionCarousel3DView.tsx
index 9a3183d88..7cebabaa9 100644
--- a/src/client/views/collections/CollectionCarousel3DView.tsx
+++ b/src/client/views/collections/CollectionCarousel3DView.tsx
@@ -9,10 +9,11 @@ import { makeInterface } from '../../../fields/Schema';
 import { ScriptField } from '../../../fields/ScriptField';
 import { NumCast, ScriptCast, StrCast } from '../../../fields/Types';
 import { OmitKeys, returnFalse, Utils } from '../../../Utils';
-import { DragManager } from '../../util/DragManager';
+import { DragManager, dropActionType } from '../../util/DragManager';
 import { DocumentView } from '../nodes/DocumentView';
 import "./CollectionCarousel3DView.scss";
 import { CollectionSubView } from './CollectionSubView';
+import { StyleProp } from '../StyleProvider';
 
 type Carousel3DDocument = makeInterface<[typeof documentSchema, typeof collectionSchema]>;
 const Carousel3DDocument = makeInterface(documentSchema, collectionSchema);
@@ -42,17 +43,36 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume
         const displayDoc = (childPair: { layout: Doc, data: Doc }) => {
             const script = ScriptField.MakeScript("this._showCaption = 'caption'", { this: Doc.name });
             const onChildClick = script && (() => script);
-            return <DocumentView {...OmitKeys(this.props, ["NativeWidth", "NativeHeight"]).omit}
-                onDoubleClick={this.onChildDoubleClick}
-                onClick={onChildClick}
-                renderDepth={this.props.renderDepth + 1}
+            return <DocumentView
+                Document={childPair.layout}
+                DataDoc={childPair.layout.resolvedDataDoc as Doc}
+                styleProvider={this.props.styleProvider}
+                layerProvider={this.props.layerProvider}
+                docViewPath={this.props.docViewPath}
                 LayoutTemplate={this.props.childLayoutTemplate}
                 LayoutTemplateString={this.props.childLayoutString}
-                Document={childPair.layout}
-                DataDoc={childPair.data}
+                freezeDimensions={this.props.childFreezeDimensions}
+                renderDepth={this.props.renderDepth + 1}
                 PanelWidth={this.panelWidth}
                 PanelHeight={this.panelHeight}
+                rootSelected={this.rootSelected}
+                dropAction={StrCast(this.props.Document.childDropAction) as dropActionType}
                 ScreenToLocalTransform={this.props.ScreenToLocalTransform}
+                focus={this.props.focus}
+                docFilters={this.docFilters}
+                onDoubleClick={this.onChildDoubleClick}
+                onClick={onChildClick}
+                isContentActive={returnFalse}
+                docRangeFilters={this.docRangeFilters}
+                searchFilterDocs={this.searchFilterDocs}
+                ContainingCollectionDoc={this.props.CollectionView?.props.Document}
+                ContainingCollectionView={this.props.CollectionView}
+                addDocument={this.props.addDocument}
+                moveDocument={this.props.moveDocument}
+                removeDocument={this.props.removeDocument}
+                whenChildContentsActiveChanged={this.props.whenChildContentsActiveChanged}
+                addDocTab={this.props.addDocTab}
+                pinToPres={this.props.pinToPres}
                 bringToFront={returnFalse}
             />;
         };
@@ -146,7 +166,11 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume
         const index = NumCast(this.layoutDoc._itemIndex);
         const translateX = this.panelWidth() * (1 - index);
 
-        return <div className="collectionCarousel3DView-outer" ref={this.createDashEventsTarget}>
+        return <div className="collectionCarousel3DView-outer" ref={this.createDashEventsTarget}
+            style={{
+                background: this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.BackgroundColor),
+                color: this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.Color),
+            }}  >
             <div className="carousel-wrapper" style={{ transform: `translateX(${translateX}px)` }}>
                 {this.content}
             </div>
diff --git a/src/client/views/collections/CollectionCarouselView.tsx b/src/client/views/collections/CollectionCarouselView.tsx
index 0642a1f9b..4a7bdf6db 100644
--- a/src/client/views/collections/CollectionCarouselView.tsx
+++ b/src/client/views/collections/CollectionCarouselView.tsx
@@ -7,7 +7,7 @@ import { collectionSchema, documentSchema } from '../../../fields/documentSchema
 import { makeInterface } from '../../../fields/Schema';
 import { NumCast, ScriptCast, StrCast } from '../../../fields/Types';
 import { OmitKeys, returnFalse } from '../../../Utils';
-import { DragManager } from '../../util/DragManager';
+import { DragManager, dropActionType } from '../../util/DragManager';
 import { DocumentView } from '../nodes/DocumentView';
 import { FormattedTextBox } from '../nodes/formattedText/FormattedTextBox';
 import { StyleProp } from '../StyleProvider';
@@ -47,16 +47,34 @@ export class CollectionCarouselView extends CollectionSubView(CarouselDocument)
         return !(curDoc?.layout instanceof Doc) ? (null) :
             <>
                 <div className="collectionCarouselView-image" key="image">
-                    <DocumentView  {...OmitKeys(this.props, ["NativeWidth", "NativeHeight"]).omit}
-                        onDoubleClick={this.onContentDoubleClick}
-                        onClick={this.onContentClick}
-                        renderDepth={this.props.renderDepth + 1}
+                    <DocumentView
+                        Document={curDoc.layout}
+                        DataDoc={curDoc.layout.resolvedDataDoc as Doc}
+                        styleProvider={this.props.styleProvider}
+                        layerProvider={this.props.layerProvider}
+                        docViewPath={this.props.docViewPath}
                         LayoutTemplate={this.props.childLayoutTemplate}
                         LayoutTemplateString={this.props.childLayoutString}
-                        Document={curDoc.layout}
-                        DataDoc={curDoc.data}
+                        freezeDimensions={this.props.childFreezeDimensions}
+                        renderDepth={this.props.renderDepth + 1}
+                        PanelWidth={this.props.PanelWidth}
                         PanelHeight={this.panelHeight}
+                        rootSelected={this.rootSelected}
+                        dropAction={StrCast(this.props.Document.childDropAction) as dropActionType}
                         ScreenToLocalTransform={this.props.ScreenToLocalTransform}
+                        focus={this.props.focus}
+                        docFilters={this.docFilters}
+                        isContentActive={returnFalse}
+                        docRangeFilters={this.docRangeFilters}
+                        searchFilterDocs={this.searchFilterDocs}
+                        ContainingCollectionDoc={this.props.CollectionView?.props.Document}
+                        ContainingCollectionView={this.props.CollectionView}
+                        addDocument={this.props.addDocument}
+                        moveDocument={this.props.moveDocument}
+                        removeDocument={this.props.removeDocument}
+                        whenChildContentsActiveChanged={this.props.whenChildContentsActiveChanged}
+                        addDocTab={this.props.addDocTab}
+                        pinToPres={this.props.pinToPres}
                         bringToFront={returnFalse}
                     />
                 </div>
diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx
index 95b0ef790..ab4f197a6 100644
--- a/src/client/views/collections/CollectionMenu.tsx
+++ b/src/client/views/collections/CollectionMenu.tsx
@@ -554,7 +554,7 @@ export class CollectionViewBaseChrome extends React.Component<CollectionMenuProp
                         <div className="collectionMenu-divider" key="divider3"></div>
                         {this.lightboxButton}
                         {this.recordButton}
-                        {/* {!this._buttonizableCommands ? (null) : this.templateChrome} */}
+                        {!this._buttonizableCommands ? (null) : this.templateChrome}
                     </div>
                 </div>
             </div>
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index 9203207d7..25dc93605 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -1342,6 +1342,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
         this._undoTyping = undefined;
         return wasUndoing;
     }
+    @action
     onBlur = (e: any) => {
         FormattedTextBox.Focused === this && (FormattedTextBox.Focused = undefined);
         if (RichTextMenu.Instance?.view === this._editorView && !this.props.isSelected(true)) {
-- 
cgit v1.2.3-70-g09d2


From e55aed8d419d9e1d7385d0556c09405035f01e7c Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Thu, 15 Apr 2021 23:09:26 -0400
Subject: cleaned up CollectionCarousel and styleprovider to handle
 sub-component properties better.  updated resizers in multicol/row to be
 visible.

---
 src/client/views/SidebarAnnos.tsx                  |  2 --
 src/client/views/StyleProvider.tsx                 | 12 ++++---
 .../views/collections/CollectionCarouselView.scss  | 15 ++++----
 .../views/collections/CollectionCarouselView.tsx   | 40 ++++++++++++++--------
 .../views/collections/CollectionStackingView.tsx   |  2 +-
 .../collections/collectionFreeForm/MarqueeView.tsx |  2 +-
 .../CollectionMulticolumnView.tsx                  |  2 ++
 .../CollectionMultirowView.tsx                     |  2 ++
 .../collectionMulticolumn/MulticolumnResizer.tsx   | 27 ++++++++-------
 .../collectionMulticolumn/MultirowResizer.tsx      | 27 ++++++++-------
 src/client/views/nodes/DocumentView.tsx            |  7 ++--
 src/client/views/nodes/FieldView.tsx               |  4 +--
 src/client/views/nodes/ScreenshotBox.tsx           |  4 +--
 .../views/nodes/formattedText/FormattedTextBox.tsx | 16 ++++-----
 14 files changed, 90 insertions(+), 72 deletions(-)

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

diff --git a/src/client/views/SidebarAnnos.tsx b/src/client/views/SidebarAnnos.tsx
index 6c3eb1e95..bff4c95fc 100644
--- a/src/client/views/SidebarAnnos.tsx
+++ b/src/client/views/SidebarAnnos.tsx
@@ -113,8 +113,6 @@ export class SidebarAnnos extends React.Component<FieldViewProps & ExtraProps> {
                         NativeHeight={returnZero}
                         PanelHeight={this.panelHeight}
                         PanelWidth={this.panelWidth}
-                        xMargin={0}
-                        yMargin={0}
                         styleProvider={this.sidebarStyleProvider}
                         docFilters={this.docFilters}
                         scaleField={this.sidebarKey() + "-scale"}
diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx
index ebd453295..bde741959 100644
--- a/src/client/views/StyleProvider.tsx
+++ b/src/client/views/StyleProvider.tsx
@@ -86,21 +86,23 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
             !Doc.IsSystem(doc) && doc.type === DocumentType.RTF ?
                 (doc.author === Doc.CurrentUserEmail ? StrCast(Doc.UserDoc().showTitle) : "author;creationDate") : "") || "";
         case StyleProp.Color:
+            const docColor: Opt<string> = StrCast(doc?.[fieldKey + "color"], StrCast(doc?._color));
+            if (docColor) return docColor;
             if (isCaption) return "white";
-            const backColor = backgroundCol() || "black";
+            const backColor = backgroundCol();// || (darkScheme() ? "black" : "white");
+            if (!backColor) return undefined;
             const col = Color(backColor).rgb();
             const colsum = (col.red() + col.green() + col.blue());
             if (colsum / col.alpha() > 400 || col.alpha() < 0.25) return "black";
             return "white";
         case StyleProp.Hidden: return BoolCast(doc?._hidden);
-        case StyleProp.BorderRounding: return StrCast(doc?._borderRounding);
+        case StyleProp.BorderRounding: return StrCast(doc?.[fieldKey + "borderRounding"], StrCast(doc?._borderRounding));
         case StyleProp.TitleHeight: return 15;
         case StyleProp.HeaderMargin: return ([CollectionViewType.Stacking, CollectionViewType.Masonry].includes(doc?._viewType as any) ||
             doc?.type === DocumentType.RTF) && showTitle() && !StrCast(doc?.showTitle).includes(":hover") ? 15 : 0;
         case StyleProp.BackgroundColor: {
-            if (isCaption) return "rgba(0,0,0 ,0.4)";
             if (Doc.UserDoc().renderStyle === "comic") return "transparent";
-            let docColor: Opt<string> = StrCast(doc?.[fieldKey + "backgroundColor"], StrCast(doc?._backgroundColor));
+            let docColor: Opt<string> = StrCast(doc?.[fieldKey + "backgroundColor"], StrCast(doc?._backgroundColor, isCaption ? "rbga(0,0,0,0.4)" : ""));
             if (MainView.Instance.LastButton === doc) return darkScheme() ? "dimgrey" : "lightgrey";
             switch (doc?.type) {
                 case DocumentType.PRESELEMENT: docColor = docColor || (darkScheme() ? "" : ""); break;
@@ -131,7 +133,7 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
                                             Doc.UserDoc().activeCollectionBackground));
                     break;
                 //if (doc._viewType !== CollectionViewType.Freeform && doc._viewType !== CollectionViewType.Time) return "rgb(62,62,62)";
-                default: docColor = darkScheme() ? "black" : "white"; break;
+                default: docColor = docColor || (darkScheme() ? "black" : "white"); break;
             }
             if (docColor && (!doc || props?.layerProvider?.(doc) === false)) docColor = Color(docColor.toLowerCase()).fade(0.5).toString();
             return docColor;
diff --git a/src/client/views/collections/CollectionCarouselView.scss b/src/client/views/collections/CollectionCarouselView.scss
index a9a1898f5..8660113cd 100644
--- a/src/client/views/collections/CollectionCarouselView.scss
+++ b/src/client/views/collections/CollectionCarouselView.scss
@@ -1,13 +1,10 @@
 
 .collectionCarouselView-outer {
-    background: gray;
     height : 100%;
     .collectionCarouselView-caption {
-        margin-left: 10%;
-        margin-right: 10%;
         height: 50; 
         display: inline-block;
-        width: 80%;
+        width: 100%;
     }
     .collectionCarouselView-image {
         height: calc(100% - 50px);
@@ -19,13 +16,17 @@
 .carouselView-back, .carouselView-fwd  {
     position: absolute;
     display: flex;
-    top: 50%;
+    top: 42.5%;
     width: 30;
-    height: 30;
+    height: 15%;
     align-items: center;
     border-radius: 5px;
     justify-content: center;
-    background : rgba(255, 255, 255, 0.46);
+    color: rgba(255,255,255,0.5);
+    background : rgba(0,0,0, 0.1);
+    &:hover {
+        color:white;
+    }
 }
 .carouselView-fwd {
     right: 0; 
diff --git a/src/client/views/collections/CollectionCarouselView.tsx b/src/client/views/collections/CollectionCarouselView.tsx
index d28a4d87d..cd81a99c9 100644
--- a/src/client/views/collections/CollectionCarouselView.tsx
+++ b/src/client/views/collections/CollectionCarouselView.tsx
@@ -2,17 +2,17 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { computed } from 'mobx';
 import { observer } from 'mobx-react';
 import * as React from 'react';
-import { Doc } from '../../../fields/Doc';
+import { Doc, Opt } from '../../../fields/Doc';
 import { collectionSchema, documentSchema } from '../../../fields/documentSchemas';
 import { makeInterface } from '../../../fields/Schema';
 import { NumCast, ScriptCast, StrCast } from '../../../fields/Types';
 import { OmitKeys, returnFalse } from '../../../Utils';
 import { DragManager } from '../../util/DragManager';
-import { DocumentView } from '../nodes/DocumentView';
+import { DocumentView, DocumentViewProps } from '../nodes/DocumentView';
 import { FormattedTextBox } from '../nodes/formattedText/FormattedTextBox';
 import { StyleProp } from '../StyleProvider';
 import "./CollectionCarouselView.scss";
-import { CollectionSubView } from './CollectionSubView';
+import { CollectionSubView, SubCollectionViewProps } from './CollectionSubView';
 
 type CarouselDocument = makeInterface<[typeof documentSchema, typeof collectionSchema]>;
 const CarouselDocument = makeInterface(documentSchema, collectionSchema);
@@ -38,12 +38,19 @@ export class CollectionCarouselView extends CollectionSubView(CarouselDocument)
         e.stopPropagation();
         this.layoutDoc._itemIndex = (NumCast(this.layoutDoc._itemIndex) - 1 + this.childLayoutPairs.length) % this.childLayoutPairs.length;
     }
-    panelHeight = () => this.props.PanelHeight() - 50;
+    captionStyleProvider = (doc: (Doc | undefined), props: Opt<DocumentViewProps>, property: string): any => {
+        const captionProps = { ...this.props, fieldKey: "caption" };
+        return this.props.styleProvider?.(doc, props, property) || this.props.styleProvider?.(this.layoutDoc, captionProps, property);
+    }
+    panelHeight = () => this.props.PanelHeight() - (StrCast(this.layoutDoc._showCaption) ? 50 : 0);
     onContentDoubleClick = () => ScriptCast(this.layoutDoc.onChildDoubleClick);
     onContentClick = () => ScriptCast(this.layoutDoc.onChildClick);
     @computed get content() {
         const index = NumCast(this.layoutDoc._itemIndex);
         const curDoc = this.childLayoutPairs?.[index];
+        const captionProps = { ...this.props, fieldKey: "caption" };
+        const marginX = NumCast(this.layoutDoc["caption-xMargin"]);
+        const marginY = NumCast(this.layoutDoc["caption-yMargin"]);
         return !(curDoc?.layout instanceof Doc) ? (null) :
             <>
                 <div className="collectionCarouselView-image" key="image">
@@ -51,6 +58,7 @@ export class CollectionCarouselView extends CollectionSubView(CarouselDocument)
                         onDoubleClick={this.onContentDoubleClick}
                         onClick={this.onContentClick}
                         renderDepth={this.props.renderDepth + 1}
+                        ContainingCollectionView={this}
                         LayoutTemplate={this.props.childLayoutTemplate}
                         LayoutTemplateString={this.props.childLayoutString}
                         Document={curDoc.layout}
@@ -61,25 +69,27 @@ export class CollectionCarouselView extends CollectionSubView(CarouselDocument)
                 </div>
                 <div className="collectionCarouselView-caption" key="caption"
                     style={{
-                        background: this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.BackgroundColor + ":caption"),
-                        color: this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.Color + ":caption"),
-                        borderRadius: this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.BorderRounding + ":caption"),
+                        display: StrCast(this.layoutDoc._showCaption) ? undefined : "none",
+                        borderRadius: this.props.styleProvider?.(this.layoutDoc, captionProps, StyleProp.BorderRounding),
+                        marginRight: marginX, marginLeft: marginX,
+                        width: `calc(100% - ${marginX * 2}px)`
                     }}>
-                    <FormattedTextBox key={index} {...this.props}
-                        Document={curDoc.layout} DataDoc={undefined} fieldKey={"caption"}
+                    <FormattedTextBox key={index} {...captionProps}
+                        styleProvider={this.captionStyleProvider}
+                        Document={curDoc.layout} DataDoc={undefined}
                         fontSize={NumCast(this.layoutDoc["caption-fontSize"])}
-                        xMargin={NumCast(this.layoutDoc["caption-xMargin"])}
-                        yMargin={NumCast(this.layoutDoc["caption-yMargin"])} />
+                        xPadding={NumCast(this.layoutDoc["caption-xPadding"])}
+                        yPadding={NumCast(this.layoutDoc["caption-yPadding"])} />
                 </div>
             </>;
     }
     @computed get buttons() {
         return <>
-            <div key="back" className="carouselView-back" style={{ background: `${StrCast(this.layoutDoc.backgroundColor)}` }} onClick={this.goback}>
-                <FontAwesomeIcon icon={"caret-left"} size={"2x"} />
+            <div key="back" className="carouselView-back" onClick={this.goback}>
+                <FontAwesomeIcon icon={"chevron-left"} size={"2x"} />
             </div>
-            <div key="fwd" className="carouselView-fwd" style={{ background: `${StrCast(this.layoutDoc.backgroundColor)}` }} onClick={this.advance}>
-                <FontAwesomeIcon icon={"caret-right"} size={"2x"} />
+            <div key="fwd" className="carouselView-fwd" onClick={this.advance}>
+                <FontAwesomeIcon icon={"chevron-right"} size={"2x"} />
             </div>
         </>;
     }
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index 1aed40bc3..30f8e0112 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -58,7 +58,7 @@ export class CollectionStackingView extends CollectionSubView<StackingDocument,
     @computed get filteredChildren() { return this.childLayoutPairs.filter(pair => (pair.layout instanceof Doc) && !pair.layout.hidden).map(pair => pair.layout); }
     @computed get headerMargin() { return this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.HeaderMargin); }
     @computed get xMargin() { return NumCast(this.layoutDoc._xMargin, 2 * Math.min(this.gridGap, .05 * this.props.PanelWidth())); }
-    @computed get yMargin() { return this.props.yMargin || NumCast(this.layoutDoc._yMargin, 5); } // 2 * this.gridGap)); }
+    @computed get yMargin() { return this.props.yPadding || NumCast(this.layoutDoc._yMargin, 5); } // 2 * this.gridGap)); }
     @computed get gridGap() { return NumCast(this.layoutDoc._gridGap, 10); }
     @computed get isStackingView() { return (this.props.viewType ?? this.layoutDoc._viewType) === CollectionViewType.Stacking; }
     @computed get numGroupColumns() { return this.isStackingView ? Math.max(1, this.Sections.size + (this.showAddAGroup ? 1 : 0)) : 1; }
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index a4f129b8c..b1f2750c3 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -155,7 +155,7 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque
             } else if (!e.ctrlKey && !e.metaKey && SelectionManager.Views().length < 2) {
                 FormattedTextBox.SelectOnLoadChar = Doc.UserDoc().defaultTextLayout && !this.props.childLayoutString ? e.key : "";
                 FormattedTextBox.LiveTextUndo = UndoManager.StartBatch("live text batch");
-                this.props.addLiveTextDocument(CurrentUserUtils.GetNewTextDoc("-typed text-", x, y, 200, 100, this.props.xMargin === 0));
+                this.props.addLiveTextDocument(CurrentUserUtils.GetNewTextDoc("-typed text-", x, y, 200, 100, this.props.xPadding === 0));
                 e.stopPropagation();
             }
     }
diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx
index 8b5c02b75..8c5c3431b 100644
--- a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx
+++ b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx
@@ -273,6 +273,8 @@ export class CollectionMulticolumnView extends CollectionSubView(MulticolumnDocu
                 <ResizeBar
                     width={resizerWidth}
                     key={"resizer" + i}
+                    styleProvider={this.props.styleProvider}
+                    isContentActive={this.props.isContentActive}
                     select={this.props.select}
                     columnUnitLength={this.getColumnUnitLength}
                     toLeft={layout}
diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx b/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx
index 2c5e40d02..40b155c34 100644
--- a/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx
+++ b/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx
@@ -267,6 +267,8 @@ export class CollectionMultirowView extends CollectionSubView(MultirowDocument)
                 </div>,
                 <ResizeBar
                     height={resizerHeight}
+                    styleProvider={this.props.styleProvider}
+                    isContentActive={this.props.isContentActive}
                     key={"resizer" + i}
                     columnUnitLength={this.getRowUnitLength}
                     toTop={layout}
diff --git a/src/client/views/collections/collectionMulticolumn/MulticolumnResizer.tsx b/src/client/views/collections/collectionMulticolumn/MulticolumnResizer.tsx
index 734915a93..9fe18d118 100644
--- a/src/client/views/collections/collectionMulticolumn/MulticolumnResizer.tsx
+++ b/src/client/views/collections/collectionMulticolumn/MulticolumnResizer.tsx
@@ -5,9 +5,13 @@ import { Doc } from "../../../../fields/Doc";
 import { NumCast, StrCast } from "../../../../fields/Types";
 import { DimUnit } from "./CollectionMulticolumnView";
 import { UndoManager } from "../../../util/UndoManager";
+import { StyleProviderFunc } from "../../nodes/DocumentView";
+import { StyleProp } from "../../StyleProvider";
 
 interface ResizerProps {
     width: number;
+    styleProvider?: StyleProviderFunc;
+    isContentActive?: () => boolean;
     columnUnitLength(): number | undefined;
     toLeft?: Doc;
     toRight?: Doc;
@@ -85,19 +89,16 @@ export default class ResizeBar extends React.Component<ResizerProps> {
     }
 
     render() {
-        return (
-            <div
-                className={"multiColumnResizer"}
-                style={{
-                    width: this.props.width,
-                    opacity: this.isActivated && this.isHoverActive ? resizerOpacity : 0
-                }}
-                onPointerEnter={action(() => this.isHoverActive = true)}
-                onPointerLeave={action(() => !this.isResizingActive && (this.isHoverActive = false))}
-            >
-                <div className={"multiColumnResizer-hdl"} onPointerDown={e => this.registerResizing(e)} />
-            </div>
-        );
+        return <div className="multiColumnResizer"
+            style={{
+                width: this.props.width,
+                backgroundColor: !this.props.isContentActive?.() ? "" : this.props.styleProvider?.(undefined, undefined, StyleProp.WidgetColor)
+            }}
+            onPointerEnter={action(() => this.isHoverActive = true)}
+            onPointerLeave={action(() => !this.isResizingActive && (this.isHoverActive = false))}
+        >
+            <div className={"multiColumnResizer-hdl"} onPointerDown={e => this.registerResizing(e)} />
+        </div>;
     }
 
 }
\ No newline at end of file
diff --git a/src/client/views/collections/collectionMulticolumn/MultirowResizer.tsx b/src/client/views/collections/collectionMulticolumn/MultirowResizer.tsx
index d0bc4d01c..5478bf709 100644
--- a/src/client/views/collections/collectionMulticolumn/MultirowResizer.tsx
+++ b/src/client/views/collections/collectionMulticolumn/MultirowResizer.tsx
@@ -5,9 +5,13 @@ import { Doc } from "../../../../fields/Doc";
 import { NumCast, StrCast } from "../../../../fields/Types";
 import { DimUnit } from "./CollectionMultirowView";
 import { UndoManager } from "../../../util/UndoManager";
+import { StyleProp } from "../../StyleProvider";
+import { StyleProviderFunc } from "../../nodes/DocumentView";
 
 interface ResizerProps {
     height: number;
+    styleProvider?: StyleProviderFunc;
+    isContentActive?: () => boolean;
     columnUnitLength(): number | undefined;
     toTop?: Doc;
     toBottom?: Doc;
@@ -83,19 +87,16 @@ export default class ResizeBar extends React.Component<ResizerProps> {
     }
 
     render() {
-        return (
-            <div
-                className={"multiRowResizer"}
-                style={{
-                    height: this.props.height,
-                    opacity: this.isActivated && this.isHoverActive ? resizerOpacity : 0
-                }}
-                onPointerEnter={action(() => this.isHoverActive = true)}
-                onPointerLeave={action(() => !this.isResizingActive && (this.isHoverActive = false))}
-            >
-                <div className={"multiRowResizer-hdl"} onPointerDown={e => this.registerResizing(e)} />
-            </div>
-        );
+        return <div className="multiRowResizer"
+            style={{
+                height: this.props.height,
+                backgroundColor: !this.props.isContentActive?.() ? "" : this.props.styleProvider?.(undefined, undefined, StyleProp.WidgetColor)
+            }}
+            onPointerEnter={action(() => this.isHoverActive = true)}
+            onPointerLeave={action(() => !this.isResizingActive && (this.isHoverActive = false))}
+        >
+            <div className={"multiRowResizer-hdl"} onPointerDown={e => this.registerResizing(e)} />
+        </div>;
     }
 
 }
\ No newline at end of file
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index f08cda92c..5e97b07f0 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -508,6 +508,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
             // if this is part of a template, let the event go up to the tempalte root unless right/ctrl clicking
             !(this.props.Document.rootDocument && !(e.ctrlKey || e.button > 0))) {
             if ((this.props.isDocumentActive?.() || this.layoutDoc.onDragStart) &&
+                !this.Document.ignoreClick &&
                 !e.ctrlKey &&
                 (e.button === 0 || InteractionUtils.IsType(e, InteractionUtils.TOUCHTYPE)) &&
                 !CurrentUserUtils.OverlayDocs.includes(this.layoutDoc)) {
@@ -891,7 +892,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
         TraceMobx();
         const showTitle = this.ShowTitle?.split(":")[0];
         const showTitleHover = this.ShowTitle?.includes(":hover");
-        const showCaption = StrCast(this.layoutDoc._showCaption);
+        const showCaption = StrCast(this.layoutDoc._showCaption) && this.Document._viewType !== CollectionViewType.Carousel;
         const captionView = !showCaption ? (null) :
             <div className="documentView-captionWrapper"
                 style={{
@@ -899,8 +900,8 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
                     color: StrCast(this.layoutDoc["caption-color"])
                 }}>
                 <DocumentContentsView {...OmitKeys(this.props, ['children']).omit}
-                    yMargin={10}
-                    xMargin={10}
+                    yPadding={10}
+                    xPadding={10}
                     hideOnLeave={true}
                     styleProvider={this.captionStyleProvider}
                     dontRegisterView={true}
diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx
index 4f4df32b3..86250c9d1 100644
--- a/src/client/views/nodes/FieldView.tsx
+++ b/src/client/views/nodes/FieldView.tsx
@@ -32,8 +32,8 @@ export interface FieldViewProps extends DocumentViewSharedProps {
     width?: number;
     background?: string;
     color?: string;
-    xMargin?: number;
-    yMargin?: number;
+    xPadding?: number;
+    yPadding?: number;
 }
 
 @observer
diff --git a/src/client/views/nodes/ScreenshotBox.tsx b/src/client/views/nodes/ScreenshotBox.tsx
index c4f8d1143..44460dc41 100644
--- a/src/client/views/nodes/ScreenshotBox.tsx
+++ b/src/client/views/nodes/ScreenshotBox.tsx
@@ -194,8 +194,8 @@ export class ScreenshotBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatabl
                         select={emptyFunction}
                         isContentActive={returnFalse}
                         scaling={returnOne}
-                        xMargin={25}
-                        yMargin={10}
+                        xPadding={25}
+                        yPadding={10}
                         whenChildContentsActiveChanged={emptyFunction}
                         removeDocument={returnFalse}
                         moveDocument={returnFalse}
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index 25dc93605..ea854ebe7 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -68,8 +68,8 @@ const translateGoogleApi = require("translate-google-api");
 export interface FormattedTextBoxProps {
     makeLink?: () => Opt<Doc>;  // bcz: hack: notifies the text document when the container has made a link.  allows the text doc to react and setup a hyeprlink for any selected text
     hideOnLeave?: boolean;  // used by DocumentView for setting caption's hide on leave (bcz: would prefer to have caption-hideOnLeave field set or something similar)
-    xMargin?: number;   // used to override document's settings for xMargin --- see CollectionCarouselView
-    yMargin?: number;
+    xPadding?: number;   // used to override document's settings for xMargin --- see CollectionCarouselView
+    yPadding?: number;
     noSidebar?: boolean;
     dontSelectOnLoad?: boolean; // suppress selecting the text box when loaded
 }
@@ -1477,8 +1477,8 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
                     NativeHeight={returnZero}
                     PanelHeight={this.props.PanelHeight}
                     PanelWidth={this.sidebarWidth}
-                    xMargin={0}
-                    yMargin={0}
+                    xPadding={0}
+                    yPadding={0}
                     scaleField={this.SidebarKey + "-scale"}
                     isAnnotationOverlay={false}
                     select={emptyFunction}
@@ -1510,7 +1510,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
         const interactive = (CurrentUserUtils.SelectedTool === InkTool.None || SnappingManager.GetIsDragging()) && (this.layoutDoc.z || this.props.layerProvider?.(this.layoutDoc) !== false);
         if (!selected && FormattedTextBoxComment.textBox === this) setTimeout(FormattedTextBoxComment.Hide);
         const minimal = this.props.ignoreAutoHeight;
-        const margins = NumCast(this.layoutDoc._yMargin, this.props.yMargin || 0);
+        const margins = NumCast(this.layoutDoc._yMargin, this.props.yPadding || 0);
         const selPad = Math.min(margins, 10);
         const padding = Math.max(margins + ((selected && !this.layoutDoc._singleLine) || minimal ? -selPad : 0), 0);
         const selPaddingClass = selected && !this.layoutDoc._singleLine && margins >= 10 ? "-selected" : "";
@@ -1529,8 +1529,8 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
                     style={{
                         overflow: this.autoHeight ? "hidden" : undefined,
                         height: this.props.height || (this.autoHeight && this.props.renderDepth ? "max-content" : undefined),
-                        background: this.props.background ? this.props.background : StrCast(this.layoutDoc[this.props.fieldKey + "-backgroundColor"], this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.BackgroundColor)),
-                        color: this.props.color ? this.props.color : StrCast(this.layoutDoc[this.props.fieldKey + "-color"], this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.Color)),
+                        background: this.props.background ? this.props.background : this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.BackgroundColor),
+                        color: this.props.color ? this.props.color : this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.Color),
                         pointerEvents: interactive ? undefined : "none",
                         fontSize: this.props.fontSize || Cast(this.layoutDoc._fontSize, "string", null),
                         fontWeight: Cast(this.layoutDoc._fontWeight, "number", null),
@@ -1565,7 +1565,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
                     {(this.props.noSidebar || this.Document._noSidebar) || this.Document._singleLine ? (null) : this.sidebarHandle}
                     {!this.layoutDoc._showAudio ? (null) : this.audioHandle}
                 </div>
-            </div>
+            </div >
         );
     }
 }
-- 
cgit v1.2.3-70-g09d2


From e7f4439446200833082e23c7b6091817031235a5 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Fri, 16 Apr 2021 13:12:17 -0400
Subject: fixed so that minimaps can't appear on non freeform collections. 
 fixed multirow/col to work with templates & stopped normalizing dimensions
 (which breaks templates). added quick and dirty lightboxDocTemplate to
 display templated documents.  fixed TextDocs to work with template fields
 that just have a text string.

---
 src/client/views/LightboxView.tsx                  | 10 ++++---
 src/client/views/collections/TabDocView.tsx        | 10 ++++---
 .../CollectionMulticolumnView.tsx                  | 27 +++++++++++--------
 .../CollectionMultirowView.tsx                     | 31 +++++++++++++---------
 src/client/views/nodes/DocumentView.tsx            | 11 ++++----
 .../views/nodes/formattedText/FormattedTextBox.tsx |  6 ++---
 6 files changed, 58 insertions(+), 37 deletions(-)

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

diff --git a/src/client/views/LightboxView.tsx b/src/client/views/LightboxView.tsx
index b26765fa7..9c03b457b 100644
--- a/src/client/views/LightboxView.tsx
+++ b/src/client/views/LightboxView.tsx
@@ -26,6 +26,8 @@ interface LightboxViewProps {
 export class LightboxView extends React.Component<LightboxViewProps> {
 
     @computed public static get LightboxDoc() { return this._doc; }
+    private static LightboxDocTemplate = () => LightboxView._layoutTemplate;
+    @observable private static _layoutTemplate: Opt<Doc>;
     @observable private static _doc: Opt<Doc>;
     @observable private static _docTarget: Opt<Doc>;
     @observable private static _docFilters: string[] = []; // filters
@@ -35,7 +37,7 @@ export class LightboxView extends React.Component<LightboxViewProps> {
     private static _future: Opt<Doc[]> = [];
     private static _docView: Opt<DocumentView>;
     static path: { doc: Opt<Doc>, target: Opt<Doc>, history: Opt<{ doc: Doc, target?: Doc }[]>, future: Opt<Doc[]>, saved: Opt<{ panX: Opt<number>, panY: Opt<number>, scale: Opt<number>, scrollTop: Opt<number> }> }[] = [];
-    @action public static SetLightboxDoc(doc: Opt<Doc>, target?: Doc, future?: Doc[]) {
+    @action public static SetLightboxDoc(doc: Opt<Doc>, target?: Doc, future?: Doc[], layoutTemplate?: Doc) {
         if (this.LightboxDoc && this.LightboxDoc !== doc && this._savedState) {
             this.LightboxDoc._panX = this._savedState.panX;
             this.LightboxDoc._panY = this._savedState.panY;
@@ -62,6 +64,7 @@ export class LightboxView extends React.Component<LightboxViewProps> {
             this._future = future.slice().sort((a, b) => NumCast(b._timecodeToShow) - NumCast(a._timecodeToShow)).sort((a, b) => DocListCast(a.links).length - DocListCast(b.links).length);
         }
         this._doc = doc;
+        this._layoutTemplate = layoutTemplate;
         this._docTarget = target || doc;
         this._tourMap = DocListCast(doc?.links).map(link => {
             const opp = LinkManager.getOppositeAnchor(link, doc!);
@@ -101,13 +104,13 @@ export class LightboxView extends React.Component<LightboxViewProps> {
             this._docFilters = (f => this._docFilters ? [this._docFilters.push(f) as any, this._docFilters][1] : [f])(`cookies:${cookie}:provide`);
         }
     }
-    public static AddDocTab = (doc: Doc, location: string) => {
+    public static AddDocTab = (doc: Doc, location: string, layoutTemplate?: Doc) => {
         SelectionManager.DeselectAll();
         return LightboxView.SetLightboxDoc(doc, undefined,
             [...DocListCast(doc[Doc.LayoutFieldKey(doc)]),
             ...DocListCast(doc[Doc.LayoutFieldKey(doc) + "-annotations"]),
             ...(LightboxView._future ?? [])
-            ].sort((a: Doc, b: Doc) => NumCast(b._timecodeToShow) - NumCast(a._timecodeToShow)));
+            ].sort((a: Doc, b: Doc) => NumCast(b._timecodeToShow) - NumCast(a._timecodeToShow)), layoutTemplate);
     }
     docFilters = () => LightboxView._docFilters || [];
     addDocTab = LightboxView.AddDocTab;
@@ -229,6 +232,7 @@ export class LightboxView extends React.Component<LightboxViewProps> {
                     })}
                         Document={LightboxView.LightboxDoc}
                         DataDoc={undefined}
+                        LayoutTemplate={LightboxView.LightboxDocTemplate}
                         addDocument={undefined}
                         fitContentsToDoc={this.fitToBox}
                         isDocumentActive={returnFalse}
diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
index 4417038fa..983c3732f 100644
--- a/src/client/views/collections/TabDocView.tsx
+++ b/src/client/views/collections/TabDocView.tsx
@@ -9,7 +9,7 @@ import * as ReactDOM from 'react-dom';
 import { DataSym, Doc, DocListCast, DocListCastAsync, HeightSym, Opt, WidthSym } from "../../../fields/Doc";
 import { Id } from '../../../fields/FieldSymbols';
 import { FieldId } from "../../../fields/RefField";
-import { Cast, NumCast, StrCast } from "../../../fields/Types";
+import { Cast, NumCast, StrCast, BoolCast } from "../../../fields/Types";
 import { TraceMobx } from '../../../fields/util';
 import { emptyFunction, returnEmptyDoclist, returnFalse, returnTrue, setupMoveUpEvents, Utils } from "../../../Utils";
 import { DocServer } from "../../DocServer";
@@ -299,6 +299,8 @@ export class TabDocView extends React.Component<TabDocViewProps> {
     PanelHeight = () => this._panelHeight;
     miniMapColor = () => this.tabColor;
     tabView = () => this._view;
+    disableMinimap = () => !this._document || (this._document.layout !== CollectionView.LayoutString(Doc.LayoutFieldKey(this._document)) || this._document?._viewType !== CollectionViewType.Freeform);
+    hideMinimap = () => this.disableMinimap() || BoolCast(this._document?.hideMinimap);
 
     @computed get layerProvider() { return this._document && DefaultLayerProvider(this._document); }
     @computed get docView() {
@@ -330,13 +332,14 @@ export class TabDocView extends React.Component<TabDocViewProps> {
                 bringToFront={emptyFunction}
                 pinToPres={TabDocView.PinDoc} />
                 <TabMinimapView key="minimap"
+                    hideMinimap={this.hideMinimap}
                     addDocTab={this.addDocTab}
                     PanelHeight={this.PanelHeight}
                     PanelWidth={this.PanelWidth}
                     background={this.miniMapColor}
                     document={this._document}
                     tabView={this.tabView} />
-                <Tooltip style={{ display: this._document.layout !== CollectionView.LayoutString(Doc.LayoutFieldKey(this._document)) || this._document?._viewType !== CollectionViewType.Freeform ? "none" : undefined }} key="ttip" title={<div className="dash-tooltip">{"toggle minimap"}</div>}>
+                <Tooltip style={{ display: this.disableMinimap() ? "none" : undefined }} key="ttip" title={<div className="dash-tooltip">{"toggle minimap"}</div>}>
                     <div className="miniMap-hidden" onPointerDown={e => e.stopPropagation()} onClick={action(e => { e.stopPropagation(); this._document!.hideMinimap = !this._document!.hideMinimap; })} >
                         <FontAwesomeIcon icon={"globe-asia"} size="lg" />
                     </div>
@@ -361,6 +364,7 @@ export class TabDocView extends React.Component<TabDocViewProps> {
 
 interface TabMinimapViewProps {
     document: Doc;
+    hideMinimap: () => boolean;
     tabView: () => DocumentView | undefined;
     addDocTab: (doc: Doc, where: string) => boolean;
     PanelWidth: () => number;
@@ -411,7 +415,7 @@ export class TabMinimapView extends React.Component<TabMinimapViewProps> {
         const miniLeft = 50 + (NumCast(this.props.document._panX) - this.renderBounds.cx) / this.renderBounds.dim * 100 - miniWidth / 2;
         const miniTop = 50 + (NumCast(this.props.document._panY) - this.renderBounds.cy) / this.renderBounds.dim * 100 - miniHeight / 2;
         const miniSize = this.returnMiniSize();
-        return this.props.document.hideMinimap ? (null) :
+        return this.props.hideMinimap() ? (null) :
             <div className="miniMap" style={{ width: miniSize, height: miniSize, background: this.props.background() }}>
                 <CollectionFreeFormView
                     Document={this.props.document}
diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx
index 8c5c3431b..f3a39a262 100644
--- a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx
+++ b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx
@@ -49,6 +49,11 @@ export class CollectionMulticolumnView extends CollectionSubView(MulticolumnDocu
         return this.childLayoutPairs.map(pair => pair.layout).filter(layout => StrCast(layout._dimUnit, "*") === DimUnit.Ratio);
     }
 
+    @computed
+    private get minimumDim() {
+        return Math.min(...this.ratioDefinedDocs.filter(layout => layout._dimMagnitude).map(layout => NumCast(layout._dimMagnitude)));
+    }
+
     /**
      * This loops through all childLayoutPairs and extracts the values for _dimUnit
      * and _dimMagnitude, ignoring any that are malformed. Additionally, it then
@@ -63,7 +68,7 @@ export class CollectionMulticolumnView extends CollectionSubView(MulticolumnDocu
         const widthSpecifiers: WidthSpecifier[] = [];
         this.childLayoutPairs.map(pair => {
             const unit = StrCast(pair.layout._dimUnit, "*");
-            const magnitude = NumCast(pair.layout._dimMagnitude, 1);
+            const magnitude = NumCast(pair.layout._dimMagnitude, this.minimumDim);
             if (unit && magnitude && magnitude > 0 && resolvedUnits.includes(unit)) {
                 (unit === DimUnit.Ratio) && (starSum += magnitude);
                 widthSpecifiers.push({ magnitude, unit });
@@ -80,15 +85,15 @@ export class CollectionMulticolumnView extends CollectionSubView(MulticolumnDocu
          * themselves to drift toward zero. Thus, whenever we change any of the values,
          * we normalize everything (dividing by the smallest magnitude).
          */
-        setTimeout(() => {
-            const { ratioDefinedDocs } = this;
-            if (this.childLayoutPairs.length) {
-                const minimum = Math.min(...ratioDefinedDocs.map(doc => NumCast(doc._dimMagnitude, 1)));
-                if (minimum !== 0) {
-                    ratioDefinedDocs.forEach(layout => layout._dimMagnitude = NumCast(layout._dimMagnitude, 1) / minimum, 1);
-                }
-            }
-        });
+        // setTimeout(() => {
+        //     const { ratioDefinedDocs } = this;
+        //     if (this.childLayoutPairs.length) {
+        //         const minimum = this.minimumDim;
+        //         if (minimum !== 0) {
+        //             ratioDefinedDocs.forEach(layout => layout._dimMagnitude = NumCast(layout._dimMagnitude, 1) / minimum, 1);
+        //         }
+        //     }
+        // });
 
         return { widthSpecifiers, starSum };
     }
@@ -161,7 +166,7 @@ export class CollectionMulticolumnView extends CollectionSubView(MulticolumnDocu
         if (columnUnitLength === undefined) {
             return 0; // we're still waiting on promises to resolve
         }
-        let width = NumCast(layout._dimMagnitude, 1);
+        let width = NumCast(layout._dimMagnitude, this.minimumDim);
         if (StrCast(layout._dimUnit, "*") === DimUnit.Ratio) {
             width *= columnUnitLength;
         }
diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx b/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx
index 40b155c34..29cb3511a 100644
--- a/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx
+++ b/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx
@@ -49,6 +49,11 @@ export class CollectionMultirowView extends CollectionSubView(MultirowDocument)
         return this.childLayoutPairs.map(pair => pair.layout).filter(layout => StrCast(layout._dimUnit, "*") === DimUnit.Ratio);
     }
 
+    @computed
+    private get minimumDim() {
+        return Math.min(...this.ratioDefinedDocs.filter(layout => layout._dimMagnitude).map(layout => NumCast(layout._dimMagnitude)));
+    }
+
     /**
      * This loops through all childLayoutPairs and extracts the values for _dimUnit
      * and _dimUnit, ignoring any that are malformed. Additionally, it then
@@ -63,7 +68,7 @@ export class CollectionMultirowView extends CollectionSubView(MultirowDocument)
         const heightSpecifiers: HeightSpecifier[] = [];
         this.childLayoutPairs.map(pair => {
             const unit = StrCast(pair.layout._dimUnit, "*");
-            const magnitude = NumCast(pair.layout._dimMagnitude, 1);
+            const magnitude = NumCast(pair.layout._dimMagnitude, this.minimumDim);
             if (unit && magnitude && magnitude > 0 && resolvedUnits.includes(unit)) {
                 (unit === DimUnit.Ratio) && (starSum += magnitude);
                 heightSpecifiers.push({ magnitude, unit });
@@ -80,15 +85,15 @@ export class CollectionMultirowView extends CollectionSubView(MultirowDocument)
          * themselves to drift toward zero. Thus, whenever we change any of the values,
          * we normalize everything (dividing by the smallest magnitude).
          */
-        setTimeout(() => {
-            const { ratioDefinedDocs } = this;
-            if (this.childLayoutPairs.length) {
-                const minimum = Math.min(...ratioDefinedDocs.map(layout => NumCast(layout._dimMagnitude, 1)));
-                if (minimum !== 0) {
-                    ratioDefinedDocs.forEach(layout => layout._dimMagnitude = NumCast(layout._dimMagnitude, 1) / minimum);
-                }
-            }
-        });
+        // setTimeout(() => {
+        //     const { ratioDefinedDocs } = this;
+        //     if (this.childLayoutPairs.length) {
+        //         const minimum = Math.min(...ratioDefinedDocs.map(layout => NumCast(layout._dimMagnitude, 1)));
+        //         if (minimum !== 0) {
+        //             ratioDefinedDocs.forEach(layout => layout._dimMagnitude = NumCast(layout._dimMagnitude, 1) / minimum);
+        //         }
+        //     }
+        // });
 
         return { heightSpecifiers, starSum };
     }
@@ -161,7 +166,7 @@ export class CollectionMultirowView extends CollectionSubView(MultirowDocument)
         if (rowUnitLength === undefined) {
             return 0; // we're still waiting on promises to resolve
         }
-        let height = NumCast(layout._dimMagnitude, 1);
+        let height = NumCast(layout._dimMagnitude, this.minimumDim);
         if (StrCast(layout._dimUnit, "*") === DimUnit.Ratio) {
             height *= rowUnitLength;
         }
@@ -261,7 +266,9 @@ export class CollectionMultirowView extends CollectionSubView(MultirowDocument)
             const height = () => this.lookupPixels(layout);
             const width = () => PanelWidth() - 2 * NumCast(Document._xMargin) - (BoolCast(Document.showWidthLabels) ? 20 : 0);
             collector.push(
-                <div className={"document-wrapper"} key={"wrapper" + i} >
+                <div className={"document-wrapper"}
+                    style={{ height: height() }}
+                    key={"wrapper" + i} >
                     {this.getDisplayDoc(layout, dxf, width, height)}
                     <HeightLabel layout={layout} collectionDoc={Document} />
                 </div>,
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 5e97b07f0..857d06ea7 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -200,7 +200,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
     @computed get finalLayoutKey() { return StrCast(this.Document.layoutKey, "layout"); }
     @computed get nativeWidth() { return this.props.NativeWidth(); }
     @computed get nativeHeight() { return this.props.NativeHeight(); }
-    @computed get onClickHandler() { return this.props.onClick?.() ?? Cast(this.Document.onClick, ScriptField, Cast(this.layoutDoc.onClick, ScriptField, null)); }
+    @computed get onClickHandler() { return this.props.onClick?.() ?? Cast(this.Document.onfClick, ScriptField, Cast(this.layoutDoc.onClick, ScriptField, null)); }
     @computed get onDoubleClickHandler() { return this.props.onDoubleClick?.() ?? (Cast(this.layoutDoc.onDoubleClick, ScriptField, null) ?? this.Document.onDoubleClick); }
     @computed get onPointerDownHandler() { return this.props.onPointerDown?.() ?? ScriptCast(this.Document.onPointerDown); }
     @computed get onPointerUpHandler() { return this.props.onPointerUp?.() ?? ScriptCast(this.Document.onPointerUp); }
@@ -453,10 +453,11 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
                     }, console.log);
                     UndoManager.RunInBatch(() => func().result?.select === true ? this.props.select(false) : "", "on double click");
                 } else if (!Doc.IsSystem(this.rootDoc)) {
-                    if (this.props.Document.type !== DocumentType.LABEL) {
-                        UndoManager.RunInBatch(() => this.props.addDocTab((this.rootDoc._fullScreenView as Doc) || this.rootDoc, "lightbox"), "double tap");
-                        SelectionManager.DeselectAll();
-                    }
+                    UndoManager.RunInBatch(() =>
+                        LightboxView.AddDocTab(this.rootDoc, "lightbox", this.props.LayoutTemplate?.())
+                        //this.props.addDocTab((this.rootDoc._fullScreenView as Doc) || this.rootDoc, "lightbox")
+                        , "double tap");
+                    SelectionManager.DeselectAll();
                     Doc.UnBrushDoc(this.props.Document);
                 }
             } else if (this.onClickHandler?.script && !StrCast(Doc.LayoutField(this.layoutDoc))?.includes(ScriptingBox.name)) { // bcz: hack? don't execute script if you're clicking on a scripting box itself
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index ea854ebe7..8039e777e 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -1064,8 +1064,8 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
         });
     }
     setupEditor(config: any, fieldKey: string) {
-        const curText = Cast(this.dataDoc[this.props.fieldKey], RichTextField, null);
-        const rtfField = Cast((!curText?.Text && this.layoutDoc[this.props.fieldKey]) || this.dataDoc[fieldKey], RichTextField);
+        const curText = Cast(this.dataDoc[this.props.fieldKey], RichTextField, null) || StrCast(this.dataDoc[this.props.fieldKey]);
+        const rtfField = Cast((!curText && this.layoutDoc[this.props.fieldKey]) || this.dataDoc[fieldKey], RichTextField);
         if (this.ProseRef) {
             const self = this;
             this._editorView?.destroy();
@@ -1118,7 +1118,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
                 const tr = this._editorView.state.tr.setStoredMarks(storedMarks).insertText(FormattedTextBox.SelectOnLoadChar, this._editorView.state.doc.content.size - 1, this._editorView.state.doc.content.size).setStoredMarks(storedMarks);
                 this._editorView.dispatch(tr.setSelection(new TextSelection(tr.doc.resolve(tr.doc.content.size))));
                 FormattedTextBox.SelectOnLoadChar = "";
-            } else if (curText?.Text && !FormattedTextBox.DontSelectInitialText) {
+            } else if (curText && !FormattedTextBox.DontSelectInitialText) {
                 selectAll(this._editorView!.state, this._editorView?.dispatch);
                 this.startUndoTypingBatch();
             }
-- 
cgit v1.2.3-70-g09d2


From e26e07f6956c1a4cb7593f66fc88f219b7349e05 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Fri, 16 Apr 2021 15:44:23 -0400
Subject: addded documents as fields

---
 src/client/views/DocComponent.tsx                  |  2 +-
 src/client/views/DocumentDecorations.tsx           | 27 +++++++++++++++++-----
 src/client/views/nodes/DocumentView.tsx            | 15 ++++++++++++
 .../views/nodes/formattedText/FormattedTextBox.tsx |  2 +-
 4 files changed, 38 insertions(+), 8 deletions(-)

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

diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx
index 3c565fd62..a878a7afb 100644
--- a/src/client/views/DocComponent.tsx
+++ b/src/client/views/DocComponent.tsx
@@ -182,7 +182,7 @@ export function ViewBoxAnnotatableComponent<P extends ViewBoxAnnotatableProps, T
         addDocument(doc: Doc | Doc[], annotationKey?: string): boolean {
             const docs = doc instanceof Doc ? [doc] : doc;
             if (this.props.filterAddDocument?.(docs) === false ||
-                docs.find(doc => Doc.AreProtosEqual(doc, this.props.Document))) {
+                docs.find(doc => Doc.AreProtosEqual(doc, this.props.Document) && Doc.LayoutField(doc) === Doc.LayoutField(this.props.Document))) {
                 return false;
             }
             const targetDataDoc = this.props.Document[DataSym];
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index e23374cea..24ca3a8fa 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -8,7 +8,7 @@ import { Document } from '../../fields/documentSchemas';
 import { HtmlField } from '../../fields/HtmlField';
 import { InkField } from "../../fields/InkField";
 import { ScriptField } from '../../fields/ScriptField';
-import { Cast, NumCast } from "../../fields/Types";
+import { Cast, NumCast, StrCast } from "../../fields/Types";
 import { GetEffectiveAcl } from '../../fields/util';
 import { setupMoveUpEvents, emptyFunction, returnFalse } from "../../Utils";
 import { Docs, DocUtils } from "../documents/Documents";
@@ -26,6 +26,7 @@ import { InkStrokeProperties } from './InkStrokeProperties';
 import { LightboxView } from './LightboxView';
 import { DocumentView } from "./nodes/DocumentView";
 import React = require("react");
+import { FormattedTextBox } from './nodes/formattedText/FormattedTextBox';
 
 @observer
 export class DocumentDecorations extends React.Component<{ boundsLeft: number, boundsTop: number }, { value: string }> {
@@ -83,7 +84,21 @@ export class DocumentDecorations extends React.Component<{ boundsLeft: number, b
             UndoManager.RunInBatch(() => titleFieldKey && SelectionManager.Views().forEach(d => {
                 titleFieldKey === "title" && (d.dataDoc["title-custom"] = !this._accumulatedTitle.startsWith("-"));
                 //@ts-ignore
-                Doc.SetInPlace(d.rootDoc, titleFieldKey, +this._accumulatedTitle === this._accumulatedTitle ? +this._accumulatedTitle : this._accumulatedTitle, true);
+                const titleField = (+this._accumulatedTitle === this._accumulatedTitle ? +this._accumulatedTitle : this._accumulatedTitle);
+                Doc.SetInPlace(d.rootDoc, titleFieldKey, titleField, true);
+
+                if (d.rootDoc.syncLayoutFieldWithTitle) {
+                    const title = titleField.toString();
+                    const curKey = Doc.LayoutFieldKey(d.rootDoc);
+                    if (curKey !== title && d.dataDoc[title] === undefined) {
+                        d.rootDoc.layout = FormattedTextBox.LayoutString(title);
+                        setTimeout(() => {
+                            const val = d.dataDoc[curKey];
+                            d.dataDoc[curKey] = undefined;
+                            d.dataDoc[title] = val;
+                        });
+                    }
+                }
             }), "title blur");
         }
     }
@@ -376,10 +391,10 @@ export class DocumentDecorations extends React.Component<{ boundsLeft: number, b
         this._inkDragDocs.map(oldbds => ({ oldbds, inkPts: Cast(oldbds.doc.data, InkField)?.inkData || [] }))
             .forEach(({ oldbds: { doc, x, y, width, height }, inkPts }) => {
                 Doc.GetProto(doc).data = new InkField(inkPts.map(ipt =>  // (new x — oldx) + newWidth * (oldxpoint /oldWidth)
-                ({
-                    X: (NumCast(doc.x) - x) + NumCast(doc.width) * ipt.X / width,
-                    Y: (NumCast(doc.y) - y) + NumCast(doc.height) * ipt.Y / height
-                })));
+                    ({
+                        X: (NumCast(doc.x) - x) + NumCast(doc.width) * ipt.X / width,
+                        Y: (NumCast(doc.y) - y) + NumCast(doc.height) * ipt.Y / height
+                    })));
                 Doc.SetNativeWidth(doc, undefined);
                 Doc.SetNativeHeight(doc, undefined);
             });
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 857d06ea7..01b83644e 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -47,6 +47,7 @@ import { PresBox } from './PresBox';
 import { RadialMenu } from './RadialMenu';
 import React = require("react");
 import { ScriptingBox } from "./ScriptingBox";
+import { FormattedTextBox } from "./formattedText/FormattedTextBox";
 const { Howl } = require('howler');
 
 interface Window {
@@ -670,6 +671,20 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
             const appearance = cm.findByDescription("UI Controls...");
             const appearanceItems: ContextMenuProps[] = appearance && "subitems" in appearance ? appearance.subitems : [];
             !Doc.UserDoc().noviceMode && templateDoc && appearanceItems.push({ description: "Open Template   ", event: () => this.props.addDocTab(templateDoc, "add:right"), icon: "eye" });
+            appearanceItems.push({
+                description: "Add a Field", event: () => {
+                    const alias = Doc.MakeAlias(this.rootDoc);
+                    alias.layout = FormattedTextBox.LayoutString("newfield");
+                    alias.title = "newfield";
+                    alias._yMargin = 10;
+                    alias._height = 35;
+                    alias._width = 100;
+                    alias.syncLayoutFieldWithTitle = true;
+                    alias.x = NumCast(this.rootDoc.x) + NumCast(this.rootDoc.width);
+                    alias.y = NumCast(this.rootDoc.y);
+                    this.props.addDocument?.(alias);
+                }, icon: "eye"
+            });
             DocListCast(this.Document.links).length && appearanceItems.splice(0, 0, { description: `${this.layoutDoc.hideLinkButton ? "Show" : "Hide"} Link Button`, event: action(() => this.layoutDoc.hideLinkButton = !this.layoutDoc.hideLinkButton), icon: "eye" });
             !appearance && cm.addItem({ description: "UI Controls...", subitems: appearanceItems, icon: "compass" });
 
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index 8039e777e..b98ec870a 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -1556,7 +1556,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
                         onScroll={this.onScroll} onDrop={this.ondrop} >
                         <div className={minimal ? "formattedTextBox-minimal" : `formattedTextBox-inner${rounded}${selPaddingClass}`} ref={this.createDropTarget}
                             style={{
-                                padding: this.layoutDoc._textBoxPadding ? StrCast(this.layoutDoc._textBoxPadding) : `${padding}px`,
+                                padding: StrCast(this.layoutDoc._textBoxPadding, `${padding}px`),
                                 pointerEvents: !active && !SnappingManager.GetIsDragging() ? (this.layoutDoc.isLinkButton ? "none" : undefined) : undefined
                             }}
                         />
-- 
cgit v1.2.3-70-g09d2


From 82b9c13e3fdcf883ce97a66e24ca1dbc80e6739a Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Thu, 29 Apr 2021 11:38:31 -0400
Subject: fixed up some caption things with carousel and other views.  made
 caption fontsizes increase with zoom level.

---
 src/client/views/StyleProvider.tsx                     |  7 +++++--
 .../views/collections/CollectionCarousel3DView.tsx     |  7 +++----
 .../views/collections/CollectionCarouselView.tsx       | 18 ++++++++++--------
 src/client/views/collections/CollectionMenu.tsx        |  5 ++---
 src/client/views/nodes/DocumentView.tsx                | 16 +++++++---------
 .../views/nodes/formattedText/FormattedTextBox.tsx     |  6 ++++--
 6 files changed, 31 insertions(+), 28 deletions(-)

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

diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx
index 0fca61913..8cb8fea11 100644
--- a/src/client/views/StyleProvider.tsx
+++ b/src/client/views/StyleProvider.tsx
@@ -43,6 +43,7 @@ export enum StyleProp {
     ShowTitle = "showTitle",              // whether to display a title on a Document (optional :hover suffix)
     JitterRotation = "jitterRotation",    // whether documents should be randomly rotated
     BorderPath = "customBorder",          // border path for document view
+    FontSize = "fontSize",                // size of text font
 }
 
 function darkScheme() { return BoolCast(CurrentUserUtils.ActiveDashboard?.darkScheme); }
@@ -70,12 +71,12 @@ export function wavyBorderPath(pw: number, ph: number, inset: number = 0.05) {
 // 
 export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps>, property: string): any {
     const docProps = testDocProps(props) ? props : undefined;
-    const fieldKey = (props as any)?.fieldKey ? (props as any).fieldKey + "-" : "";
     const selected = property.includes(":selected");
     const isCaption = property.includes(":caption");
     const isAnchor = property.includes(":anchor");
     const isAnnotated = property.includes(":annotated");
     const isOpen = property.includes(":open");
+    const fieldKey = (props as any)?.fieldKey ? (props as any).fieldKey + "-" : isCaption ? "caption-" : "";
     const comicStyle = () => doc && !Doc.IsSystem(doc) && Doc.UserDoc().renderStyle === "comic";
     const isBackground = () => StrListCast(doc?._layerTags).includes(StyleLayers.Background);
     const backgroundCol = () => props?.styleProvider?.(doc, props, StyleProp.BackgroundColor);
@@ -88,6 +89,7 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
         case StyleProp.WidgetColor: return isAnnotated ? "lightBlue" : darkScheme() ? "lightgrey" : "dimgrey";
         case StyleProp.Opacity: return Cast(doc?._opacity, "number", Cast(doc?.opacity, "number", null));
         case StyleProp.HideLinkButton: return props?.hideLinkButton || (!selected && (doc?.isLinkButton || doc?.hideLinkButton));
+        case StyleProp.FontSize: return StrCast(doc?.[fieldKey + "fontSize"]);
         case StyleProp.ShowTitle: return doc && !doc.presentationTargetDoc && StrCast(doc._showTitle,
             !Doc.IsSystem(doc) && doc.type === DocumentType.RTF ?
                 (doc.author === Doc.CurrentUserEmail ? StrCast(Doc.UserDoc().showTitle) : "author;creationDate") : "") || "";
@@ -102,7 +104,7 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
             if (colsum / col.alpha() > 400 || col.alpha() < 0.25) return "black";
             return "white";
         case StyleProp.Hidden: return BoolCast(doc?._hidden);
-        case StyleProp.BorderRounding: return StrCast(doc?.[fieldKey + "borderRounding"], StrCast(doc?._borderRounding));
+        case StyleProp.BorderRounding: return StrCast(doc?.[fieldKey + "borderRounding"]);
         case StyleProp.TitleHeight: return 15;
         case StyleProp.BorderPath: return comicStyle() && props?.renderDepth ? { path: wavyBorderPath(props?.PanelWidth?.() || 0, props?.PanelHeight?.() || 0), fill: wavyBorderPath(props?.PanelWidth?.() || 0, props?.PanelHeight?.() || 0, .08), width: 3 } : { path: undefined, width: 0 };
         case StyleProp.JitterRotation: return comicStyle() ? random(-1, 1, NumCast(doc?.x), NumCast(doc?.y)) * ((props?.PanelWidth() || 0) > (props?.PanelHeight() || 0) ? 5 : 10) : 0;
@@ -124,6 +126,7 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
                 case DocumentType.BUTTON: docColor = docColor || (darkScheme() ? "#2d2d2d" : "lightgray"); break;
                 case DocumentType.LINKANCHOR: docColor = isAnchor ? "lightblue" : "transparent"; break;
                 case DocumentType.LINK: docColor = docColor || "transparent"; break;
+                case DocumentType.IMG:
                 case DocumentType.WEB:
                 case DocumentType.PDF:
                 case DocumentType.SCREENSHOT:
diff --git a/src/client/views/collections/CollectionCarousel3DView.tsx b/src/client/views/collections/CollectionCarousel3DView.tsx
index 2251b60e5..3c66faf0c 100644
--- a/src/client/views/collections/CollectionCarousel3DView.tsx
+++ b/src/client/views/collections/CollectionCarousel3DView.tsx
@@ -133,10 +133,9 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume
     }
 
     @computed get dots() {
-        return (this.childLayoutPairs.map((_child, index) => {
-            return <div key={Utils.GenerateGuid()} className={`dot${index === NumCast(this.layoutDoc._itemIndex) ? "-active" : ""}`}
-                onClick={() => this.layoutDoc._itemIndex = index} />;
-        }));
+        return (this.childLayoutPairs.map((_child, index) =>
+            <div key={Utils.GenerateGuid()} className={`dot${index === NumCast(this.layoutDoc._itemIndex) ? "-active" : ""}`}
+                onClick={() => this.layoutDoc._itemIndex = index} />));
     }
 
     render() {
diff --git a/src/client/views/collections/CollectionCarouselView.tsx b/src/client/views/collections/CollectionCarouselView.tsx
index cd81a99c9..6c2c27e8e 100644
--- a/src/client/views/collections/CollectionCarouselView.tsx
+++ b/src/client/views/collections/CollectionCarouselView.tsx
@@ -38,9 +38,10 @@ export class CollectionCarouselView extends CollectionSubView(CarouselDocument)
         e.stopPropagation();
         this.layoutDoc._itemIndex = (NumCast(this.layoutDoc._itemIndex) - 1 + this.childLayoutPairs.length) % this.childLayoutPairs.length;
     }
-    captionStyleProvider = (doc: (Doc | undefined), props: Opt<DocumentViewProps>, property: string): any => {
-        const captionProps = { ...this.props, fieldKey: "caption" };
-        return this.props.styleProvider?.(doc, props, property) || this.props.styleProvider?.(this.layoutDoc, captionProps, property);
+    captionStyleProvider = (doc: (Doc | undefined), captionProps: Opt<DocumentViewProps>, property: string): any => {
+        // first look for properties on the document in the carousel, then fallback to properties on the container
+        const childValue = doc?.["caption-" + property] ? this.props.styleProvider?.(doc, captionProps, property) : undefined;
+        return childValue ?? this.props.styleProvider?.(this.layoutDoc, captionProps, property);
     }
     panelHeight = () => this.props.PanelHeight() - (StrCast(this.layoutDoc._showCaption) ? 50 : 0);
     onContentDoubleClick = () => ScriptCast(this.layoutDoc.onChildDoubleClick);
@@ -51,12 +52,14 @@ export class CollectionCarouselView extends CollectionSubView(CarouselDocument)
         const captionProps = { ...this.props, fieldKey: "caption" };
         const marginX = NumCast(this.layoutDoc["caption-xMargin"]);
         const marginY = NumCast(this.layoutDoc["caption-yMargin"]);
+        const showCaptions = StrCast(this.layoutDoc._showCaption);
         return !(curDoc?.layout instanceof Doc) ? (null) :
             <>
                 <div className="collectionCarouselView-image" key="image">
                     <DocumentView  {...OmitKeys(this.props, ["NativeWidth", "NativeHeight", "childLayoutTemplate", "childLayoutString"]).omit}
                         onDoubleClick={this.onContentDoubleClick}
                         onClick={this.onContentClick}
+                        hideCaptions={showCaptions ? true : false}
                         renderDepth={this.props.renderDepth + 1}
                         ContainingCollectionView={this}
                         LayoutTemplate={this.props.childLayoutTemplate}
@@ -69,17 +72,16 @@ export class CollectionCarouselView extends CollectionSubView(CarouselDocument)
                 </div>
                 <div className="collectionCarouselView-caption" key="caption"
                     style={{
-                        display: StrCast(this.layoutDoc._showCaption) ? undefined : "none",
+                        display: showCaptions ? undefined : "none",
                         borderRadius: this.props.styleProvider?.(this.layoutDoc, captionProps, StyleProp.BorderRounding),
                         marginRight: marginX, marginLeft: marginX,
                         width: `calc(100% - ${marginX * 2}px)`
                     }}>
                     <FormattedTextBox key={index} {...captionProps}
+                        fieldKey={showCaptions}
                         styleProvider={this.captionStyleProvider}
-                        Document={curDoc.layout} DataDoc={undefined}
-                        fontSize={NumCast(this.layoutDoc["caption-fontSize"])}
-                        xPadding={NumCast(this.layoutDoc["caption-xPadding"])}
-                        yPadding={NumCast(this.layoutDoc["caption-yPadding"])} />
+                        Document={curDoc.layout}
+                        DataDoc={undefined} />
                 </div>
             </>;
     }
diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx
index 08290a9b3..6e6fabd0d 100644
--- a/src/client/views/collections/CollectionMenu.tsx
+++ b/src/client/views/collections/CollectionMenu.tsx
@@ -763,7 +763,7 @@ export class CollectionFreeFormViewChrome extends React.Component<CollectionMenu
     render() {
         return !this.props.docView.layoutDoc ? (null) :
             <div className="collectionFreeFormMenu-cont">
-
+                <RichTextMenu key="rich" />
                 {!this.isText ?
                     <>
                         {this.drawButtons}
@@ -789,8 +789,7 @@ export class CollectionFreeFormViewChrome extends React.Component<CollectionMenu
                                     </div>
                                 </Tooltip>
                             </>}
-                    </> :
-                    <RichTextMenu />
+                    </> : (null)
                 }
                 {!this.selectedDocumentView?.ComponentView?.menuControls ? (null) : this.selectedDocumentView?.ComponentView?.menuControls?.()}
             </div>;
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 37394ba83..7ec9f5f74 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -121,6 +121,7 @@ export interface DocumentViewSharedProps {
     dropAction?: dropActionType;
     dontRegisterView?: boolean;
     hideLinkButton?: boolean;
+    hideCaptions?: boolean;
     ignoreAutoHeight?: boolean;
     disableDocBrushing?: boolean; // should highlighting for this view be disabled when same document in another view is hovered over.
     pointerEvents?: string;
@@ -908,22 +909,19 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
         TraceMobx();
         const showTitle = this.ShowTitle?.split(":")[0];
         const showTitleHover = this.ShowTitle?.includes(":hover");
-        const showCaption = StrCast(this.layoutDoc._showCaption) && this.Document._viewType !== CollectionViewType.Carousel;
+        const showCaption = !this.props.hideCaptions && this.Document._viewType !== CollectionViewType.Carousel ? StrCast(this.layoutDoc._showCaption) : undefined;
         const captionView = !showCaption ? (null) :
-            <div className="documentView-captionWrapper"
-                style={{
-                    backgroundColor: StrCast(this.layoutDoc["caption-backgroundColor"]),
-                    color: StrCast(this.layoutDoc["caption-color"])
-                }}>
-                <DocumentContentsView {...OmitKeys(this.props, ['children']).omit}
+            <div className="documentView-captionWrapper">
+                <FormattedTextBox {...OmitKeys(this.props, ['children']).omit}
                     yPadding={10}
                     xPadding={10}
+                    fieldKey={showCaption}
+                    fontSize={Math.min(32, 12 * this.props.ScreenToLocalTransform().Scale)}
                     hideOnLeave={true}
                     styleProvider={this.captionStyleProvider}
                     dontRegisterView={true}
-                    LayoutTemplateString={`<FormattedTextBox {...props} fieldKey={'${showCaption}'}/>`}
                     onClick={this.onClickFunc}
-                    layoutKey={this.finalLayoutKey} />
+                />
             </div>;
         const titleView = !showTitle ? (null) :
             <div className={`documentView-titleWrapper${showTitleHover ? "-hover" : ""}`} key="title" style={{
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index b98ec870a..2a1ff5540 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -1514,6 +1514,8 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
         const selPad = Math.min(margins, 10);
         const padding = Math.max(margins + ((selected && !this.layoutDoc._singleLine) || minimal ? -selPad : 0), 0);
         const selPaddingClass = selected && !this.layoutDoc._singleLine && margins >= 10 ? "-selected" : "";
+        const col = this.props.color ? this.props.color : this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.Color);
+        const back = this.props.background ? this.props.background : this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.BackgroundColor);
         return (
             <div className="formattedTextBox-cont"
                 onWheel={e => this.isContentActive() && e.stopPropagation()}
@@ -1531,10 +1533,10 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
                         height: this.props.height || (this.autoHeight && this.props.renderDepth ? "max-content" : undefined),
                         background: this.props.background ? this.props.background : this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.BackgroundColor),
                         color: this.props.color ? this.props.color : this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.Color),
-                        pointerEvents: interactive ? undefined : "none",
-                        fontSize: this.props.fontSize || Cast(this.layoutDoc._fontSize, "string", null),
+                        fontSize: this.props.fontSize ? this.props.fontSize : this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.FontSize),
                         fontWeight: Cast(this.layoutDoc._fontWeight, "number", null),
                         fontFamily: StrCast(this.layoutDoc._fontFamily, "inherit"),
+                        pointerEvents: interactive ? undefined : "none",
                     }}
                     onContextMenu={this.specificContextMenu}
                     onKeyDown={this.onKeyDown}
-- 
cgit v1.2.3-70-g09d2


From c05e2330189a78b6fb14dd5181b38478bb20917e Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Wed, 12 May 2021 12:40:56 -0400
Subject: adjusted scroll focus of text docs to position scrollbar so that
 target is in view

---
 src/client/views/nodes/formattedText/FormattedTextBox.tsx | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

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

diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index 2a1ff5540..911ec1560 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -1075,8 +1075,11 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
                     const docPos = editorView.coordsAtPos(editorView.state.selection.to);
                     const viewRect = self._ref.current!.getBoundingClientRect();
                     const scrollRef = self._scrollRef.current;
-                    if ((docPos.bottom < viewRect.top || docPos.bottom > viewRect.bottom) && scrollRef) {
-                        const scrollPos = scrollRef.scrollTop + (docPos.bottom - viewRect.top) * self.props.ScreenToLocalTransform().Scale;
+                    const topOff = docPos.top < viewRect.top ? docPos.top - viewRect.top : undefined;
+                    const botOff = docPos.bottom > viewRect.bottom ? docPos.bottom - viewRect.bottom : undefined;
+                    if ((topOff || botOff) && scrollRef) {
+                        const shift = Math.min(topOff ?? Number.MAX_VALUE, botOff ?? Number.MAX_VALUE);
+                        const scrollPos = scrollRef.scrollTop + shift * self.props.ScreenToLocalTransform().Scale;
                         if (this._focusSpeed !== undefined) {
                             scrollPos && smoothScroll(this._focusSpeed, scrollRef, scrollPos);
                         } else {
-- 
cgit v1.2.3-70-g09d2

