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.

---
 .../views/collections/CollectionCarousel3DView.tsx | 23 +---------------------
 1 file changed, 1 insertion(+), 22 deletions(-)

(limited to 'src/client/views/collections/CollectionCarousel3DView.tsx')

diff --git a/src/client/views/collections/CollectionCarousel3DView.tsx b/src/client/views/collections/CollectionCarousel3DView.tsx
index b2ae441d6..9a3183d88 100644
--- a/src/client/views/collections/CollectionCarousel3DView.tsx
+++ b/src/client/views/collections/CollectionCarousel3DView.tsx
@@ -104,27 +104,6 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume
         }, 1500);
     }
 
-    _downX = 0;
-    _downY = 0;
-    onPointerDown = (e: React.PointerEvent) => {
-        this._downX = e.clientX;
-        this._downY = e.clientY;
-        document.addEventListener("pointerup", this.onpointerup);
-    }
-    private _lastTap: number = 0;
-    private _doubleTap = false;
-    onpointerup = (e: PointerEvent) => {
-        this._doubleTap = (Date.now() - this._lastTap < 300 && e.button === 0 && Math.abs(e.clientX - this._downX) < 2 && Math.abs(e.clientY - this._downY) < 2);
-        this._lastTap = Date.now();
-    }
-
-    onClick = (e: React.MouseEvent) => {
-        if (this._doubleTap) {
-            e.stopPropagation();
-            this.props.Document.isLightboxOpen = true;
-        }
-    }
-
     @computed get buttons() {
         if (!this.props.isContentActive()) return null;
         return <div className="arrow-buttons" >
@@ -167,7 +146,7 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume
         const index = NumCast(this.layoutDoc._itemIndex);
         const translateX = this.panelWidth() * (1 - index);
 
-        return <div className="collectionCarousel3DView-outer" onClick={this.onClick} onPointerDown={this.onPointerDown} ref={this.createDashEventsTarget}>
+        return <div className="collectionCarousel3DView-outer" ref={this.createDashEventsTarget}>
             <div className="carousel-wrapper" style={{ transform: `translateX(${translateX}px)` }}>
                 {this.content}
             </div>
-- 
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/collections/CollectionCarousel3DView.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 70f92c85461dc50fb0e63d3ecd5c429bcae37cc7 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Thu, 15 Apr 2021 00:20:57 -0400
Subject: simplified carousel DocumentView calls.

---
 .../views/collections/CollectionCarousel3DView.tsx | 35 ++++------------------
 .../views/collections/CollectionCarouselView.tsx   | 33 +++++---------------
 2 files changed, 13 insertions(+), 55 deletions(-)

(limited to 'src/client/views/collections/CollectionCarousel3DView.tsx')

diff --git a/src/client/views/collections/CollectionCarousel3DView.tsx b/src/client/views/collections/CollectionCarousel3DView.tsx
index 7cebabaa9..2251b60e5 100644
--- a/src/client/views/collections/CollectionCarousel3DView.tsx
+++ b/src/client/views/collections/CollectionCarousel3DView.tsx
@@ -9,7 +9,7 @@ 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, dropActionType } from '../../util/DragManager';
+import { DragManager } from '../../util/DragManager';
 import { DocumentView } from '../nodes/DocumentView';
 import "./CollectionCarousel3DView.scss";
 import { CollectionSubView } from './CollectionSubView';
@@ -41,38 +41,15 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume
     @computed get content() {
         const currentIndex = NumCast(this.layoutDoc._itemIndex);
         const displayDoc = (childPair: { layout: Doc, data: Doc }) => {
-            const script = ScriptField.MakeScript("this._showCaption = 'caption'", { this: Doc.name });
-            const onChildClick = script && (() => script);
-            return <DocumentView
-                Document={childPair.layout}
-                DataDoc={childPair.layout.resolvedDataDoc as Doc}
-                styleProvider={this.props.styleProvider}
-                layerProvider={this.props.layerProvider}
-                docViewPath={this.props.docViewPath}
+            return <DocumentView  {...OmitKeys(this.props, ["NativeWidth", "NativeHeight", "childLayoutTemplate", "childLayoutString"]).omit}
+                onDoubleClick={this.onChildDoubleClick}
+                renderDepth={this.props.renderDepth + 1}
                 LayoutTemplate={this.props.childLayoutTemplate}
                 LayoutTemplateString={this.props.childLayoutString}
-                freezeDimensions={this.props.childFreezeDimensions}
-                renderDepth={this.props.renderDepth + 1}
+                Document={childPair.layout}
+                DataDoc={childPair.data}
                 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}
             />;
         };
diff --git a/src/client/views/collections/CollectionCarouselView.tsx b/src/client/views/collections/CollectionCarouselView.tsx
index 4a7bdf6db..d28a4d87d 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, dropActionType } from '../../util/DragManager';
+import { DragManager } from '../../util/DragManager';
 import { DocumentView } from '../nodes/DocumentView';
 import { FormattedTextBox } from '../nodes/formattedText/FormattedTextBox';
 import { StyleProp } from '../StyleProvider';
@@ -47,34 +47,15 @@ export class CollectionCarouselView extends CollectionSubView(CarouselDocument)
         return !(curDoc?.layout instanceof Doc) ? (null) :
             <>
                 <div className="collectionCarouselView-image" key="image">
-                    <DocumentView
-                        Document={curDoc.layout}
-                        DataDoc={curDoc.layout.resolvedDataDoc as Doc}
-                        styleProvider={this.props.styleProvider}
-                        layerProvider={this.props.layerProvider}
-                        docViewPath={this.props.docViewPath}
+                    <DocumentView  {...OmitKeys(this.props, ["NativeWidth", "NativeHeight", "childLayoutTemplate", "childLayoutString"]).omit}
+                        onDoubleClick={this.onContentDoubleClick}
+                        onClick={this.onContentClick}
+                        renderDepth={this.props.renderDepth + 1}
                         LayoutTemplate={this.props.childLayoutTemplate}
                         LayoutTemplateString={this.props.childLayoutString}
-                        freezeDimensions={this.props.childFreezeDimensions}
-                        renderDepth={this.props.renderDepth + 1}
-                        PanelWidth={this.props.PanelWidth}
+                        Document={curDoc.layout}
+                        DataDoc={curDoc.layout.resolvedDataDoc as Doc}
                         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>
-- 
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/collections/CollectionCarousel3DView.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

