From bf94b54dba511bb4badb0ffcb9f017dc9a81942e Mon Sep 17 00:00:00 2001
From: Melissa Zhang <mzhang19096@gmail.com>
Date: Fri, 15 May 2020 20:13:20 -0700
Subject: branch setup

---
 .../views/collections/CollectionCarousel3DView.tsx | 125 +++++++++++++++++++++
 1 file changed, 125 insertions(+)
 create mode 100644 src/client/views/collections/CollectionCarousel3DView.tsx

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

diff --git a/src/client/views/collections/CollectionCarousel3DView.tsx b/src/client/views/collections/CollectionCarousel3DView.tsx
new file mode 100644
index 000000000..4de35a978
--- /dev/null
+++ b/src/client/views/collections/CollectionCarousel3DView.tsx
@@ -0,0 +1,125 @@
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { observable, computed } from 'mobx';
+import { observer } from 'mobx-react';
+import * as React from 'react';
+import { documentSchema } from '../../../new_fields/documentSchemas';
+import { makeInterface } from '../../../new_fields/Schema';
+import { NumCast, StrCast } from '../../../new_fields/Types';
+import { DragManager } from '../../util/DragManager';
+import { ContentFittingDocumentView } from '../nodes/ContentFittingDocumentView';
+import "./CollectionCarousel3DView.scss";
+import { CollectionSubView } from './CollectionSubView';
+import { faCaretLeft, faCaretRight } from '@fortawesome/free-solid-svg-icons';
+import { Doc } from '../../../new_fields/Doc';
+import { FormattedTextBox } from '../nodes/formattedText/FormattedTextBox';
+import { ContextMenu } from '../ContextMenu';
+import { ObjectField } from '../../../new_fields/ObjectField';
+
+type Carousel3DDocument = makeInterface<[typeof documentSchema,]>;
+const Carousel3DDocument = makeInterface(documentSchema);
+
+@observer
+export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocument) {
+    private _dropDisposer?: DragManager.DragDropDisposer;
+
+    componentWillUnmount() { this._dropDisposer?.(); }
+
+    protected createDashEventsTarget = (ele: HTMLDivElement) => { //used for stacking and masonry view
+        this._dropDisposer?.();
+        if (ele) {
+            this._dropDisposer = DragManager.MakeDropTarget(ele, this.onInternalDrop.bind(this), this.layoutDoc);
+        }
+    }
+
+    advance = (e: React.MouseEvent) => {
+        e.stopPropagation();
+        this.layoutDoc._itemIndex = (NumCast(this.layoutDoc._itemIndex) + 1) % this.childLayoutPairs.length;
+    }
+    goback = (e: React.MouseEvent) => {
+        e.stopPropagation();
+        this.layoutDoc._itemIndex = (NumCast(this.layoutDoc._itemIndex) - 1 + this.childLayoutPairs.length) % this.childLayoutPairs.length;
+    }
+
+    panelHeight = () => this.props.PanelHeight() - 50;
+    @computed get content() {
+        const index = NumCast(this.layoutDoc._itemIndex);
+        return !(this.childLayoutPairs?.[index]?.layout instanceof Doc) ? (null) :
+            <>
+                <div className="collectionCarouselView-prev"></div>
+                <div className="collectionCarouselView-next"></div>
+                <div className="collectionCarouselView-center-container">
+                    <div className="collectionCarouselView-image" key="image">
+                        <ContentFittingDocumentView {...this.props}
+                            renderDepth={this.props.renderDepth + 1}
+                            Document={this.childLayoutPairs[index].layout}
+                            DataDocument={this.childLayoutPairs[index].data}
+                            PanelHeight={this.panelHeight}
+                            getTransform={this.props.ScreenToLocalTransform} />
+                    </div>
+                    <div className="collectionCarouselView-caption" key="caption"
+                        style={{
+                            background: StrCast(this.layoutDoc._captionBackgroundColor, this.props.backgroundColor?.(this.props.Document)),
+                            color: StrCast(this.layoutDoc._captionColor, StrCast(this.layoutDoc.color)),
+                            borderRadius: StrCast(this.layoutDoc._captionBorderRounding),
+                        }}>
+                        <FormattedTextBox key={index} {...this.props}
+                            xMargin={NumCast(this.layoutDoc["caption-xMargin"])}
+                            yMargin={NumCast(this.layoutDoc["caption-yMargin"])}
+                            Document={this.childLayoutPairs[index].layout} DataDoc={undefined} fieldKey={"caption"}></FormattedTextBox>
+                    </div>
+                </div>
+            </>;
+    }
+    @computed get buttons() {
+        return <>
+            <div key="back" className="carouselView-back" style={{ background: `${StrCast(this.props.Document.backgroundColor)}` }} onClick={this.goback}>
+                <FontAwesomeIcon icon={faCaretLeft} size={"2x"} />
+            </div>
+            <div key="fwd" className="carouselView-fwd" style={{ background: `${StrCast(this.props.Document.backgroundColor)}` }} onClick={this.advance}>
+                <FontAwesomeIcon icon={faCaretRight} size={"2x"} />
+            </div>
+        </>;
+    }
+
+
+    onContextMenu = (e: React.MouseEvent): void => {
+        // need to test if propagation has stopped because GoldenLayout forces a parallel react hierarchy to be created for its top-level layout
+        if (!e.isPropagationStopped()) {
+            ContextMenu.Instance.addItem({
+                description: "Make Hero Image", event: () => {
+                    const index = NumCast(this.layoutDoc._itemIndex);
+                    (this.dataDoc || Doc.GetProto(this.props.Document)).hero = ObjectField.MakeCopy(this.childLayoutPairs[index].layout.data as ObjectField);
+                }, icon: "plus"
+            });
+        }
+    }
+    _downX = 0;
+    _downY = 0;
+    onPointerDown = (e: React.PointerEvent) => {
+        this._downX = e.clientX;
+        this._downY = e.clientY;
+        console.log("CAROUSEL down");
+        document.addEventListener("pointerup", this.onpointerup);
+    }
+    private _lastTap: number = 0;
+    private _doubleTap = false;
+    onpointerup = (e: PointerEvent) => {
+        console.log("CAROUSEL up");
+        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;
+        }
+    }
+
+    render() {
+        return <div className="collectionCarouselView-outer" onClick={this.onClick} onPointerDown={this.onPointerDown} ref={this.createDashEventsTarget} onContextMenu={this.onContextMenu}>
+            {this.content}
+            {this.props.Document._chromeStatus !== "replaced" ? this.buttons : (null)}
+        </div>;
+    }
+}
\ No newline at end of file
-- 
cgit v1.2.3-70-g09d2


From 3c6e288fa031e8871618170d3b8d6db66dd3c66b Mon Sep 17 00:00:00 2001
From: Melissa Zhang <mzhang19096@gmail.com>
Date: Sun, 17 May 2020 23:38:58 -0700
Subject: add 3D carousel view to code base

---
 src/client/documents/Documents.ts                  |  4 ++
 .../views/collections/CollectionCarousel3DView.tsx | 60 ++++++++++------------
 src/client/views/collections/CollectionView.tsx    |  4 ++
 .../views/collections/CollectionViewChromes.tsx    |  1 +
 4 files changed, 35 insertions(+), 34 deletions(-)

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

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 18a0b43ff..47e13c8e2 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -670,6 +670,10 @@ export namespace Docs {
             return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _chromeStatus: "collapsed", schemaColumns: new List([new SchemaHeaderField("title", "#f1efeb")]), ...options, _viewType: CollectionViewType.Carousel });
         }
 
+        export function Carousel3DDocument(documents: Array<Doc>, options: DocumentOptions) {
+            return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _chromeStatus: "collapsed", schemaColumns: new List([new SchemaHeaderField("title", "#f1efeb")]), ...options, _viewType: CollectionViewType.Carousel3D });
+        }
+
         export function SchemaDocument(schemaColumns: SchemaHeaderField[], documents: Array<Doc>, options: DocumentOptions) {
             return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _chromeStatus: "collapsed", schemaColumns: new List(schemaColumns), ...options, _viewType: CollectionViewType.Schema });
         }
diff --git a/src/client/views/collections/CollectionCarousel3DView.tsx b/src/client/views/collections/CollectionCarousel3DView.tsx
index 4de35a978..8839658d6 100644
--- a/src/client/views/collections/CollectionCarousel3DView.tsx
+++ b/src/client/views/collections/CollectionCarousel3DView.tsx
@@ -2,21 +2,20 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { observable, computed } from 'mobx';
 import { observer } from 'mobx-react';
 import * as React from 'react';
-import { documentSchema } from '../../../new_fields/documentSchemas';
-import { makeInterface } from '../../../new_fields/Schema';
-import { NumCast, StrCast } from '../../../new_fields/Types';
+import { documentSchema, collectionSchema } from '../../../fields/documentSchemas';
+import { makeInterface } from '../../../fields/Schema';
+import { NumCast, StrCast, ScriptCast, Cast } from '../../../fields/Types';
 import { DragManager } from '../../util/DragManager';
 import { ContentFittingDocumentView } from '../nodes/ContentFittingDocumentView';
 import "./CollectionCarousel3DView.scss";
 import { CollectionSubView } from './CollectionSubView';
-import { faCaretLeft, faCaretRight } from '@fortawesome/free-solid-svg-icons';
-import { Doc } from '../../../new_fields/Doc';
-import { FormattedTextBox } from '../nodes/formattedText/FormattedTextBox';
+import { Doc } from '../../../fields/Doc';
 import { ContextMenu } from '../ContextMenu';
-import { ObjectField } from '../../../new_fields/ObjectField';
+import { ObjectField } from '../../../fields/ObjectField';
+import { returnFalse } from '../../../Utils';
 
-type Carousel3DDocument = makeInterface<[typeof documentSchema,]>;
-const Carousel3DDocument = makeInterface(documentSchema);
+type Carousel3DDocument = makeInterface<[typeof documentSchema, typeof collectionSchema]>;
+const Carousel3DDocument = makeInterface(documentSchema, collectionSchema);
 
 @observer
 export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocument) {
@@ -39,44 +38,37 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume
         e.stopPropagation();
         this.layoutDoc._itemIndex = (NumCast(this.layoutDoc._itemIndex) - 1 + this.childLayoutPairs.length) % this.childLayoutPairs.length;
     }
-
     panelHeight = () => this.props.PanelHeight() - 50;
     @computed get content() {
         const index = NumCast(this.layoutDoc._itemIndex);
         return !(this.childLayoutPairs?.[index]?.layout instanceof Doc) ? (null) :
             <>
-                <div className="collectionCarouselView-prev"></div>
-                <div className="collectionCarouselView-next"></div>
-                <div className="collectionCarouselView-center-container">
-                    <div className="collectionCarouselView-image" key="image">
-                        <ContentFittingDocumentView {...this.props}
-                            renderDepth={this.props.renderDepth + 1}
-                            Document={this.childLayoutPairs[index].layout}
-                            DataDocument={this.childLayoutPairs[index].data}
-                            PanelHeight={this.panelHeight}
-                            getTransform={this.props.ScreenToLocalTransform} />
-                    </div>
-                    <div className="collectionCarouselView-caption" key="caption"
-                        style={{
-                            background: StrCast(this.layoutDoc._captionBackgroundColor, this.props.backgroundColor?.(this.props.Document)),
-                            color: StrCast(this.layoutDoc._captionColor, StrCast(this.layoutDoc.color)),
-                            borderRadius: StrCast(this.layoutDoc._captionBorderRounding),
-                        }}>
-                        <FormattedTextBox key={index} {...this.props}
-                            xMargin={NumCast(this.layoutDoc["caption-xMargin"])}
-                            yMargin={NumCast(this.layoutDoc["caption-yMargin"])}
-                            Document={this.childLayoutPairs[index].layout} DataDoc={undefined} fieldKey={"caption"}></FormattedTextBox>
-                    </div>
+                <div className="collectionCarouselView-prev" />
+                <div className="collectionCarouselView-next" />
+                <div className="collectionCarouselView-image" key="image">
+                    <ContentFittingDocumentView {...this.props}
+                        onDoubleClick={ScriptCast(this.layoutDoc.onChildDoubleClick)}
+                        onClick={ScriptCast(this.layoutDoc.onChildClick)}
+                        renderDepth={this.props.renderDepth + 1}
+                        LayoutTemplate={this.props.ChildLayoutTemplate}
+                        LayoutTemplateString={this.props.ChildLayoutString}
+                        Document={this.childLayoutPairs[index].layout}
+                        DataDoc={this.childLayoutPairs[index].data}
+                        PanelHeight={this.panelHeight}
+                        ScreenToLocalTransform={this.props.ScreenToLocalTransform}
+                        bringToFront={returnFalse}
+                        parentActive={this.props.active}
+                    />
                 </div>
             </>;
     }
     @computed get buttons() {
         return <>
             <div key="back" className="carouselView-back" style={{ background: `${StrCast(this.props.Document.backgroundColor)}` }} onClick={this.goback}>
-                <FontAwesomeIcon icon={faCaretLeft} size={"2x"} />
+                <FontAwesomeIcon icon={"caret-left"} size={"2x"} />
             </div>
             <div key="fwd" className="carouselView-fwd" style={{ background: `${StrCast(this.props.Document.backgroundColor)}` }} onClick={this.advance}>
-                <FontAwesomeIcon icon={faCaretRight} size={"2x"} />
+                <FontAwesomeIcon icon={"caret-right"} size={"2x"} />
             </div>
         </>;
     }
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index 3b2e5e4fc..8d6866632 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -21,6 +21,7 @@ import { FieldView, FieldViewProps } from '../nodes/FieldView';
 import { ScriptBox } from '../ScriptBox';
 import { Touchable } from '../Touchable';
 import { CollectionCarouselView } from './CollectionCarouselView';
+import { CollectionCarousel3DView } from './CollectionCarousel3DView';
 import { CollectionDockingView } from "./CollectionDockingView";
 import { AddCustomFreeFormLayout } from './collectionFreeForm/CollectionFreeFormLayoutEngines';
 import { CollectionFreeFormView } from './collectionFreeForm/CollectionFreeFormView';
@@ -63,6 +64,7 @@ export enum CollectionViewType {
     Multirow = "multirow",
     Time = "time",
     Carousel = "carousel",
+    Carousel3D = "3D carousel",
     Linear = "linear",
     Staff = "staff",
     Map = "map",
@@ -183,6 +185,7 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus
             case CollectionViewType.Linear: { return (<CollectionLinearView key="collview" {...props} />); }
             case CollectionViewType.Pile: { return (<CollectionPileView key="collview" {...props} />); }
             case CollectionViewType.Carousel: { return (<CollectionCarouselView key="collview" {...props} />); }
+            case CollectionViewType.Carousel3D: { return (<CollectionCarousel3DView key="collview" {...props} />); }
             case CollectionViewType.Stacking: { this.props.Document.singleColumn = true; return (<CollectionStackingView key="collview" {...props} />); }
             case CollectionViewType.Masonry: { this.props.Document.singleColumn = false; return (<CollectionStackingView key="collview" {...props} />); }
             case CollectionViewType.Time: { return (<CollectionTimeView key="collview" {...props} />); }
@@ -222,6 +225,7 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus
         subItems.push({ description: "Multirow", event: () => func(CollectionViewType.Multirow), icon: "columns" });
         subItems.push({ description: "Masonry", event: () => func(CollectionViewType.Masonry), icon: "columns" });
         subItems.push({ description: "Carousel", event: () => func(CollectionViewType.Carousel), icon: "columns" });
+        subItems.push({ description: "3D Carousel", event: () => func(CollectionViewType.Carousel3D), icon: "columns" });
         subItems.push({ description: "Pivot/Time", event: () => func(CollectionViewType.Time), icon: "columns" });
         subItems.push({ description: "Map", event: () => func(CollectionViewType.Map), icon: "globe-americas" });
         if (addExtras && this.props.Document._viewType === CollectionViewType.Freeform) {
diff --git a/src/client/views/collections/CollectionViewChromes.tsx b/src/client/views/collections/CollectionViewChromes.tsx
index 5dc0b09ac..53860d8ad 100644
--- a/src/client/views/collections/CollectionViewChromes.tsx
+++ b/src/client/views/collections/CollectionViewChromes.tsx
@@ -75,6 +75,7 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewChro
             case CollectionViewType.Freeform: return this._freeform_commands;
             case CollectionViewType.Time: return this._freeform_commands;
             case CollectionViewType.Carousel: return this._freeform_commands;
+            case CollectionViewType.Carousel3D: return this._freeform_commands;
         }
         return [];
     }
-- 
cgit v1.2.3-70-g09d2


From ba688bb39f5c863a1e91166feae3ac843750348c Mon Sep 17 00:00:00 2001
From: Melissa Zhang <mzhang19096@gmail.com>
Date: Mon, 18 May 2020 00:33:19 -0700
Subject: rough 3D layout, add prev/next images

---
 .../collections/CollectionCarousel3DView.scss      | 27 ++++++---------
 .../views/collections/CollectionCarousel3DView.tsx | 39 +++++++++++++++++++---
 2 files changed, 46 insertions(+), 20 deletions(-)

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

diff --git a/src/client/views/collections/CollectionCarousel3DView.scss b/src/client/views/collections/CollectionCarousel3DView.scss
index 2142eca39..ee92cde4c 100644
--- a/src/client/views/collections/CollectionCarousel3DView.scss
+++ b/src/client/views/collections/CollectionCarousel3DView.scss
@@ -2,27 +2,21 @@
     background: white;
     height: 100%;
 
-    .collectionCarouselView-center-container {
+    .collectionCarouselView-image {
+        overflow: hidden; //fix ContentFittingView size
+        position: absolute;
+        height: 100%;
         width: 70%;
+        top: 0;
+        left: 0;
+        right: 0;
+        bottom: 0;
         margin: auto;
-        overflow: hidden; //fix ContentFittingView position!!
-
-        .collectionCarouselView-caption {
-            height: 50;
-            display: inline-block;
-            width: 100%;
-            margin: auto;
-        }
-
-        .collectionCarouselView-image {
-            height: calc(100% - 50px);
-            width: 70%;
-            display: inline-block;
-            user-select: none;
-        }
+        user-select: none;
     }
 
     .collectionCarouselView-prev {
+        overflow: hidden;
         position: absolute;
         height: 50%;
         width: 50%;
@@ -32,6 +26,7 @@
     }
 
     .collectionCarouselView-next {
+        overflow: hidden;
         position: absolute;
         height: 50%;
         width: 50%;
diff --git a/src/client/views/collections/CollectionCarousel3DView.tsx b/src/client/views/collections/CollectionCarousel3DView.tsx
index 8839658d6..4452ceb6b 100644
--- a/src/client/views/collections/CollectionCarousel3DView.tsx
+++ b/src/client/views/collections/CollectionCarousel3DView.tsx
@@ -34,17 +34,48 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume
         e.stopPropagation();
         this.layoutDoc._itemIndex = (NumCast(this.layoutDoc._itemIndex) + 1) % this.childLayoutPairs.length;
     }
+
     goback = (e: React.MouseEvent) => {
         e.stopPropagation();
         this.layoutDoc._itemIndex = (NumCast(this.layoutDoc._itemIndex) - 1 + this.childLayoutPairs.length) % this.childLayoutPairs.length;
     }
-    panelHeight = () => this.props.PanelHeight() - 50;
+
     @computed get content() {
         const index = NumCast(this.layoutDoc._itemIndex);
+        const prevIndex = (index - 1 + this.childLayoutPairs.length) % this.childLayoutPairs.length;
+        const nextIndex = (index + 1 + this.childLayoutPairs.length) % this.childLayoutPairs.length;
         return !(this.childLayoutPairs?.[index]?.layout instanceof Doc) ? (null) :
             <>
-                <div className="collectionCarouselView-prev" />
-                <div className="collectionCarouselView-next" />
+                <div className="collectionCarouselView-prev">
+                    <ContentFittingDocumentView {...this.props}
+                        onDoubleClick={ScriptCast(this.layoutDoc.onChildDoubleClick)}
+                        onClick={ScriptCast(this.layoutDoc.onChildClick)}
+                        renderDepth={this.props.renderDepth + 1}
+                        LayoutTemplate={this.props.ChildLayoutTemplate}
+                        LayoutTemplateString={this.props.ChildLayoutString}
+                        Document={this.childLayoutPairs[prevIndex].layout}
+                        DataDoc={this.childLayoutPairs[prevIndex].data}
+                        PanelHeight={this.props.PanelHeight}
+                        ScreenToLocalTransform={this.props.ScreenToLocalTransform}
+                        bringToFront={returnFalse}
+                        parentActive={this.props.active}
+                    />
+                </div>
+                <div className="collectionCarouselView-next">
+                    <ContentFittingDocumentView {...this.props}
+                        onDoubleClick={ScriptCast(this.layoutDoc.onChildDoubleClick)}
+                        onClick={ScriptCast(this.layoutDoc.onChildClick)}
+                        renderDepth={this.props.renderDepth + 1}
+                        LayoutTemplate={this.props.ChildLayoutTemplate}
+                        LayoutTemplateString={this.props.ChildLayoutString}
+                        Document={this.childLayoutPairs[nextIndex].layout}
+                        DataDoc={this.childLayoutPairs[nextIndex].data}
+                        PanelHeight={this.props.PanelHeight}
+                        ScreenToLocalTransform={this.props.ScreenToLocalTransform}
+                        bringToFront={returnFalse}
+                        parentActive={this.props.active}
+                    />
+                </div>
                 <div className="collectionCarouselView-image" key="image">
                     <ContentFittingDocumentView {...this.props}
                         onDoubleClick={ScriptCast(this.layoutDoc.onChildDoubleClick)}
@@ -54,7 +85,7 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume
                         LayoutTemplateString={this.props.ChildLayoutString}
                         Document={this.childLayoutPairs[index].layout}
                         DataDoc={this.childLayoutPairs[index].data}
-                        PanelHeight={this.panelHeight}
+                        PanelHeight={this.props.PanelHeight}
                         ScreenToLocalTransform={this.props.ScreenToLocalTransform}
                         bringToFront={returnFalse}
                         parentActive={this.props.active}
-- 
cgit v1.2.3-70-g09d2


From 75254dbe3512e3507e34481e75bb60e7760a946f Mon Sep 17 00:00:00 2001
From: Melissa Zhang <mzhang19096@gmail.com>
Date: Mon, 18 May 2020 00:59:32 -0700
Subject: fit ContentFittingViews into main/prev/next panels

---
 src/client/views/collections/CollectionCarousel3DView.scss | 11 +++--------
 src/client/views/collections/CollectionCarousel3DView.tsx  | 11 +++++++++--
 2 files changed, 12 insertions(+), 10 deletions(-)

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

diff --git a/src/client/views/collections/CollectionCarousel3DView.scss b/src/client/views/collections/CollectionCarousel3DView.scss
index ee92cde4c..0f2d20242 100644
--- a/src/client/views/collections/CollectionCarousel3DView.scss
+++ b/src/client/views/collections/CollectionCarousel3DView.scss
@@ -3,10 +3,9 @@
     height: 100%;
 
     .collectionCarouselView-image {
-        overflow: hidden; //fix ContentFittingView size
         position: absolute;
         height: 100%;
-        width: 70%;
+        width: 60%;
         top: 0;
         left: 0;
         right: 0;
@@ -16,21 +15,17 @@
     }
 
     .collectionCarouselView-prev {
-        overflow: hidden;
         position: absolute;
         height: 50%;
-        width: 50%;
-        background-color: lightgrey;
+        width: 30%;
         left: 0;
         top: 25%;
     }
 
     .collectionCarouselView-next {
-        overflow: hidden;
         position: absolute;
         height: 50%;
-        width: 50%;
-        background-color: lightgrey;
+        width: 30%;
         right: 0;
         top: 25%;
     }
diff --git a/src/client/views/collections/CollectionCarousel3DView.tsx b/src/client/views/collections/CollectionCarousel3DView.tsx
index 4452ceb6b..c2ed39cc9 100644
--- a/src/client/views/collections/CollectionCarousel3DView.tsx
+++ b/src/client/views/collections/CollectionCarousel3DView.tsx
@@ -40,6 +40,10 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume
         this.layoutDoc._itemIndex = (NumCast(this.layoutDoc._itemIndex) - 1 + this.childLayoutPairs.length) % this.childLayoutPairs.length;
     }
 
+    mainPanelWidth = () => this.props.PanelWidth() * 0.6;
+    sidePanelWidth = () => this.props.PanelWidth() * 0.3;
+    sidePanelHeight = () => this.props.PanelHeight() * 0.5;
+
     @computed get content() {
         const index = NumCast(this.layoutDoc._itemIndex);
         const prevIndex = (index - 1 + this.childLayoutPairs.length) % this.childLayoutPairs.length;
@@ -55,7 +59,8 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume
                         LayoutTemplateString={this.props.ChildLayoutString}
                         Document={this.childLayoutPairs[prevIndex].layout}
                         DataDoc={this.childLayoutPairs[prevIndex].data}
-                        PanelHeight={this.props.PanelHeight}
+                        PanelWidth={this.sidePanelWidth}
+                        PanelHeight={this.sidePanelHeight}
                         ScreenToLocalTransform={this.props.ScreenToLocalTransform}
                         bringToFront={returnFalse}
                         parentActive={this.props.active}
@@ -70,7 +75,8 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume
                         LayoutTemplateString={this.props.ChildLayoutString}
                         Document={this.childLayoutPairs[nextIndex].layout}
                         DataDoc={this.childLayoutPairs[nextIndex].data}
-                        PanelHeight={this.props.PanelHeight}
+                        PanelWidth={this.sidePanelWidth}
+                        PanelHeight={this.sidePanelHeight}
                         ScreenToLocalTransform={this.props.ScreenToLocalTransform}
                         bringToFront={returnFalse}
                         parentActive={this.props.active}
@@ -85,6 +91,7 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume
                         LayoutTemplateString={this.props.ChildLayoutString}
                         Document={this.childLayoutPairs[index].layout}
                         DataDoc={this.childLayoutPairs[index].data}
+                        PanelWidth={this.mainPanelWidth}
                         PanelHeight={this.props.PanelHeight}
                         ScreenToLocalTransform={this.props.ScreenToLocalTransform}
                         bringToFront={returnFalse}
-- 
cgit v1.2.3-70-g09d2


From 8d4b00c3e2b62b1e83997f60e7df249e84766bdc Mon Sep 17 00:00:00 2001
From: Melissa Zhang <mzhang19096@gmail.com>
Date: Wed, 20 May 2020 00:44:27 -0700
Subject: basic image captioning

---
 .../collections/CollectionCarousel3DView.scss      |  7 +++++++
 .../views/collections/CollectionCarousel3DView.tsx | 23 ++++++++++++++++++----
 2 files changed, 26 insertions(+), 4 deletions(-)

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

diff --git a/src/client/views/collections/CollectionCarousel3DView.scss b/src/client/views/collections/CollectionCarousel3DView.scss
index 0f2d20242..c1260f899 100644
--- a/src/client/views/collections/CollectionCarousel3DView.scss
+++ b/src/client/views/collections/CollectionCarousel3DView.scss
@@ -2,6 +2,13 @@
     background: white;
     height: 100%;
 
+    .test-button {
+        position: absolute;
+        top: 0;
+        left: 0;
+        z-index: 999;
+    }
+
     .collectionCarouselView-image {
         position: absolute;
         height: 100%;
diff --git a/src/client/views/collections/CollectionCarousel3DView.tsx b/src/client/views/collections/CollectionCarousel3DView.tsx
index c2ed39cc9..d957b8749 100644
--- a/src/client/views/collections/CollectionCarousel3DView.tsx
+++ b/src/client/views/collections/CollectionCarousel3DView.tsx
@@ -13,6 +13,7 @@ import { Doc } from '../../../fields/Doc';
 import { ContextMenu } from '../ContextMenu';
 import { ObjectField } from '../../../fields/ObjectField';
 import { returnFalse } from '../../../Utils';
+import { ScriptField } from '../../../fields/ScriptField';
 
 type Carousel3DDocument = makeInterface<[typeof documentSchema, typeof collectionSchema]>;
 const Carousel3DDocument = makeInterface(documentSchema, collectionSchema);
@@ -40,6 +41,18 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume
         this.layoutDoc._itemIndex = (NumCast(this.layoutDoc._itemIndex) - 1 + this.childLayoutPairs.length) % this.childLayoutPairs.length;
     }
 
+    addCaption = (e: React.MouseEvent) => {
+        e.stopPropagation();
+        const index = NumCast(this.layoutDoc._itemIndex);
+        this.childLayoutPairs[index].layout._showCaption = "caption";
+    }
+
+    // @computed get gobackScript() {
+    //     return ScriptField.MakeScript("this.layoutDoc._itemIndex = index",
+    //         { this: Doc.name, heading: "string", checked: "string", containingTreeView: Doc.name, firstDoc: Doc.name },
+    //         { index: (NumCast(this.layoutDoc._itemIndex) - 1 + this.childLayoutPairs.length) % this.childLayoutPairs.length });
+    // }
+
     mainPanelWidth = () => this.props.PanelWidth() * 0.6;
     sidePanelWidth = () => this.props.PanelWidth() * 0.3;
     sidePanelHeight = () => this.props.PanelHeight() * 0.5;
@@ -50,10 +63,12 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume
         const nextIndex = (index + 1 + this.childLayoutPairs.length) % this.childLayoutPairs.length;
         return !(this.childLayoutPairs?.[index]?.layout instanceof Doc) ? (null) :
             <>
-                <div className="collectionCarouselView-prev">
+                <button className="test-button" onClick={this.addCaption}>add caption</button>
+                <div className="collectionCarouselView-prev" onClick={this.goback}>
                     <ContentFittingDocumentView {...this.props}
                         onDoubleClick={ScriptCast(this.layoutDoc.onChildDoubleClick)}
-                        onClick={ScriptCast(this.layoutDoc.onChildClick)}
+                        // onClick={ScriptCast(this.layoutDoc.onChildClick)}
+                        // onClick={this.gobackScript}
                         renderDepth={this.props.renderDepth + 1}
                         LayoutTemplate={this.props.ChildLayoutTemplate}
                         LayoutTemplateString={this.props.ChildLayoutString}
@@ -66,10 +81,10 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume
                         parentActive={this.props.active}
                     />
                 </div>
-                <div className="collectionCarouselView-next">
+                <div className="collectionCarouselView-next" onClick={this.advance}>
                     <ContentFittingDocumentView {...this.props}
                         onDoubleClick={ScriptCast(this.layoutDoc.onChildDoubleClick)}
-                        onClick={ScriptCast(this.layoutDoc.onChildClick)}
+                        // onClick={ScriptCast(this.layoutDoc.onChildClick)}
                         renderDepth={this.props.renderDepth + 1}
                         LayoutTemplate={this.props.ChildLayoutTemplate}
                         LayoutTemplateString={this.props.ChildLayoutString}
-- 
cgit v1.2.3-70-g09d2


From 210ce6f29e1674d4e2af893a9c5c995506e0c4b7 Mon Sep 17 00:00:00 2001
From: Melissa Zhang <mzhang19096@gmail.com>
Date: Wed, 20 May 2020 23:04:09 -0700
Subject: eliminated prev/next buttons, add caption by clicking on image

---
 src/client/views/.DS_Store                         | Bin 6148 -> 6148 bytes
 .../collections/CollectionCarousel3DView.scss      |   6 +++
 .../views/collections/CollectionCarousel3DView.tsx |  57 ++++++++-------------
 3 files changed, 26 insertions(+), 37 deletions(-)

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

diff --git a/src/client/views/.DS_Store b/src/client/views/.DS_Store
index 5008ddfcf..3717a2923 100644
Binary files a/src/client/views/.DS_Store and b/src/client/views/.DS_Store differ
diff --git a/src/client/views/collections/CollectionCarousel3DView.scss b/src/client/views/collections/CollectionCarousel3DView.scss
index 7ae9dd2c6..25d1df2f4 100644
--- a/src/client/views/collections/CollectionCarousel3DView.scss
+++ b/src/client/views/collections/CollectionCarousel3DView.scss
@@ -20,6 +20,8 @@
         bottom: 0;
         margin: auto;
         user-select: none;
+        transition: transform 0.5s;
+        transform-style: preserve-3d;
     }
 
     .collectionCarouselView-prev {
@@ -65,4 +67,8 @@
 .carouselView-back:hover,
 .carouselView-fwd:hover {
     background: lightgray;
+}
+
+.carouselView-fwd:hover~.collectionCarouselView-image {
+    transform: translateX(50px)
 }
\ No newline at end of file
diff --git a/src/client/views/collections/CollectionCarousel3DView.tsx b/src/client/views/collections/CollectionCarousel3DView.tsx
index d957b8749..fd1785641 100644
--- a/src/client/views/collections/CollectionCarousel3DView.tsx
+++ b/src/client/views/collections/CollectionCarousel3DView.tsx
@@ -1,4 +1,3 @@
-import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { observable, computed } from 'mobx';
 import { observer } from 'mobx-react';
 import * as React from 'react';
@@ -31,28 +30,14 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume
         }
     }
 
-    advance = (e: React.MouseEvent) => {
-        e.stopPropagation();
-        this.layoutDoc._itemIndex = (NumCast(this.layoutDoc._itemIndex) + 1) % this.childLayoutPairs.length;
-    }
-
-    goback = (e: React.MouseEvent) => {
-        e.stopPropagation();
-        this.layoutDoc._itemIndex = (NumCast(this.layoutDoc._itemIndex) - 1 + this.childLayoutPairs.length) % this.childLayoutPairs.length;
-    }
-
     addCaption = (e: React.MouseEvent) => {
         e.stopPropagation();
         const index = NumCast(this.layoutDoc._itemIndex);
-        this.childLayoutPairs[index].layout._showCaption = "caption";
+        if (this.childLayoutPairs[index].layout._showCaption !== "caption") {
+            this.childLayoutPairs[index].layout._showCaption = "caption";
+        }
     }
 
-    // @computed get gobackScript() {
-    //     return ScriptField.MakeScript("this.layoutDoc._itemIndex = index",
-    //         { this: Doc.name, heading: "string", checked: "string", containingTreeView: Doc.name, firstDoc: Doc.name },
-    //         { index: (NumCast(this.layoutDoc._itemIndex) - 1 + this.childLayoutPairs.length) % this.childLayoutPairs.length });
-    // }
-
     mainPanelWidth = () => this.props.PanelWidth() * 0.6;
     sidePanelWidth = () => this.props.PanelWidth() * 0.3;
     sidePanelHeight = () => this.props.PanelHeight() * 0.5;
@@ -63,12 +48,14 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume
         const nextIndex = (index + 1 + this.childLayoutPairs.length) % this.childLayoutPairs.length;
         return !(this.childLayoutPairs?.[index]?.layout instanceof Doc) ? (null) :
             <>
-                <button className="test-button" onClick={this.addCaption}>add caption</button>
-                <div className="collectionCarouselView-prev" onClick={this.goback}>
+                <div className="collectionCarouselView-prev">
                     <ContentFittingDocumentView {...this.props}
                         onDoubleClick={ScriptCast(this.layoutDoc.onChildDoubleClick)}
-                        // onClick={ScriptCast(this.layoutDoc.onChildClick)}
-                        // onClick={this.gobackScript}
+                        onClick={ScriptField.MakeScript(
+                            "collectionLayoutDoc._itemIndex = collectionLayoutDoc[fieldKey].indexOf(self)",
+                            { fieldKey: String.name, collectionLayoutDoc: Doc.name },
+                            { fieldKey: this.props.fieldKey, collectionLayoutDoc: this.layoutDoc }
+                        )}
                         renderDepth={this.props.renderDepth + 1}
                         LayoutTemplate={this.props.ChildLayoutTemplate}
                         LayoutTemplateString={this.props.ChildLayoutString}
@@ -81,10 +68,14 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume
                         parentActive={this.props.active}
                     />
                 </div>
-                <div className="collectionCarouselView-next" onClick={this.advance}>
+                <div className="collectionCarouselView-next">
                     <ContentFittingDocumentView {...this.props}
                         onDoubleClick={ScriptCast(this.layoutDoc.onChildDoubleClick)}
-                        // onClick={ScriptCast(this.layoutDoc.onChildClick)}
+                        onClick={ScriptField.MakeScript(
+                            "collectionLayoutDoc._itemIndex = collectionLayoutDoc[fieldKey].indexOf(self)",
+                            { fieldKey: String.name, collectionLayoutDoc: Doc.name },
+                            { fieldKey: this.props.fieldKey, collectionLayoutDoc: this.layoutDoc }
+                        )}
                         renderDepth={this.props.renderDepth + 1}
                         LayoutTemplate={this.props.ChildLayoutTemplate}
                         LayoutTemplateString={this.props.ChildLayoutString}
@@ -100,7 +91,11 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume
                 <div className="collectionCarouselView-image" key="image">
                     <ContentFittingDocumentView {...this.props}
                         onDoubleClick={ScriptCast(this.layoutDoc.onChildDoubleClick)}
-                        onClick={ScriptCast(this.layoutDoc.onChildClick)}
+                        onClick={ScriptField.MakeScript(
+                            "child._showCaption = 'caption'",
+                            { child: Doc.name },
+                            { child: this.childLayoutPairs[index].layout }
+                        )}
                         renderDepth={this.props.renderDepth + 1}
                         LayoutTemplate={this.props.ChildLayoutTemplate}
                         LayoutTemplateString={this.props.ChildLayoutString}
@@ -115,17 +110,6 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume
                 </div>
             </>;
     }
-    @computed get buttons() {
-        return <>
-            <div key="back" className="carouselView-back" style={{ background: `${StrCast(this.props.Document.backgroundColor)}` }} onClick={this.goback}>
-                <FontAwesomeIcon icon={"caret-left"} size={"2x"} />
-            </div>
-            <div key="fwd" className="carouselView-fwd" style={{ background: `${StrCast(this.props.Document.backgroundColor)}` }} onClick={this.advance}>
-                <FontAwesomeIcon icon={"caret-right"} size={"2x"} />
-            </div>
-        </>;
-    }
-
 
     onContextMenu = (e: React.MouseEvent): void => {
         // need to test if propagation has stopped because GoldenLayout forces a parallel react hierarchy to be created for its top-level layout
@@ -164,7 +148,6 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume
     render() {
         return <div className="collectionCarouselView-outer" onClick={this.onClick} onPointerDown={this.onPointerDown} ref={this.createDashEventsTarget} onContextMenu={this.onContextMenu}>
             {this.content}
-            {this.props.Document._chromeStatus !== "replaced" ? this.buttons : (null)}
         </div>;
     }
 }
\ No newline at end of file
-- 
cgit v1.2.3-70-g09d2


From 07566108db7da0a8e30dcb4c6b884482b57394a1 Mon Sep 17 00:00:00 2001
From: Melissa Zhang <mzhang19096@gmail.com>
Date: Wed, 20 May 2020 23:15:06 -0700
Subject: code clean up

---
 .../collections/CollectionCarousel3DView.scss      | 37 ----------------------
 .../views/collections/CollectionCarousel3DView.tsx | 25 +++++----------
 2 files changed, 8 insertions(+), 54 deletions(-)

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

diff --git a/src/client/views/collections/CollectionCarousel3DView.scss b/src/client/views/collections/CollectionCarousel3DView.scss
index 25d1df2f4..7da007ef3 100644
--- a/src/client/views/collections/CollectionCarousel3DView.scss
+++ b/src/client/views/collections/CollectionCarousel3DView.scss
@@ -3,13 +3,6 @@
     height: 100%;
     perspective: 30em;
 
-    .test-button {
-        position: absolute;
-        top: 0;
-        left: 0;
-        z-index: 999;
-    }
-
     .collectionCarouselView-image {
         position: absolute;
         height: 100%;
@@ -41,34 +34,4 @@
         top: 25%;
         transform: rotateY(20deg)
     }
-}
-
-.carouselView-back,
-.carouselView-fwd {
-    position: absolute;
-    display: flex;
-    top: 50%;
-    width: 30;
-    height: 30;
-    align-items: center;
-    border-radius: 5px;
-    justify-content: center;
-    background: rgba(255, 255, 255, 0.46);
-}
-
-.carouselView-fwd {
-    right: 0;
-}
-
-.carouselView-back {
-    left: 0;
-}
-
-.carouselView-back:hover,
-.carouselView-fwd:hover {
-    background: lightgray;
-}
-
-.carouselView-fwd:hover~.collectionCarouselView-image {
-    transform: translateX(50px)
 }
\ No newline at end of file
diff --git a/src/client/views/collections/CollectionCarousel3DView.tsx b/src/client/views/collections/CollectionCarousel3DView.tsx
index fd1785641..649ca4eba 100644
--- a/src/client/views/collections/CollectionCarousel3DView.tsx
+++ b/src/client/views/collections/CollectionCarousel3DView.tsx
@@ -30,18 +30,17 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume
         }
     }
 
-    addCaption = (e: React.MouseEvent) => {
-        e.stopPropagation();
-        const index = NumCast(this.layoutDoc._itemIndex);
-        if (this.childLayoutPairs[index].layout._showCaption !== "caption") {
-            this.childLayoutPairs[index].layout._showCaption = "caption";
-        }
+    @computed get changeIndexScript() {
+        return ScriptField.MakeScript(
+            "collectionLayoutDoc._itemIndex = collectionLayoutDoc[fieldKey].indexOf(self)",
+            { fieldKey: String.name, collectionLayoutDoc: Doc.name },
+            { fieldKey: this.props.fieldKey, collectionLayoutDoc: this.layoutDoc }
+        );
     }
 
     mainPanelWidth = () => this.props.PanelWidth() * 0.6;
     sidePanelWidth = () => this.props.PanelWidth() * 0.3;
     sidePanelHeight = () => this.props.PanelHeight() * 0.5;
-
     @computed get content() {
         const index = NumCast(this.layoutDoc._itemIndex);
         const prevIndex = (index - 1 + this.childLayoutPairs.length) % this.childLayoutPairs.length;
@@ -51,11 +50,7 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume
                 <div className="collectionCarouselView-prev">
                     <ContentFittingDocumentView {...this.props}
                         onDoubleClick={ScriptCast(this.layoutDoc.onChildDoubleClick)}
-                        onClick={ScriptField.MakeScript(
-                            "collectionLayoutDoc._itemIndex = collectionLayoutDoc[fieldKey].indexOf(self)",
-                            { fieldKey: String.name, collectionLayoutDoc: Doc.name },
-                            { fieldKey: this.props.fieldKey, collectionLayoutDoc: this.layoutDoc }
-                        )}
+                        onClick={this.changeIndexScript}
                         renderDepth={this.props.renderDepth + 1}
                         LayoutTemplate={this.props.ChildLayoutTemplate}
                         LayoutTemplateString={this.props.ChildLayoutString}
@@ -71,11 +66,7 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume
                 <div className="collectionCarouselView-next">
                     <ContentFittingDocumentView {...this.props}
                         onDoubleClick={ScriptCast(this.layoutDoc.onChildDoubleClick)}
-                        onClick={ScriptField.MakeScript(
-                            "collectionLayoutDoc._itemIndex = collectionLayoutDoc[fieldKey].indexOf(self)",
-                            { fieldKey: String.name, collectionLayoutDoc: Doc.name },
-                            { fieldKey: this.props.fieldKey, collectionLayoutDoc: this.layoutDoc }
-                        )}
+                        onClick={this.changeIndexScript}
                         renderDepth={this.props.renderDepth + 1}
                         LayoutTemplate={this.props.ChildLayoutTemplate}
                         LayoutTemplateString={this.props.ChildLayoutString}
-- 
cgit v1.2.3-70-g09d2


From da705df20b9b2d44c6aa76050bb59a0bb669f0db Mon Sep 17 00:00:00 2001
From: Melissa Zhang <mzhang19096@gmail.com>
Date: Fri, 22 May 2020 17:08:16 -0700
Subject: styling changes

---
 package-lock.json                                  | 44 ++++++++++++++++------
 .../collections/CollectionCarousel3DView.scss      | 10 ++---
 .../views/collections/CollectionCarousel3DView.tsx | 43 ++++++++++-----------
 3 files changed, 59 insertions(+), 38 deletions(-)

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

diff --git a/package-lock.json b/package-lock.json
index 6532f27ec..23d9fc590 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -2702,7 +2702,8 @@
                         },
                         "ansi-regex": {
                             "version": "2.1.1",
-                            "bundled": true
+                            "bundled": true,
+                            "optional": true
                         },
                         "aproba": {
                             "version": "1.2.0",
@@ -2720,11 +2721,13 @@
                         },
                         "balanced-match": {
                             "version": "1.0.0",
-                            "bundled": true
+                            "bundled": true,
+                            "optional": true
                         },
                         "brace-expansion": {
                             "version": "1.1.11",
                             "bundled": true,
+                            "optional": true,
                             "requires": {
                                 "balanced-match": "^1.0.0",
                                 "concat-map": "0.0.1"
@@ -2737,15 +2740,18 @@
                         },
                         "code-point-at": {
                             "version": "1.1.0",
-                            "bundled": true
+                            "bundled": true,
+                            "optional": true
                         },
                         "concat-map": {
                             "version": "0.0.1",
-                            "bundled": true
+                            "bundled": true,
+                            "optional": true
                         },
                         "console-control-strings": {
                             "version": "1.1.0",
-                            "bundled": true
+                            "bundled": true,
+                            "optional": true
                         },
                         "core-util-is": {
                             "version": "1.0.2",
@@ -2848,7 +2854,8 @@
                         },
                         "inherits": {
                             "version": "2.0.4",
-                            "bundled": true
+                            "bundled": true,
+                            "optional": true
                         },
                         "ini": {
                             "version": "1.3.5",
@@ -2858,6 +2865,7 @@
                         "is-fullwidth-code-point": {
                             "version": "1.0.0",
                             "bundled": true,
+                            "optional": true,
                             "requires": {
                                 "number-is-nan": "^1.0.0"
                             }
@@ -2870,17 +2878,20 @@
                         "minimatch": {
                             "version": "3.0.4",
                             "bundled": true,
+                            "optional": true,
                             "requires": {
                                 "brace-expansion": "^1.1.7"
                             }
                         },
                         "minimist": {
                             "version": "1.2.5",
-                            "bundled": true
+                            "bundled": true,
+                            "optional": true
                         },
                         "minipass": {
                             "version": "2.9.0",
                             "bundled": true,
+                            "optional": true,
                             "requires": {
                                 "safe-buffer": "^5.1.2",
                                 "yallist": "^3.0.0"
@@ -2897,6 +2908,7 @@
                         "mkdirp": {
                             "version": "0.5.3",
                             "bundled": true,
+                            "optional": true,
                             "requires": {
                                 "minimist": "^1.2.5"
                             }
@@ -2952,7 +2964,8 @@
                         },
                         "npm-normalize-package-bin": {
                             "version": "1.0.1",
-                            "bundled": true
+                            "bundled": true,
+                            "optional": true
                         },
                         "npm-packlist": {
                             "version": "1.4.8",
@@ -2977,7 +2990,8 @@
                         },
                         "number-is-nan": {
                             "version": "1.0.1",
-                            "bundled": true
+                            "bundled": true,
+                            "optional": true
                         },
                         "object-assign": {
                             "version": "4.1.1",
@@ -2987,6 +3001,7 @@
                         "once": {
                             "version": "1.4.0",
                             "bundled": true,
+                            "optional": true,
                             "requires": {
                                 "wrappy": "1"
                             }
@@ -3055,7 +3070,8 @@
                         },
                         "safe-buffer": {
                             "version": "5.1.2",
-                            "bundled": true
+                            "bundled": true,
+                            "optional": true
                         },
                         "safer-buffer": {
                             "version": "2.1.2",
@@ -3085,6 +3101,7 @@
                         "string-width": {
                             "version": "1.0.2",
                             "bundled": true,
+                            "optional": true,
                             "requires": {
                                 "code-point-at": "^1.0.0",
                                 "is-fullwidth-code-point": "^1.0.0",
@@ -3102,6 +3119,7 @@
                         "strip-ansi": {
                             "version": "3.0.1",
                             "bundled": true,
+                            "optional": true,
                             "requires": {
                                 "ansi-regex": "^2.0.0"
                             }
@@ -3140,11 +3158,13 @@
                         },
                         "wrappy": {
                             "version": "1.0.2",
-                            "bundled": true
+                            "bundled": true,
+                            "optional": true
                         },
                         "yallist": {
                             "version": "3.1.1",
-                            "bundled": true
+                            "bundled": true,
+                            "optional": true
                         }
                     }
                 }
diff --git a/src/client/views/collections/CollectionCarousel3DView.scss b/src/client/views/collections/CollectionCarousel3DView.scss
index 7da007ef3..df64d8cbe 100644
--- a/src/client/views/collections/CollectionCarousel3DView.scss
+++ b/src/client/views/collections/CollectionCarousel3DView.scss
@@ -1,11 +1,11 @@
 .collectionCarouselView-outer {
     background: white;
     height: 100%;
-    perspective: 30em;
+    perspective: 40em;
 
-    .collectionCarouselView-image {
+    .collectionCarouselView-center {
         position: absolute;
-        height: 100%;
+        height: 80%;
         width: 50%;
         top: 0;
         left: 0;
@@ -23,7 +23,7 @@
         width: 25%;
         left: 0;
         top: 25%;
-        transform: rotateY(-20deg)
+        transform: rotateY(-20deg);
     }
 
     .collectionCarouselView-next {
@@ -32,6 +32,6 @@
         width: 25%;
         right: 0;
         top: 25%;
-        transform: rotateY(20deg)
+        transform: rotateY(20deg);
     }
 }
\ No newline at end of file
diff --git a/src/client/views/collections/CollectionCarousel3DView.tsx b/src/client/views/collections/CollectionCarousel3DView.tsx
index 649ca4eba..0e704a1a0 100644
--- a/src/client/views/collections/CollectionCarousel3DView.tsx
+++ b/src/client/views/collections/CollectionCarousel3DView.tsx
@@ -38,8 +38,9 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume
         );
     }
 
-    mainPanelWidth = () => this.props.PanelWidth() * 0.6;
-    sidePanelWidth = () => this.props.PanelWidth() * 0.3;
+    mainPanelWidth = () => this.props.PanelWidth() * 0.5;
+    mainPanelHeight = () => this.props.PanelHeight() * 0.8;
+    sidePanelWidth = () => this.props.PanelWidth() * 0.25;
     sidePanelHeight = () => this.props.PanelHeight() * 0.5;
     @computed get content() {
         const index = NumCast(this.layoutDoc._itemIndex);
@@ -47,31 +48,35 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume
         const nextIndex = (index + 1 + this.childLayoutPairs.length) % this.childLayoutPairs.length;
         return !(this.childLayoutPairs?.[index]?.layout instanceof Doc) ? (null) :
             <>
-                <div className="collectionCarouselView-prev">
+                <div className="collectionCarouselView-center">
                     <ContentFittingDocumentView {...this.props}
                         onDoubleClick={ScriptCast(this.layoutDoc.onChildDoubleClick)}
-                        onClick={this.changeIndexScript}
+                        onClick={ScriptField.MakeScript(
+                            "child._showCaption = 'caption'",
+                            { child: Doc.name },
+                            { child: this.childLayoutPairs[index].layout }
+                        )}
                         renderDepth={this.props.renderDepth + 1}
                         LayoutTemplate={this.props.ChildLayoutTemplate}
                         LayoutTemplateString={this.props.ChildLayoutString}
-                        Document={this.childLayoutPairs[prevIndex].layout}
-                        DataDoc={this.childLayoutPairs[prevIndex].data}
-                        PanelWidth={this.sidePanelWidth}
-                        PanelHeight={this.sidePanelHeight}
+                        Document={this.childLayoutPairs[index].layout}
+                        DataDoc={this.childLayoutPairs[index].data}
+                        PanelWidth={this.mainPanelWidth}
+                        PanelHeight={this.mainPanelHeight}
                         ScreenToLocalTransform={this.props.ScreenToLocalTransform}
                         bringToFront={returnFalse}
                         parentActive={this.props.active}
                     />
                 </div>
-                <div className="collectionCarouselView-next">
+                <div className="collectionCarouselView-prev">
                     <ContentFittingDocumentView {...this.props}
                         onDoubleClick={ScriptCast(this.layoutDoc.onChildDoubleClick)}
                         onClick={this.changeIndexScript}
                         renderDepth={this.props.renderDepth + 1}
                         LayoutTemplate={this.props.ChildLayoutTemplate}
                         LayoutTemplateString={this.props.ChildLayoutString}
-                        Document={this.childLayoutPairs[nextIndex].layout}
-                        DataDoc={this.childLayoutPairs[nextIndex].data}
+                        Document={this.childLayoutPairs[prevIndex].layout}
+                        DataDoc={this.childLayoutPairs[prevIndex].data}
                         PanelWidth={this.sidePanelWidth}
                         PanelHeight={this.sidePanelHeight}
                         ScreenToLocalTransform={this.props.ScreenToLocalTransform}
@@ -79,21 +84,17 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume
                         parentActive={this.props.active}
                     />
                 </div>
-                <div className="collectionCarouselView-image" key="image">
+                <div className="collectionCarouselView-next">
                     <ContentFittingDocumentView {...this.props}
                         onDoubleClick={ScriptCast(this.layoutDoc.onChildDoubleClick)}
-                        onClick={ScriptField.MakeScript(
-                            "child._showCaption = 'caption'",
-                            { child: Doc.name },
-                            { child: this.childLayoutPairs[index].layout }
-                        )}
+                        onClick={this.changeIndexScript}
                         renderDepth={this.props.renderDepth + 1}
                         LayoutTemplate={this.props.ChildLayoutTemplate}
                         LayoutTemplateString={this.props.ChildLayoutString}
-                        Document={this.childLayoutPairs[index].layout}
-                        DataDoc={this.childLayoutPairs[index].data}
-                        PanelWidth={this.mainPanelWidth}
-                        PanelHeight={this.props.PanelHeight}
+                        Document={this.childLayoutPairs[nextIndex].layout}
+                        DataDoc={this.childLayoutPairs[nextIndex].data}
+                        PanelWidth={this.sidePanelWidth}
+                        PanelHeight={this.sidePanelHeight}
                         ScreenToLocalTransform={this.props.ScreenToLocalTransform}
                         bringToFront={returnFalse}
                         parentActive={this.props.active}
-- 
cgit v1.2.3-70-g09d2


From f398609a9819e5bb370063d5106b8484093393c9 Mon Sep 17 00:00:00 2001
From: Melissa Zhang <mzhang19096@gmail.com>
Date: Sat, 23 May 2020 23:57:10 -0700
Subject: reorganized & condensed render function

---
 .../views/collections/CollectionCarousel3DView.tsx | 87 +++++++++-------------
 1 file changed, 37 insertions(+), 50 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 0e704a1a0..f95645a6c 100644
--- a/src/client/views/collections/CollectionCarousel3DView.tsx
+++ b/src/client/views/collections/CollectionCarousel3DView.tsx
@@ -43,62 +43,49 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume
     sidePanelWidth = () => this.props.PanelWidth() * 0.25;
     sidePanelHeight = () => this.props.PanelHeight() * 0.5;
     @computed get content() {
-        const index = NumCast(this.layoutDoc._itemIndex);
-        const prevIndex = (index - 1 + this.childLayoutPairs.length) % this.childLayoutPairs.length;
-        const nextIndex = (index + 1 + this.childLayoutPairs.length) % this.childLayoutPairs.length;
-        return !(this.childLayoutPairs?.[index]?.layout instanceof Doc) ? (null) :
+        const centerIndex = NumCast(this.layoutDoc._itemIndex);
+        const prevIndex = (centerIndex - 1 + this.childLayoutPairs.length) % this.childLayoutPairs.length;
+        const nextIndex = (centerIndex + 1 + this.childLayoutPairs.length) % this.childLayoutPairs.length;
+
+        const displayDoc = (index: number, onClickAction: ScriptField | undefined, width: () => number, height: () => number) => {
+            return <ContentFittingDocumentView {...this.props}
+                onDoubleClick={ScriptCast(this.layoutDoc.onChildDoubleClick)}
+                onClick={onClickAction}
+                renderDepth={this.props.renderDepth + 1}
+                LayoutTemplate={this.props.ChildLayoutTemplate}
+                LayoutTemplateString={this.props.ChildLayoutString}
+                Document={this.childLayoutPairs[index].layout}
+                DataDoc={this.childLayoutPairs[index].data}
+                PanelWidth={width}
+                PanelHeight={height}
+                ScreenToLocalTransform={this.props.ScreenToLocalTransform}
+                bringToFront={returnFalse}
+                parentActive={this.props.active}
+            />;
+        };
+
+        const showCaptionScript = ScriptField.MakeScript(
+            "child._showCaption = 'caption'",
+            { child: Doc.name },
+            { child: this.childLayoutPairs[centerIndex].layout }
+        );
+
+        const changeIndexScript = ScriptField.MakeScript(
+            "collectionLayoutDoc._itemIndex = collectionLayoutDoc[fieldKey].indexOf(self)",
+            { fieldKey: String.name, collectionLayoutDoc: Doc.name },
+            { fieldKey: this.props.fieldKey, collectionLayoutDoc: this.layoutDoc }
+        );
+
+        return !(this.childLayoutPairs?.[centerIndex]?.layout instanceof Doc) ? (null) :
             <>
                 <div className="collectionCarouselView-center">
-                    <ContentFittingDocumentView {...this.props}
-                        onDoubleClick={ScriptCast(this.layoutDoc.onChildDoubleClick)}
-                        onClick={ScriptField.MakeScript(
-                            "child._showCaption = 'caption'",
-                            { child: Doc.name },
-                            { child: this.childLayoutPairs[index].layout }
-                        )}
-                        renderDepth={this.props.renderDepth + 1}
-                        LayoutTemplate={this.props.ChildLayoutTemplate}
-                        LayoutTemplateString={this.props.ChildLayoutString}
-                        Document={this.childLayoutPairs[index].layout}
-                        DataDoc={this.childLayoutPairs[index].data}
-                        PanelWidth={this.mainPanelWidth}
-                        PanelHeight={this.mainPanelHeight}
-                        ScreenToLocalTransform={this.props.ScreenToLocalTransform}
-                        bringToFront={returnFalse}
-                        parentActive={this.props.active}
-                    />
+                    {displayDoc(centerIndex, showCaptionScript, this.mainPanelWidth, this.mainPanelHeight)}
                 </div>
                 <div className="collectionCarouselView-prev">
-                    <ContentFittingDocumentView {...this.props}
-                        onDoubleClick={ScriptCast(this.layoutDoc.onChildDoubleClick)}
-                        onClick={this.changeIndexScript}
-                        renderDepth={this.props.renderDepth + 1}
-                        LayoutTemplate={this.props.ChildLayoutTemplate}
-                        LayoutTemplateString={this.props.ChildLayoutString}
-                        Document={this.childLayoutPairs[prevIndex].layout}
-                        DataDoc={this.childLayoutPairs[prevIndex].data}
-                        PanelWidth={this.sidePanelWidth}
-                        PanelHeight={this.sidePanelHeight}
-                        ScreenToLocalTransform={this.props.ScreenToLocalTransform}
-                        bringToFront={returnFalse}
-                        parentActive={this.props.active}
-                    />
+                    {displayDoc(prevIndex, changeIndexScript, this.sidePanelWidth, this.sidePanelHeight)}
                 </div>
                 <div className="collectionCarouselView-next">
-                    <ContentFittingDocumentView {...this.props}
-                        onDoubleClick={ScriptCast(this.layoutDoc.onChildDoubleClick)}
-                        onClick={this.changeIndexScript}
-                        renderDepth={this.props.renderDepth + 1}
-                        LayoutTemplate={this.props.ChildLayoutTemplate}
-                        LayoutTemplateString={this.props.ChildLayoutString}
-                        Document={this.childLayoutPairs[nextIndex].layout}
-                        DataDoc={this.childLayoutPairs[nextIndex].data}
-                        PanelWidth={this.sidePanelWidth}
-                        PanelHeight={this.sidePanelHeight}
-                        ScreenToLocalTransform={this.props.ScreenToLocalTransform}
-                        bringToFront={returnFalse}
-                        parentActive={this.props.active}
-                    />
+                    {displayDoc(nextIndex, changeIndexScript, this.sidePanelWidth, this.sidePanelHeight)}
                 </div>
             </>;
     }
-- 
cgit v1.2.3-70-g09d2


From 481ce09aa523de3792295e766c1bc4c80982bf53 Mon Sep 17 00:00:00 2001
From: Melissa Zhang <mzhang19096@gmail.com>
Date: Tue, 26 May 2020 23:31:44 -0700
Subject: re-structured 3D carousel

---
 .../collections/CollectionCarousel3DView.scss      |  46 +++------
 .../views/collections/CollectionCarousel3DView.tsx | 106 +++++++++++++--------
 2 files changed, 80 insertions(+), 72 deletions(-)

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

diff --git a/src/client/views/collections/CollectionCarousel3DView.scss b/src/client/views/collections/CollectionCarousel3DView.scss
index df64d8cbe..d1504dd12 100644
--- a/src/client/views/collections/CollectionCarousel3DView.scss
+++ b/src/client/views/collections/CollectionCarousel3DView.scss
@@ -1,37 +1,21 @@
 .collectionCarouselView-outer {
-    background: white;
     height: 100%;
-    perspective: 40em;
+    position: relative;
+    background-color: white;
+}
 
-    .collectionCarouselView-center {
-        position: absolute;
-        height: 80%;
-        width: 50%;
-        top: 0;
-        left: 0;
-        right: 0;
-        bottom: 0;
-        margin: auto;
-        user-select: none;
-        transition: transform 0.5s;
-        transform-style: preserve-3d;
-    }
-
-    .collectionCarouselView-prev {
-        position: absolute;
-        height: 50%;
-        width: 25%;
-        left: 0;
-        top: 25%;
-        transform: rotateY(-20deg);
-    }
+.carousel-wrapper {
+    display: flex;
+    position: absolute;
+    top: 10px;
+    align-items: center;
+    transition: transform 0.75s cubic-bezier(0.455, 0.03, 0.515, 0.955);
 
-    .collectionCarouselView-next {
-        position: absolute;
-        height: 50%;
-        width: 25%;
-        right: 0;
-        top: 25%;
-        transform: rotateY(20deg);
+    .collectionCarouselView-item {
+        flex: 1;
+        transition: opacity 0.5s linear;
+        transition: transform 0.5s linear;
+        transition: height 0.5s linear;
+        transition: width 0.5s linear;
     }
 }
\ No newline at end of file
diff --git a/src/client/views/collections/CollectionCarousel3DView.tsx b/src/client/views/collections/CollectionCarousel3DView.tsx
index f95645a6c..9665e23ff 100644
--- a/src/client/views/collections/CollectionCarousel3DView.tsx
+++ b/src/client/views/collections/CollectionCarousel3DView.tsx
@@ -13,6 +13,7 @@ import { ContextMenu } from '../ContextMenu';
 import { ObjectField } from '../../../fields/ObjectField';
 import { returnFalse } from '../../../Utils';
 import { ScriptField } from '../../../fields/ScriptField';
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 
 type Carousel3DDocument = makeInterface<[typeof documentSchema, typeof collectionSchema]>;
 const Carousel3DDocument = makeInterface(documentSchema, collectionSchema);
@@ -30,32 +31,36 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume
         }
     }
 
-    @computed get changeIndexScript() {
-        return ScriptField.MakeScript(
-            "collectionLayoutDoc._itemIndex = collectionLayoutDoc[fieldKey].indexOf(self)",
-            { fieldKey: String.name, collectionLayoutDoc: Doc.name },
-            { fieldKey: this.props.fieldKey, collectionLayoutDoc: this.layoutDoc }
-        );
-    }
-
     mainPanelWidth = () => this.props.PanelWidth() * 0.5;
-    mainPanelHeight = () => this.props.PanelHeight() * 0.8;
+    mainPanelHeight = () => this.props.PanelHeight() * 0.9;
     sidePanelWidth = () => this.props.PanelWidth() * 0.25;
     sidePanelHeight = () => this.props.PanelHeight() * 0.5;
+
     @computed get content() {
-        const centerIndex = NumCast(this.layoutDoc._itemIndex);
-        const prevIndex = (centerIndex - 1 + this.childLayoutPairs.length) % this.childLayoutPairs.length;
-        const nextIndex = (centerIndex + 1 + this.childLayoutPairs.length) % this.childLayoutPairs.length;
+        const currentIndex = NumCast(this.layoutDoc._itemIndex);
+
+
+        const displayDoc = (childPair: { layout: Doc, data: Doc }, width: () => number, height: () => number) => {
+            const showCaptionScript = ScriptField.MakeScript(
+                "child._showCaption = 'caption'",
+                { child: Doc.name },
+                { child: childPair.layout }
+            );
+
+            // const changeIndexScript = ScriptField.MakeScript(
+            //     "collectionLayoutDoc._itemIndex = collectionLayoutDoc[fieldKey].indexOf(self)",
+            //     { fieldKey: String.name, collectionLayoutDoc: Doc.name },
+            //     { fieldKey: this.props.fieldKey, collectionLayoutDoc: this.layoutDoc }
+            // );
 
-        const displayDoc = (index: number, onClickAction: ScriptField | undefined, width: () => number, height: () => number) => {
             return <ContentFittingDocumentView {...this.props}
                 onDoubleClick={ScriptCast(this.layoutDoc.onChildDoubleClick)}
-                onClick={onClickAction}
+                onClick={showCaptionScript}
                 renderDepth={this.props.renderDepth + 1}
                 LayoutTemplate={this.props.ChildLayoutTemplate}
                 LayoutTemplateString={this.props.ChildLayoutString}
-                Document={this.childLayoutPairs[index].layout}
-                DataDoc={this.childLayoutPairs[index].data}
+                Document={childPair.layout}
+                DataDoc={childPair.data}
                 PanelWidth={width}
                 PanelHeight={height}
                 ScreenToLocalTransform={this.props.ScreenToLocalTransform}
@@ -64,30 +69,31 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume
             />;
         };
 
-        const showCaptionScript = ScriptField.MakeScript(
-            "child._showCaption = 'caption'",
-            { child: Doc.name },
-            { child: this.childLayoutPairs[centerIndex].layout }
-        );
-
-        const changeIndexScript = ScriptField.MakeScript(
-            "collectionLayoutDoc._itemIndex = collectionLayoutDoc[fieldKey].indexOf(self)",
-            { fieldKey: String.name, collectionLayoutDoc: Doc.name },
-            { fieldKey: this.props.fieldKey, collectionLayoutDoc: this.layoutDoc }
-        );
-
-        return !(this.childLayoutPairs?.[centerIndex]?.layout instanceof Doc) ? (null) :
-            <>
-                <div className="collectionCarouselView-center">
-                    {displayDoc(centerIndex, showCaptionScript, this.mainPanelWidth, this.mainPanelHeight)}
-                </div>
-                <div className="collectionCarouselView-prev">
-                    {displayDoc(prevIndex, changeIndexScript, this.sidePanelWidth, this.sidePanelHeight)}
-                </div>
-                <div className="collectionCarouselView-next">
-                    {displayDoc(nextIndex, changeIndexScript, this.sidePanelWidth, this.sidePanelHeight)}
-                </div>
-            </>;
+        return (
+            this.childLayoutPairs.map((child, index) => {
+                if (index === currentIndex) {
+                    return (
+                        <div key={index} className={`collectionCarouselView-item ${index}`}
+                            style={{ opacity: '1' }}>
+                            {displayDoc(child, this.mainPanelWidth, this.mainPanelHeight)}
+                        </div>);
+                } else {
+                    return (
+                        <div key={index} className={`collectionCarouselView-item ${index}`}
+                            style={{ opacity: '0.5', userSelect: 'none' }}>
+                            {displayDoc(child, this.sidePanelWidth, this.sidePanelHeight)}
+                        </div>);
+                }
+            }));
+    }
+
+    advance = (e: React.MouseEvent) => {
+        e.stopPropagation();
+        this.layoutDoc._itemIndex = (NumCast(this.layoutDoc._itemIndex) + 1) % this.childLayoutPairs.length;
+    }
+    goback = (e: React.MouseEvent) => {
+        e.stopPropagation();
+        this.layoutDoc._itemIndex = (NumCast(this.layoutDoc._itemIndex) - 1 + this.childLayoutPairs.length) % this.childLayoutPairs.length;
     }
 
     onContextMenu = (e: React.MouseEvent): void => {
@@ -124,9 +130,27 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume
         }
     }
 
+    @computed get buttons() {
+        return <>
+            <div key="back" className="carouselView-back" style={{ background: `${StrCast(this.props.Document.backgroundColor)}` }} onClick={this.goback}>
+                <FontAwesomeIcon icon={"caret-left"} size={"2x"} />
+            </div>
+            <div key="fwd" className="carouselView-fwd" style={{ background: `${StrCast(this.props.Document.backgroundColor)}` }} onClick={this.advance}>
+                <FontAwesomeIcon icon={"caret-right"} size={"2x"} />
+            </div>
+        </>;
+    }
+
     render() {
+        const index = NumCast(this.layoutDoc._itemIndex);
+        const offset = (index - 1) * (this.mainPanelWidth() - this.sidePanelWidth()) / this.childLayoutPairs.length;
+        const translateX = (1 - index) / this.childLayoutPairs.length * 100;
+
         return <div className="collectionCarouselView-outer" onClick={this.onClick} onPointerDown={this.onPointerDown} ref={this.createDashEventsTarget} onContextMenu={this.onContextMenu}>
-            {this.content}
+            <div className="carousel-wrapper" style={{ transform: `translateX(calc(${translateX}% + ${offset}px)` }}>
+                {this.content}
+            </div>
+            {this.props.Document._chromeStatus !== "replaced" ? this.buttons : (null)}
         </div>;
     }
 }
\ No newline at end of file
-- 
cgit v1.2.3-70-g09d2


From 04e285a5b65d0b66c0792fafcd97d7f80e05b7f4 Mon Sep 17 00:00:00 2001
From: Melissa Zhang <mzhang19096@gmail.com>
Date: Tue, 26 May 2020 23:33:31 -0700
Subject: added dots bar for navigating through carousel

---
 .../collections/CollectionCarousel3DView.scss      | 23 ++++++++++++++++++++++
 .../views/collections/CollectionCarousel3DView.tsx | 10 ++++++++++
 2 files changed, 33 insertions(+)

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

diff --git a/src/client/views/collections/CollectionCarousel3DView.scss b/src/client/views/collections/CollectionCarousel3DView.scss
index d1504dd12..47ee8ef53 100644
--- a/src/client/views/collections/CollectionCarousel3DView.scss
+++ b/src/client/views/collections/CollectionCarousel3DView.scss
@@ -18,4 +18,27 @@
         transition: height 0.5s linear;
         transition: width 0.5s linear;
     }
+}
+
+.dot-bar {
+    display: flex;
+    position: absolute;
+    justify-content: center;
+    bottom: 5%;
+    width: 100%;
+
+    .dot,
+    .dot-active {
+        height: 15px;
+        width: 15px;
+        border-radius: 50%;
+        margin: 3px;
+        display: inline-block;
+        background-color: lightgrey;
+        cursor: pointer;
+    }
+
+    .dot-active {
+        background-color: grey;
+    }
 }
\ No newline at end of file
diff --git a/src/client/views/collections/CollectionCarousel3DView.tsx b/src/client/views/collections/CollectionCarousel3DView.tsx
index 9665e23ff..aefac3512 100644
--- a/src/client/views/collections/CollectionCarousel3DView.tsx
+++ b/src/client/views/collections/CollectionCarousel3DView.tsx
@@ -141,6 +141,13 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume
         </>;
     }
 
+    @computed get dots() {
+        return (this.childLayoutPairs.map((_child, index) => {
+            return <div key={index} className={`dot${index === NumCast(this.layoutDoc._itemIndex) ? "-active" : ""}`}
+                onClick={() => this.layoutDoc._itemIndex = index} />;
+        }));
+    }
+
     render() {
         const index = NumCast(this.layoutDoc._itemIndex);
         const offset = (index - 1) * (this.mainPanelWidth() - this.sidePanelWidth()) / this.childLayoutPairs.length;
@@ -151,6 +158,9 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume
                 {this.content}
             </div>
             {this.props.Document._chromeStatus !== "replaced" ? this.buttons : (null)}
+            <div className="dot-bar">
+                {this.dots}
+            </div>
         </div>;
     }
 }
\ No newline at end of file
-- 
cgit v1.2.3-70-g09d2


From 8de2aa4c90926ce733f0cd6021c226ab91df15ee Mon Sep 17 00:00:00 2001
From: Melissa Zhang <mzhang19096@gmail.com>
Date: Wed, 27 May 2020 01:31:59 -0700
Subject: formatting changes

---
 .../collections/CollectionCarousel3DView.scss      |  9 ++---
 .../views/collections/CollectionCarousel3DView.tsx | 38 ++++++++--------------
 2 files changed, 17 insertions(+), 30 deletions(-)

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

diff --git a/src/client/views/collections/CollectionCarousel3DView.scss b/src/client/views/collections/CollectionCarousel3DView.scss
index 47ee8ef53..601071917 100644
--- a/src/client/views/collections/CollectionCarousel3DView.scss
+++ b/src/client/views/collections/CollectionCarousel3DView.scss
@@ -7,16 +7,13 @@
 .carousel-wrapper {
     display: flex;
     position: absolute;
-    top: 10px;
+    top: 15%;
     align-items: center;
-    transition: transform 0.75s cubic-bezier(0.455, 0.03, 0.515, 0.955);
+    transition: transform 0.5s cubic-bezier(0.455, 0.03, 0.515, 0.955);
 
     .collectionCarouselView-item {
         flex: 1;
-        transition: opacity 0.5s linear;
-        transition: transform 0.5s linear;
-        transition: height 0.5s linear;
-        transition: width 0.5s linear;
+        transition: opacity 0.5s linear, transform 0.5s cubic-bezier(0.455, 0.03, 0.515, 0.955);
     }
 }
 
diff --git a/src/client/views/collections/CollectionCarousel3DView.tsx b/src/client/views/collections/CollectionCarousel3DView.tsx
index aefac3512..b47ce0836 100644
--- a/src/client/views/collections/CollectionCarousel3DView.tsx
+++ b/src/client/views/collections/CollectionCarousel3DView.tsx
@@ -11,9 +11,10 @@ import { CollectionSubView } from './CollectionSubView';
 import { Doc } from '../../../fields/Doc';
 import { ContextMenu } from '../ContextMenu';
 import { ObjectField } from '../../../fields/ObjectField';
-import { returnFalse } from '../../../Utils';
+import { returnFalse, Utils } from '../../../Utils';
 import { ScriptField } from '../../../fields/ScriptField';
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { Id } from '../../../fields/FieldSymbols';
 
 type Carousel3DDocument = makeInterface<[typeof documentSchema, typeof collectionSchema]>;
 const Carousel3DDocument = makeInterface(documentSchema, collectionSchema);
@@ -31,15 +32,11 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume
         }
     }
 
-    mainPanelWidth = () => this.props.PanelWidth() * 0.5;
-    mainPanelHeight = () => this.props.PanelHeight() * 0.9;
-    sidePanelWidth = () => this.props.PanelWidth() * 0.25;
-    sidePanelHeight = () => this.props.PanelHeight() * 0.5;
-
+    panelWidth = () => this.props.PanelWidth() / 3;
+    panelHeight = () => this.props.PanelHeight() * 0.6;
     @computed get content() {
         const currentIndex = NumCast(this.layoutDoc._itemIndex);
 
-
         const displayDoc = (childPair: { layout: Doc, data: Doc }, width: () => number, height: () => number) => {
             const showCaptionScript = ScriptField.MakeScript(
                 "child._showCaption = 'caption'",
@@ -70,20 +67,14 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume
         };
 
         return (
-            this.childLayoutPairs.map((child, index) => {
-                if (index === currentIndex) {
-                    return (
-                        <div key={index} className={`collectionCarouselView-item ${index}`}
-                            style={{ opacity: '1' }}>
-                            {displayDoc(child, this.mainPanelWidth, this.mainPanelHeight)}
-                        </div>);
-                } else {
-                    return (
-                        <div key={index} className={`collectionCarouselView-item ${index}`}
-                            style={{ opacity: '0.5', userSelect: 'none' }}>
-                            {displayDoc(child, this.sidePanelWidth, this.sidePanelHeight)}
-                        </div>);
-                }
+            this.childLayoutPairs.map((childPair, index) => {
+                return (
+                    <div key={childPair.layout[Id]} className={`collectionCarouselView-item ${index}`}
+                        style={index === currentIndex ?
+                            { opacity: '1', transform: 'scale(1.3)' } :
+                            { opacity: '0.5', transform: 'scale(0.6)', userSelect: 'none' }}>
+                        {displayDoc(childPair, this.panelWidth, this.panelHeight)}
+                    </div>);
             }));
     }
 
@@ -143,18 +134,17 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume
 
     @computed get dots() {
         return (this.childLayoutPairs.map((_child, index) => {
-            return <div key={index} className={`dot${index === NumCast(this.layoutDoc._itemIndex) ? "-active" : ""}`}
+            return <div key={Utils.GenerateGuid()} className={`dot${index === NumCast(this.layoutDoc._itemIndex) ? "-active" : ""}`}
                 onClick={() => this.layoutDoc._itemIndex = index} />;
         }));
     }
 
     render() {
         const index = NumCast(this.layoutDoc._itemIndex);
-        const offset = (index - 1) * (this.mainPanelWidth() - this.sidePanelWidth()) / this.childLayoutPairs.length;
         const translateX = (1 - index) / this.childLayoutPairs.length * 100;
 
         return <div className="collectionCarouselView-outer" onClick={this.onClick} onPointerDown={this.onPointerDown} ref={this.createDashEventsTarget} onContextMenu={this.onContextMenu}>
-            <div className="carousel-wrapper" style={{ transform: `translateX(calc(${translateX}% + ${offset}px)` }}>
+            <div className="carousel-wrapper" style={{ transform: `translateX(calc(${translateX}%` }}>
                 {this.content}
             </div>
             {this.props.Document._chromeStatus !== "replaced" ? this.buttons : (null)}
-- 
cgit v1.2.3-70-g09d2


From 7551a05109cafd4f1aba1b717a54c0eb32209234 Mon Sep 17 00:00:00 2001
From: Melissa Zhang <mzhang19096@gmail.com>
Date: Sun, 31 May 2020 14:30:45 -0700
Subject: add hold down arrow to autoscroll functionality

---
 .../collections/CollectionCarousel3DView.scss      |  4 +-
 .../views/collections/CollectionCarousel3DView.tsx | 56 +++++++++++++++++++---
 2 files changed, 51 insertions(+), 9 deletions(-)

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

diff --git a/src/client/views/collections/CollectionCarousel3DView.scss b/src/client/views/collections/CollectionCarousel3DView.scss
index 601071917..650b76b31 100644
--- a/src/client/views/collections/CollectionCarousel3DView.scss
+++ b/src/client/views/collections/CollectionCarousel3DView.scss
@@ -9,11 +9,11 @@
     position: absolute;
     top: 15%;
     align-items: center;
-    transition: transform 0.5s cubic-bezier(0.455, 0.03, 0.515, 0.955);
+    transition: transform 0.3s cubic-bezier(0.455, 0.03, 0.515, 0.955);
 
     .collectionCarouselView-item {
         flex: 1;
-        transition: opacity 0.5s linear, transform 0.5s cubic-bezier(0.455, 0.03, 0.515, 0.955);
+        transition: opacity 0.3s linear, transform 0.5s cubic-bezier(0.455, 0.03, 0.515, 0.955);
     }
 }
 
diff --git a/src/client/views/collections/CollectionCarousel3DView.tsx b/src/client/views/collections/CollectionCarousel3DView.tsx
index b47ce0836..4ec5394da 100644
--- a/src/client/views/collections/CollectionCarousel3DView.tsx
+++ b/src/client/views/collections/CollectionCarousel3DView.tsx
@@ -78,13 +78,51 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume
             }));
     }
 
-    advance = (e: React.MouseEvent) => {
+    handleArrowClick = (e: React.MouseEvent, direction: number) => {
         e.stopPropagation();
-        this.layoutDoc._itemIndex = (NumCast(this.layoutDoc._itemIndex) + 1) % this.childLayoutPairs.length;
+        this.rotate(direction);
     }
-    goback = (e: React.MouseEvent) => {
-        e.stopPropagation();
-        this.layoutDoc._itemIndex = (NumCast(this.layoutDoc._itemIndex) - 1 + this.childLayoutPairs.length) % this.childLayoutPairs.length;
+
+    rotate = (direction: number) => {
+        this.layoutDoc._itemIndex = (NumCast(this.layoutDoc._itemIndex) + direction + this.childLayoutPairs.length) % this.childLayoutPairs.length;
+    }
+
+    timer?: NodeJS.Timeout;
+    interval?: NodeJS.Timeout;
+    onPress = (e: React.PointerEvent, direction: number) => {
+        e.stopPropagation;
+        document.removeEventListener("pointerup", this.onRelease);
+        document.addEventListener("pointerup", this.onRelease);
+
+        this.timer = setTimeout(() => {
+            this.startScroll(direction);
+        }, 1500);
+    }
+
+    onRelease = () => {
+        if (this.timer) {
+            clearTimeout(this.timer);
+            this.timer = undefined;
+        }
+        this.stopScroll();
+    }
+
+    startScroll = (direction: number) => {
+        this.interval = setInterval(() => {
+            this.rotate(direction);
+        }, 500);
+    }
+
+    stopScroll = () => {
+        if (this.timer) {
+            clearTimeout(this.timer);
+            this.timer = undefined;
+        }
+
+        if (this.interval) {
+            clearInterval(this.interval);
+            this.interval = undefined;
+        }
     }
 
     onContextMenu = (e: React.MouseEvent): void => {
@@ -123,10 +161,14 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume
 
     @computed get buttons() {
         return <>
-            <div key="back" className="carouselView-back" style={{ background: `${StrCast(this.props.Document.backgroundColor)}` }} onClick={this.goback}>
+            <div key="back" className="carouselView-back" style={{ background: `${StrCast(this.props.Document.backgroundColor)}` }}
+                onClick={(e) => this.handleArrowClick(e, -1)}
+                onPointerDown={(e) => this.onPress(e, -1)}>
                 <FontAwesomeIcon icon={"caret-left"} size={"2x"} />
             </div>
-            <div key="fwd" className="carouselView-fwd" style={{ background: `${StrCast(this.props.Document.backgroundColor)}` }} onClick={this.advance}>
+            <div key="fwd" className="carouselView-fwd" style={{ background: `${StrCast(this.props.Document.backgroundColor)}` }}
+                onClick={(e) => this.handleArrowClick(e, 1)}
+                onPointerDown={(e) => this.onPress(e, 1)}>
                 <FontAwesomeIcon icon={"caret-right"} size={"2x"} />
             </div>
         </>;
-- 
cgit v1.2.3-70-g09d2


From 3a1541e1ef4277471075936aedadd4541384f470 Mon Sep 17 00:00:00 2001
From: Melissa Zhang <mzhang19096@gmail.com>
Date: Mon, 1 Jun 2020 13:26:49 -0700
Subject: cleanup

---
 .../collections/CollectionCarousel3DView.scss      |  5 +++
 .../views/collections/CollectionCarousel3DView.tsx | 47 ++++++++--------------
 2 files changed, 21 insertions(+), 31 deletions(-)

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

diff --git a/src/client/views/collections/CollectionCarousel3DView.scss b/src/client/views/collections/CollectionCarousel3DView.scss
index 650b76b31..6c746490a 100644
--- a/src/client/views/collections/CollectionCarousel3DView.scss
+++ b/src/client/views/collections/CollectionCarousel3DView.scss
@@ -38,4 +38,9 @@
     .dot-active {
         background-color: grey;
     }
+}
+
+.carouselView-back,
+.carouselView-forward {
+    cursor: pointer;
 }
\ No newline at end of file
diff --git a/src/client/views/collections/CollectionCarousel3DView.tsx b/src/client/views/collections/CollectionCarousel3DView.tsx
index 4ec5394da..0baf44aeb 100644
--- a/src/client/views/collections/CollectionCarousel3DView.tsx
+++ b/src/client/views/collections/CollectionCarousel3DView.tsx
@@ -36,30 +36,17 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume
     panelHeight = () => this.props.PanelHeight() * 0.6;
     @computed get content() {
         const currentIndex = NumCast(this.layoutDoc._itemIndex);
-
-        const displayDoc = (childPair: { layout: Doc, data: Doc }, width: () => number, height: () => number) => {
-            const showCaptionScript = ScriptField.MakeScript(
-                "child._showCaption = 'caption'",
-                { child: Doc.name },
-                { child: childPair.layout }
-            );
-
-            // const changeIndexScript = ScriptField.MakeScript(
-            //     "collectionLayoutDoc._itemIndex = collectionLayoutDoc[fieldKey].indexOf(self)",
-            //     { fieldKey: String.name, collectionLayoutDoc: Doc.name },
-            //     { fieldKey: this.props.fieldKey, collectionLayoutDoc: this.layoutDoc }
-            // );
-
+        const displayDoc = (childPair: { layout: Doc, data: Doc }, onClickScript: ScriptField | undefined) => {
             return <ContentFittingDocumentView {...this.props}
                 onDoubleClick={ScriptCast(this.layoutDoc.onChildDoubleClick)}
-                onClick={showCaptionScript}
+                onClick={onClickScript}
                 renderDepth={this.props.renderDepth + 1}
                 LayoutTemplate={this.props.ChildLayoutTemplate}
                 LayoutTemplateString={this.props.ChildLayoutString}
                 Document={childPair.layout}
                 DataDoc={childPair.data}
-                PanelWidth={width}
-                PanelHeight={height}
+                PanelWidth={this.panelWidth}
+                PanelHeight={this.panelHeight}
                 ScreenToLocalTransform={this.props.ScreenToLocalTransform}
                 bringToFront={returnFalse}
                 parentActive={this.props.active}
@@ -68,22 +55,28 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume
 
         return (
             this.childLayoutPairs.map((childPair, index) => {
+                const showCaptionScript = ScriptField.MakeScript(
+                    "child._showCaption = 'caption'",
+                    { child: Doc.name },
+                    { child: childPair.layout }
+                );
+
                 return (
                     <div key={childPair.layout[Id]} className={`collectionCarouselView-item ${index}`}
                         style={index === currentIndex ?
                             { opacity: '1', transform: 'scale(1.3)' } :
                             { opacity: '0.5', transform: 'scale(0.6)', userSelect: 'none' }}>
-                        {displayDoc(childPair, this.panelWidth, this.panelHeight)}
+                        {displayDoc(childPair, index === currentIndex ? showCaptionScript : undefined)}
                     </div>);
             }));
     }
 
     handleArrowClick = (e: React.MouseEvent, direction: number) => {
         e.stopPropagation();
-        this.rotate(direction);
+        this.changeSlide(direction);
     }
 
-    rotate = (direction: number) => {
+    changeSlide = (direction: number) => {
         this.layoutDoc._itemIndex = (NumCast(this.layoutDoc._itemIndex) + direction + this.childLayoutPairs.length) % this.childLayoutPairs.length;
     }
 
@@ -91,25 +84,17 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume
     interval?: NodeJS.Timeout;
     onPress = (e: React.PointerEvent, direction: number) => {
         e.stopPropagation;
-        document.removeEventListener("pointerup", this.onRelease);
-        document.addEventListener("pointerup", this.onRelease);
+        document.removeEventListener("pointerup", this.stopScroll);
+        document.addEventListener("pointerup", this.stopScroll);
 
         this.timer = setTimeout(() => {
             this.startScroll(direction);
         }, 1500);
     }
 
-    onRelease = () => {
-        if (this.timer) {
-            clearTimeout(this.timer);
-            this.timer = undefined;
-        }
-        this.stopScroll();
-    }
-
     startScroll = (direction: number) => {
         this.interval = setInterval(() => {
-            this.rotate(direction);
+            this.changeSlide(direction);
         }, 500);
     }
 
-- 
cgit v1.2.3-70-g09d2


From 7788d70d5ae6a5ccdf7cd354c31f463fb00731a2 Mon Sep 17 00:00:00 2001
From: Melissa Zhang <mzhang19096@gmail.com>
Date: Tue, 2 Jun 2020 14:02:02 -0700
Subject: fix timeout bug, disable pointer events for items on the side

---
 .../collections/CollectionCarousel3DView.scss      |  8 ++-
 .../views/collections/CollectionCarousel3DView.tsx | 61 +++++++++++-----------
 2 files changed, 37 insertions(+), 32 deletions(-)

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

diff --git a/src/client/views/collections/CollectionCarousel3DView.scss b/src/client/views/collections/CollectionCarousel3DView.scss
index 6c746490a..d00a666f8 100644
--- a/src/client/views/collections/CollectionCarousel3DView.scss
+++ b/src/client/views/collections/CollectionCarousel3DView.scss
@@ -11,9 +11,15 @@
     align-items: center;
     transition: transform 0.3s cubic-bezier(0.455, 0.03, 0.515, 0.955);
 
-    .collectionCarouselView-item {
+    .collectionCarouselView-item,
+    .collectionCarouselView-item-active {
         flex: 1;
         transition: opacity 0.3s linear, transform 0.5s cubic-bezier(0.455, 0.03, 0.515, 0.955);
+        pointer-events: none;
+    }
+
+    .collectionCarouselView-item-active {
+        pointer-events: unset;
     }
 }
 
diff --git a/src/client/views/collections/CollectionCarousel3DView.tsx b/src/client/views/collections/CollectionCarousel3DView.tsx
index 0baf44aeb..bad3096c8 100644
--- a/src/client/views/collections/CollectionCarousel3DView.tsx
+++ b/src/client/views/collections/CollectionCarousel3DView.tsx
@@ -36,10 +36,14 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume
     panelHeight = () => this.props.PanelHeight() * 0.6;
     @computed get content() {
         const currentIndex = NumCast(this.layoutDoc._itemIndex);
-        const displayDoc = (childPair: { layout: Doc, data: Doc }, onClickScript: ScriptField | undefined) => {
+        const displayDoc = (childPair: { layout: Doc, data: Doc }) => {
             return <ContentFittingDocumentView {...this.props}
                 onDoubleClick={ScriptCast(this.layoutDoc.onChildDoubleClick)}
-                onClick={onClickScript}
+                onClick={ScriptField.MakeScript(
+                    "child._showCaption = 'caption'",
+                    { child: Doc.name },
+                    { child: childPair.layout }
+                )}
                 renderDepth={this.props.renderDepth + 1}
                 LayoutTemplate={this.props.ChildLayoutTemplate}
                 LayoutTemplateString={this.props.ChildLayoutString}
@@ -55,57 +59,54 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume
 
         return (
             this.childLayoutPairs.map((childPair, index) => {
-                const showCaptionScript = ScriptField.MakeScript(
-                    "child._showCaption = 'caption'",
-                    { child: Doc.name },
-                    { child: childPair.layout }
-                );
-
                 return (
-                    <div key={childPair.layout[Id]} className={`collectionCarouselView-item ${index}`}
+                    <div key={childPair.layout[Id]}
+                        className={`collectionCarouselView-item${index === currentIndex ? "-active" : ""} ${index}`}
                         style={index === currentIndex ?
                             { opacity: '1', transform: 'scale(1.3)' } :
                             { opacity: '0.5', transform: 'scale(0.6)', userSelect: 'none' }}>
-                        {displayDoc(childPair, index === currentIndex ? showCaptionScript : undefined)}
+                        {displayDoc(childPair)}
                     </div>);
             }));
     }
 
-    handleArrowClick = (e: React.MouseEvent, direction: number) => {
-        e.stopPropagation();
-        this.changeSlide(direction);
-    }
-
     changeSlide = (direction: number) => {
         this.layoutDoc._itemIndex = (NumCast(this.layoutDoc._itemIndex) + direction + this.childLayoutPairs.length) % this.childLayoutPairs.length;
     }
 
-    timer?: NodeJS.Timeout;
-    interval?: NodeJS.Timeout;
-    onPress = (e: React.PointerEvent, direction: number) => {
+    timer?: number;
+    interval?: number;
+    onArrowDown = (e: React.PointerEvent, direction: number) => {
         e.stopPropagation;
-        document.removeEventListener("pointerup", this.stopScroll);
-        document.addEventListener("pointerup", this.stopScroll);
+        document.removeEventListener("pointerup", () => this.onArrowRelease(direction));
+        document.addEventListener("pointerup", () => this.onArrowRelease(direction));
 
-        this.timer = setTimeout(() => {
+        this.layoutDoc.startScrollTimeout = 1500;
+        this.timer = window.setTimeout(() => { // if arrow is held down long enough, activate automatic scrolling
+            window.clearTimeout(this.timer);
+            this.timer = undefined;
             this.startScroll(direction);
-        }, 1500);
+        }, this.layoutDoc.startScrollTimeout);
     }
 
     startScroll = (direction: number) => {
-        this.interval = setInterval(() => {
+        this.layoutDoc.scrollInterval = 500;
+        this.interval = window.setInterval(() => {
             this.changeSlide(direction);
-        }, 500);
+        }, this.layoutDoc.scrollInterval);
     }
 
-    stopScroll = () => {
+    onArrowRelease = (direction: number) => {
+        document.removeEventListener("pointerup", () => this.onArrowRelease(direction));
+
         if (this.timer) {
-            clearTimeout(this.timer);
+            this.changeSlide(direction); // if click wasn't long enough to activate autoscroll, only advance/go back 1 slide
+            window.clearTimeout(this.timer);
             this.timer = undefined;
         }
 
         if (this.interval) {
-            clearInterval(this.interval);
+            window.clearInterval(this.interval); // stop scrolling
             this.interval = undefined;
         }
     }
@@ -147,13 +148,11 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume
     @computed get buttons() {
         return <>
             <div key="back" className="carouselView-back" style={{ background: `${StrCast(this.props.Document.backgroundColor)}` }}
-                onClick={(e) => this.handleArrowClick(e, -1)}
-                onPointerDown={(e) => this.onPress(e, -1)}>
+                onPointerDown={(e) => this.onArrowDown(e, -1)}>
                 <FontAwesomeIcon icon={"caret-left"} size={"2x"} />
             </div>
             <div key="fwd" className="carouselView-fwd" style={{ background: `${StrCast(this.props.Document.backgroundColor)}` }}
-                onClick={(e) => this.handleArrowClick(e, 1)}
-                onPointerDown={(e) => this.onPress(e, 1)}>
+                onPointerDown={(e) => this.onArrowDown(e, 1)}>
                 <FontAwesomeIcon icon={"caret-right"} size={"2x"} />
             </div>
         </>;
-- 
cgit v1.2.3-70-g09d2


From ced0c14ea8410eeedcbdc8eba4e0227840c488b5 Mon Sep 17 00:00:00 2001
From: Melissa Zhang <mzhang19096@gmail.com>
Date: Tue, 2 Jun 2020 20:08:06 -0700
Subject: arrows bug fix

---
 package-lock.json                                  | 84 +++++++++++++---------
 .../views/collections/CollectionCarousel3DView.tsx | 27 ++++---
 2 files changed, 68 insertions(+), 43 deletions(-)

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

diff --git a/package-lock.json b/package-lock.json
index 842553659..6ee723aab 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -2827,7 +2827,8 @@
                         },
                         "ansi-regex": {
                             "version": "2.1.1",
-                            "bundled": true
+                            "bundled": true,
+                            "optional": true
                         },
                         "aproba": {
                             "version": "1.2.0",
@@ -2845,11 +2846,13 @@
                         },
                         "balanced-match": {
                             "version": "1.0.0",
-                            "bundled": true
+                            "bundled": true,
+                            "optional": true
                         },
                         "brace-expansion": {
                             "version": "1.1.11",
                             "bundled": true,
+                            "optional": true,
                             "requires": {
                                 "balanced-match": "^1.0.0",
                                 "concat-map": "0.0.1"
@@ -2862,15 +2865,18 @@
                         },
                         "code-point-at": {
                             "version": "1.1.0",
-                            "bundled": true
+                            "bundled": true,
+                            "optional": true
                         },
                         "concat-map": {
                             "version": "0.0.1",
-                            "bundled": true
+                            "bundled": true,
+                            "optional": true
                         },
                         "console-control-strings": {
                             "version": "1.1.0",
-                            "bundled": true
+                            "bundled": true,
+                            "optional": true
                         },
                         "core-util-is": {
                             "version": "1.0.2",
@@ -2973,7 +2979,8 @@
                         },
                         "inherits": {
                             "version": "2.0.4",
-                            "bundled": true
+                            "bundled": true,
+                            "optional": true
                         },
                         "ini": {
                             "version": "1.3.5",
@@ -2983,6 +2990,7 @@
                         "is-fullwidth-code-point": {
                             "version": "1.0.0",
                             "bundled": true,
+                            "optional": true,
                             "requires": {
                                 "number-is-nan": "^1.0.0"
                             }
@@ -2995,17 +3003,20 @@
                         "minimatch": {
                             "version": "3.0.4",
                             "bundled": true,
+                            "optional": true,
                             "requires": {
                                 "brace-expansion": "^1.1.7"
                             }
                         },
                         "minimist": {
                             "version": "1.2.5",
-                            "bundled": true
+                            "bundled": true,
+                            "optional": true
                         },
                         "minipass": {
                             "version": "2.9.0",
                             "bundled": true,
+                            "optional": true,
                             "requires": {
                                 "safe-buffer": "^5.1.2",
                                 "yallist": "^3.0.0"
@@ -3022,6 +3033,7 @@
                         "mkdirp": {
                             "version": "0.5.3",
                             "bundled": true,
+                            "optional": true,
                             "requires": {
                                 "minimist": "^1.2.5"
                             }
@@ -3077,7 +3089,8 @@
                         },
                         "npm-normalize-package-bin": {
                             "version": "1.0.1",
-                            "bundled": true
+                            "bundled": true,
+                            "optional": true
                         },
                         "npm-packlist": {
                             "version": "1.4.8",
@@ -3102,7 +3115,8 @@
                         },
                         "number-is-nan": {
                             "version": "1.0.1",
-                            "bundled": true
+                            "bundled": true,
+                            "optional": true
                         },
                         "object-assign": {
                             "version": "4.1.1",
@@ -3112,6 +3126,7 @@
                         "once": {
                             "version": "1.4.0",
                             "bundled": true,
+                            "optional": true,
                             "requires": {
                                 "wrappy": "1"
                             }
@@ -3180,7 +3195,8 @@
                         },
                         "safe-buffer": {
                             "version": "5.1.2",
-                            "bundled": true
+                            "bundled": true,
+                            "optional": true
                         },
                         "safer-buffer": {
                             "version": "2.1.2",
@@ -3210,6 +3226,7 @@
                         "string-width": {
                             "version": "1.0.2",
                             "bundled": true,
+                            "optional": true,
                             "requires": {
                                 "code-point-at": "^1.0.0",
                                 "is-fullwidth-code-point": "^1.0.0",
@@ -3227,6 +3244,7 @@
                         "strip-ansi": {
                             "version": "3.0.1",
                             "bundled": true,
+                            "optional": true,
                             "requires": {
                                 "ansi-regex": "^2.0.0"
                             }
@@ -3265,11 +3283,13 @@
                         },
                         "wrappy": {
                             "version": "1.0.2",
-                            "bundled": true
+                            "bundled": true,
+                            "optional": true
                         },
                         "yallist": {
                             "version": "3.1.1",
-                            "bundled": true
+                            "bundled": true,
+                            "optional": true
                         }
                     }
                 }
@@ -9486,7 +9506,7 @@
                 },
                 "chownr": {
                     "version": "1.1.4",
-                    "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
+                    "resolved": false,
                     "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg=="
                 },
                 "ci-info": {
@@ -9792,7 +9812,7 @@
                 },
                 "deep-extend": {
                     "version": "0.6.0",
-                    "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
+                    "resolved": false,
                     "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA=="
                 },
                 "defaults": {
@@ -10291,7 +10311,7 @@
                 },
                 "glob": {
                     "version": "7.1.6",
-                    "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
+                    "resolved": false,
                     "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
                     "requires": {
                         "fs.realpath": "^1.0.0",
@@ -10379,7 +10399,7 @@
                 },
                 "hosted-git-info": {
                     "version": "2.8.8",
-                    "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz",
+                    "resolved": false,
                     "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg=="
                 },
                 "http-cache-semantics": {
@@ -10515,7 +10535,7 @@
                 },
                 "is-ci": {
                     "version": "1.2.1",
-                    "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.2.1.tgz",
+                    "resolved": false,
                     "integrity": "sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg==",
                     "requires": {
                         "ci-info": "^1.5.0"
@@ -10591,7 +10611,7 @@
                 },
                 "is-retry-allowed": {
                     "version": "1.2.0",
-                    "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz",
+                    "resolved": false,
                     "integrity": "sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg=="
                 },
                 "is-stream": {
@@ -11100,7 +11120,7 @@
                 },
                 "mkdirp": {
                     "version": "0.5.4",
-                    "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.4.tgz",
+                    "resolved": false,
                     "integrity": "sha512-iG9AK/dJLtJ0XNgTuDbSyNS3zECqDlAhnQW4CsNxBG3LQJBbHmRX1egw39DmtOdCAqY+dKXV+sgPgilNWUKMVw==",
                     "requires": {
                         "minimist": "^1.2.5"
@@ -11108,7 +11128,7 @@
                     "dependencies": {
                         "minimist": {
                             "version": "1.2.5",
-                            "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
+                            "resolved": false,
                             "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="
                         }
                     }
@@ -11160,7 +11180,7 @@
                 },
                 "node-gyp": {
                     "version": "5.1.0",
-                    "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-5.1.0.tgz",
+                    "resolved": false,
                     "integrity": "sha512-OUTryc5bt/P8zVgNUmC6xdXiDJxLMAW8cF5tLQOT9E5sOQj+UeQxnnPy74K3CLCa/SOjjBlbuzDLR8ANwA+wmw==",
                     "requires": {
                         "env-paths": "^2.2.0",
@@ -11274,7 +11294,7 @@
                 },
                 "npm-packlist": {
                     "version": "1.4.8",
-                    "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.8.tgz",
+                    "resolved": false,
                     "integrity": "sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A==",
                     "requires": {
                         "ignore-walk": "^3.0.1",
@@ -11294,7 +11314,7 @@
                 },
                 "npm-profile": {
                     "version": "4.0.4",
-                    "resolved": "https://registry.npmjs.org/npm-profile/-/npm-profile-4.0.4.tgz",
+                    "resolved": false,
                     "integrity": "sha512-Ta8xq8TLMpqssF0H60BXS1A90iMoM6GeKwsmravJ6wYjWwSzcYBTdyWa3DZCYqPutacBMEm7cxiOkiIeCUAHDQ==",
                     "requires": {
                         "aproba": "^1.1.2 || 2",
@@ -11304,7 +11324,7 @@
                 },
                 "npm-registry-fetch": {
                     "version": "4.0.3",
-                    "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-4.0.3.tgz",
+                    "resolved": false,
                     "integrity": "sha512-WGvUx0lkKFhu9MbiGFuT9nG2NpfQ+4dCJwRwwtK2HK5izJEvwDxMeUyqbuMS7N/OkpVCqDorV6rO5E4V9F8lJw==",
                     "requires": {
                         "JSONStream": "^1.3.4",
@@ -11739,7 +11759,7 @@
                 },
                 "rc": {
                     "version": "1.2.8",
-                    "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
+                    "resolved": false,
                     "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
                     "requires": {
                         "deep-extend": "^0.6.0",
@@ -11750,7 +11770,7 @@
                     "dependencies": {
                         "minimist": {
                             "version": "1.2.5",
-                            "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
+                            "resolved": false,
                             "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="
                         }
                     }
@@ -11809,7 +11829,7 @@
                 },
                 "readable-stream": {
                     "version": "3.6.0",
-                    "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
+                    "resolved": false,
                     "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
                     "requires": {
                         "inherits": "^2.0.3",
@@ -11830,7 +11850,7 @@
                 },
                 "registry-auth-token": {
                     "version": "3.4.0",
-                    "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.4.0.tgz",
+                    "resolved": false,
                     "integrity": "sha512-4LM6Fw8eBQdwMYcES4yTnn2TqIasbXuwDx3um+QRs7S55aMKCBKBxvPXl2RiUjHwuJLTyYfxSpmfSAjQpcuP+A==",
                     "requires": {
                         "rc": "^1.1.6",
@@ -11894,7 +11914,7 @@
                 },
                 "rimraf": {
                     "version": "2.7.1",
-                    "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
+                    "resolved": false,
                     "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
                     "requires": {
                         "glob": "^7.1.3"
@@ -12193,7 +12213,7 @@
                 },
                 "string_decoder": {
                     "version": "1.3.0",
-                    "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
+                    "resolved": false,
                     "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
                     "requires": {
                         "safe-buffer": "~5.2.0"
@@ -12201,7 +12221,7 @@
                     "dependencies": {
                         "safe-buffer": {
                             "version": "5.2.0",
-                            "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz",
+                            "resolved": false,
                             "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg=="
                         }
                     }
@@ -12513,7 +12533,7 @@
                 },
                 "widest-line": {
                     "version": "2.0.1",
-                    "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-2.0.1.tgz",
+                    "resolved": false,
                     "integrity": "sha512-Ba5m9/Fa4Xt9eb2ELXt77JxVDV8w7qQrH0zS/TWSJdLyAwQjWoOzpzj5lwVftDz6n/EOu3tNACS84v509qwnJA==",
                     "requires": {
                         "string-width": "^2.1.1"
diff --git a/src/client/views/collections/CollectionCarousel3DView.tsx b/src/client/views/collections/CollectionCarousel3DView.tsx
index bad3096c8..097bbb7b3 100644
--- a/src/client/views/collections/CollectionCarousel3DView.tsx
+++ b/src/client/views/collections/CollectionCarousel3DView.tsx
@@ -71,15 +71,29 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume
     }
 
     changeSlide = (direction: number) => {
+        console.log("old", NumCast(this.layoutDoc._itemIndex), direction);
         this.layoutDoc._itemIndex = (NumCast(this.layoutDoc._itemIndex) + direction + this.childLayoutPairs.length) % this.childLayoutPairs.length;
+        console.log("new", NumCast(this.layoutDoc._itemIndex));
+    }
+
+    startScroll = (direction: number) => {
+        this.layoutDoc.scrollInterval = 500;
+        this.interval = window.setInterval(() => {
+            this.changeSlide(direction);
+        }, this.layoutDoc.scrollInterval);
     }
 
     timer?: number;
     interval?: number;
     onArrowDown = (e: React.PointerEvent, direction: number) => {
+        console.log("onArrowDown", direction);
         e.stopPropagation;
-        document.removeEventListener("pointerup", () => this.onArrowRelease(direction));
-        document.addEventListener("pointerup", () => this.onArrowRelease(direction));
+
+        const listener = () => { // is able to pass in the direction parameter and then correctly remove the listener
+            this.onArrowRelease(direction);
+            document.removeEventListener("pointerup", listener);
+        };
+        document.addEventListener("pointerup", listener);
 
         this.layoutDoc.startScrollTimeout = 1500;
         this.timer = window.setTimeout(() => { // if arrow is held down long enough, activate automatic scrolling
@@ -89,16 +103,7 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume
         }, this.layoutDoc.startScrollTimeout);
     }
 
-    startScroll = (direction: number) => {
-        this.layoutDoc.scrollInterval = 500;
-        this.interval = window.setInterval(() => {
-            this.changeSlide(direction);
-        }, this.layoutDoc.scrollInterval);
-    }
-
     onArrowRelease = (direction: number) => {
-        document.removeEventListener("pointerup", () => this.onArrowRelease(direction));
-
         if (this.timer) {
             this.changeSlide(direction); // if click wasn't long enough to activate autoscroll, only advance/go back 1 slide
             window.clearTimeout(this.timer);
-- 
cgit v1.2.3-70-g09d2


From 2ca409065cd851e58033c5b1ac06f503a9ffe141 Mon Sep 17 00:00:00 2001
From: Melissa Zhang <mzhang19096@gmail.com>
Date: Wed, 3 Jun 2020 17:16:52 -0700
Subject: clean up

---
 src/client/views/collections/CollectionCarousel3DView.tsx | 9 +++------
 1 file changed, 3 insertions(+), 6 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 097bbb7b3..2f161e255 100644
--- a/src/client/views/collections/CollectionCarousel3DView.tsx
+++ b/src/client/views/collections/CollectionCarousel3DView.tsx
@@ -61,7 +61,7 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume
             this.childLayoutPairs.map((childPair, index) => {
                 return (
                     <div key={childPair.layout[Id]}
-                        className={`collectionCarouselView-item${index === currentIndex ? "-active" : ""} ${index}`}
+                        className={`collectionCarousel3DView-item${index === currentIndex ? "-active" : ""} ${index}`}
                         style={index === currentIndex ?
                             { opacity: '1', transform: 'scale(1.3)' } :
                             { opacity: '0.5', transform: 'scale(0.6)', userSelect: 'none' }}>
@@ -71,9 +71,7 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume
     }
 
     changeSlide = (direction: number) => {
-        console.log("old", NumCast(this.layoutDoc._itemIndex), direction);
         this.layoutDoc._itemIndex = (NumCast(this.layoutDoc._itemIndex) + direction + this.childLayoutPairs.length) % this.childLayoutPairs.length;
-        console.log("new", NumCast(this.layoutDoc._itemIndex));
     }
 
     startScroll = (direction: number) => {
@@ -86,7 +84,6 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume
     timer?: number;
     interval?: number;
     onArrowDown = (e: React.PointerEvent, direction: number) => {
-        console.log("onArrowDown", direction);
         e.stopPropagation;
 
         const listener = () => { // is able to pass in the direction parameter and then correctly remove the listener
@@ -95,7 +92,7 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume
         };
         document.addEventListener("pointerup", listener);
 
-        this.layoutDoc.startScrollTimeout = 1500;
+        this.layoutDoc.startScrollTimeout = 500;
         this.timer = window.setTimeout(() => { // if arrow is held down long enough, activate automatic scrolling
             window.clearTimeout(this.timer);
             this.timer = undefined;
@@ -174,7 +171,7 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume
         const index = NumCast(this.layoutDoc._itemIndex);
         const translateX = (1 - index) / this.childLayoutPairs.length * 100;
 
-        return <div className="collectionCarouselView-outer" onClick={this.onClick} onPointerDown={this.onPointerDown} ref={this.createDashEventsTarget} onContextMenu={this.onContextMenu}>
+        return <div className="collectionCarousel3DView-outer" onClick={this.onClick} onPointerDown={this.onPointerDown} ref={this.createDashEventsTarget} onContextMenu={this.onContextMenu}>
             <div className="carousel-wrapper" style={{ transform: `translateX(calc(${translateX}%` }}>
                 {this.content}
             </div>
-- 
cgit v1.2.3-70-g09d2


From 05fe7bb89e51f3d8b643726f3283ba8adee740e4 Mon Sep 17 00:00:00 2001
From: Melissa Zhang <mzhang19096@gmail.com>
Date: Thu, 4 Jun 2020 16:22:27 -0700
Subject: hover to show autoscroll button

---
 src/client/views/DocumentDecorations.tsx           |  7 +-
 .../collections/CollectionCarousel3DView.scss      | 49 ++++++++++--
 .../views/collections/CollectionCarousel3DView.tsx | 86 +++++++++++++---------
 src/client/views/collections/CollectionView.tsx    |  2 +-
 4 files changed, 100 insertions(+), 44 deletions(-)

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

diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 04f02c683..7cdf955a1 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -1,5 +1,5 @@
 import { IconProp, library } from '@fortawesome/fontawesome-svg-core';
-import { faCaretUp, faFilePdf, faFilm, faImage, faObjectGroup, faStickyNote, faTextHeight, faArrowAltCircleDown, faArrowAltCircleUp, faCheckCircle, faCloudUploadAlt, faLink, faShare, faStopCircle, faSyncAlt, faTag, faTimes } from '@fortawesome/free-solid-svg-icons';
+import { faCaretUp, faFilePdf, faFilm, faImage, faObjectGroup, faStickyNote, faTextHeight, faArrowAltCircleDown, faArrowAltCircleUp, faCheckCircle, faCloudUploadAlt, faLink, faShare, faStopCircle, faSyncAlt, faTag, faTimes, faAngleLeft, faAngleRight, faAngleDoubleLeft, faAngleDoubleRight, faPause } from '@fortawesome/free-solid-svg-icons';
 import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
 import { action, computed, observable, reaction, runInAction } from "mobx";
 import { observer } from "mobx-react";
@@ -38,6 +38,11 @@ library.add(faCheckCircle);
 library.add(faCloudUploadAlt);
 library.add(faSyncAlt);
 library.add(faShare);
+library.add(faAngleDoubleLeft);
+library.add(faAngleDoubleRight);
+library.add(faAngleLeft);
+library.add(faAngleRight);
+library.add(faPause);
 
 @observer
 export class DocumentDecorations extends React.Component<{}, { value: string }> {
diff --git a/src/client/views/collections/CollectionCarousel3DView.scss b/src/client/views/collections/CollectionCarousel3DView.scss
index d00a666f8..ff63f4116 100644
--- a/src/client/views/collections/CollectionCarousel3DView.scss
+++ b/src/client/views/collections/CollectionCarousel3DView.scss
@@ -1,4 +1,4 @@
-.collectionCarouselView-outer {
+.collectionCarousel3DView-outer {
     height: 100%;
     position: relative;
     background-color: white;
@@ -11,14 +11,14 @@
     align-items: center;
     transition: transform 0.3s cubic-bezier(0.455, 0.03, 0.515, 0.955);
 
-    .collectionCarouselView-item,
-    .collectionCarouselView-item-active {
+    .collectionCarousel3DView-item,
+    .collectionCarousel3DView-item-active {
         flex: 1;
         transition: opacity 0.3s linear, transform 0.5s cubic-bezier(0.455, 0.03, 0.515, 0.955);
         pointer-events: none;
     }
 
-    .collectionCarouselView-item-active {
+    .collectionCarousel3DView-item-active {
         pointer-events: unset;
     }
 }
@@ -46,7 +46,44 @@
     }
 }
 
-.carouselView-back,
-.carouselView-forward {
+.carousel3DView-back,
+.carousel3DView-fwd,
+.carousel3DView-back-scroll,
+.carousel3DView-fwd-scroll {
+    position: absolute;
+    display: flex;
+    width: 30;
+    height: 30;
+    align-items: center;
+    border-radius: 5px;
+    justify-content: center;
+    background: rgba(255, 255, 255, 0.46);
     cursor: pointer;
+}
+
+.carousel3DView-fwd {
+    top: 50%;
+    right: 0;
+}
+
+.carousel3DView-back {
+    top: 50%;
+    left: 0;
+}
+
+.carousel3DView-fwd-scroll {
+    top: calc(50% - 30px);
+    right: 0;
+}
+
+.carousel3DView-back-scroll {
+    top: calc(50% - 30px);
+    left: 0;
+}
+
+.carousel3DView-back:hover,
+.carousel3DView-fwd:hover,
+.carousel3DView-back-scroll:hover,
+.carousel3DView-fwd-scroll:hover {
+    background: lightgray;
 }
\ No newline at end of file
diff --git a/src/client/views/collections/CollectionCarousel3DView.tsx b/src/client/views/collections/CollectionCarousel3DView.tsx
index 2f161e255..1fa96df65 100644
--- a/src/client/views/collections/CollectionCarousel3DView.tsx
+++ b/src/client/views/collections/CollectionCarousel3DView.tsx
@@ -21,6 +21,10 @@ const Carousel3DDocument = makeInterface(documentSchema, collectionSchema);
 
 @observer
 export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocument) {
+    @computed get scrollSpeed() {
+        return this.layoutDoc._autoScrollSpeed ? NumCast(this.layoutDoc._autoScrollSpeed) : 1000; //default scroll speed
+    }
+
     private _dropDisposer?: DragManager.DragDropDisposer;
 
     componentWillUnmount() { this._dropDisposer?.(); }
@@ -74,43 +78,32 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume
         this.layoutDoc._itemIndex = (NumCast(this.layoutDoc._itemIndex) + direction + this.childLayoutPairs.length) % this.childLayoutPairs.length;
     }
 
-    startScroll = (direction: number) => {
-        this.layoutDoc.scrollInterval = 500;
-        this.interval = window.setInterval(() => {
-            this.changeSlide(direction);
-        }, this.layoutDoc.scrollInterval);
+    onArrowClick = (e: React.MouseEvent, direction: number) => {
+        e.stopPropagation();
+        this.changeSlide(direction);
     }
 
-    timer?: number;
     interval?: number;
-    onArrowDown = (e: React.PointerEvent, direction: number) => {
-        e.stopPropagation;
+    startAutoScroll = (direction: number) => {
+        this.interval = window.setInterval(() => {
+            this.changeSlide(direction);
+        }, this.scrollSpeed);
+    }
 
-        const listener = () => { // is able to pass in the direction parameter and then correctly remove the listener
-            this.onArrowRelease(direction);
-            document.removeEventListener("pointerup", listener);
-        };
-        document.addEventListener("pointerup", listener);
+    stopAutoScroll = () => {
+        window.clearInterval(this.interval);
+        this.interval = undefined;
+    }
 
-        this.layoutDoc.startScrollTimeout = 500;
-        this.timer = window.setTimeout(() => { // if arrow is held down long enough, activate automatic scrolling
-            window.clearTimeout(this.timer);
-            this.timer = undefined;
-            this.startScroll(direction);
-        }, this.layoutDoc.startScrollTimeout);
+    toggleAutoScroll = (direction: number) => {
+        this.layoutDoc.autoScrollOn = this.layoutDoc.autoScrollOn ? false : true;
+        this.layoutDoc.autoScrollOn ? this.startAutoScroll(direction) : this.stopAutoScroll();
     }
 
-    onArrowRelease = (direction: number) => {
-        if (this.timer) {
-            this.changeSlide(direction); // if click wasn't long enough to activate autoscroll, only advance/go back 1 slide
-            window.clearTimeout(this.timer);
-            this.timer = undefined;
-        }
+    showAutoScrollButton = (direction: string) => {
+        // keep pause button visible while autoscroll is on, and don't show the other side's autoscroll button
+        !this.layoutDoc.autoScrollOn && (this.layoutDoc.showScrollButton = direction);
 
-        if (this.interval) {
-            window.clearInterval(this.interval); // stop scrolling
-            this.interval = undefined;
-        }
     }
 
     onContextMenu = (e: React.MouseEvent): void => {
@@ -148,14 +141,35 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume
     }
 
     @computed get buttons() {
-        return <>
-            <div key="back" className="carouselView-back" style={{ background: `${StrCast(this.props.Document.backgroundColor)}` }}
-                onPointerDown={(e) => this.onArrowDown(e, -1)}>
-                <FontAwesomeIcon icon={"caret-left"} size={"2x"} />
+        if (!this.props.active()) return null;
+        return <div className="arrow-buttons" onMouseLeave={() => this.showAutoScrollButton("none")}>
+            <div key="back" className="carousel3DView-back" style={{ background: `${StrCast(this.props.Document.backgroundColor)}` }}
+                onClick={(e) => this.onArrowClick(e, -1)}
+                onMouseEnter={() => this.showAutoScrollButton("back")}>
+                <FontAwesomeIcon icon={"angle-left"} size={"2x"} />
             </div>
-            <div key="fwd" className="carouselView-fwd" style={{ background: `${StrCast(this.props.Document.backgroundColor)}` }}
-                onPointerDown={(e) => this.onArrowDown(e, 1)}>
-                <FontAwesomeIcon icon={"caret-right"} size={"2x"} />
+            <div key="fwd" className="carousel3DView-fwd" style={{ background: `${StrCast(this.props.Document.backgroundColor)}` }}
+                onClick={(e) => this.onArrowClick(e, 1)}
+                onMouseEnter={() => this.showAutoScrollButton("fwd")}>
+                <FontAwesomeIcon icon={"angle-right"} size={"2x"} />
+            </div>
+            {this.autoScrollButton}
+        </div>;
+    }
+
+    @computed get autoScrollButton() {
+        const direction = this.layoutDoc.showScrollButton;
+        if (direction !== "back" && direction !== "fwd") return null;
+
+        const offset = (direction === "back") ? -1 : 1;
+        return <>
+            <div className={`carousel3DView-${direction}-scroll`} style={{ background: `${StrCast(this.props.Document.backgroundColor)}` }}
+                onClick={() => this.toggleAutoScroll(offset)}>
+                {this.layoutDoc.autoScrollOn ?
+                    <FontAwesomeIcon icon={"pause"} size={"1x"} /> :
+                    direction === "back" ?
+                        <FontAwesomeIcon icon={"angle-double-left"} size={"1x"} /> :
+                        <FontAwesomeIcon icon={"angle-double-right"} size={"1x"} />}
             </div>
         </>;
     }
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index a0f6ad9c7..82aa3dbd5 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -64,7 +64,7 @@ export enum CollectionViewType {
     Multirow = "multirow",
     Time = "time",
     Carousel = "carousel",
-    Carousel3D = "3D carousel",
+    Carousel3D = "3D Carousel",
     Linear = "linear",
     Staff = "staff",
     Map = "map",
-- 
cgit v1.2.3-70-g09d2


From 633c62652ad7cef151c68d0cf6e2c420ed07de87 Mon Sep 17 00:00:00 2001
From: Melissa Zhang <mzhang19096@gmail.com>
Date: Thu, 4 Jun 2020 22:34:59 -0700
Subject: show autoscroll button on arrow click, then fade away after a while
 if it's not clicked

---
 .../collections/CollectionCarousel3DView.scss      | 40 +++++++++++----
 .../views/collections/CollectionCarousel3DView.tsx | 60 +++++++++++-----------
 2 files changed, 58 insertions(+), 42 deletions(-)

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

diff --git a/src/client/views/collections/CollectionCarousel3DView.scss b/src/client/views/collections/CollectionCarousel3DView.scss
index ff63f4116..5f8895c1f 100644
--- a/src/client/views/collections/CollectionCarousel3DView.scss
+++ b/src/client/views/collections/CollectionCarousel3DView.scss
@@ -32,8 +32,8 @@
 
     .dot,
     .dot-active {
-        height: 15px;
-        width: 15px;
+        height: 10px;
+        width: 10px;
         border-radius: 50%;
         margin: 3px;
         display: inline-block;
@@ -49,7 +49,9 @@
 .carousel3DView-back,
 .carousel3DView-fwd,
 .carousel3DView-back-scroll,
-.carousel3DView-fwd-scroll {
+.carousel3DView-fwd-scroll,
+.carousel3DView-back-scroll-hidden,
+.carousel3DView-fwd-scroll-hidden {
     position: absolute;
     display: flex;
     width: 30;
@@ -61,24 +63,40 @@
     cursor: pointer;
 }
 
-.carousel3DView-fwd {
+.carousel3DView-fwd,
+.carousel3DView-back {
     top: 50%;
+}
+
+.carousel3DView-fwd-scroll,
+.carousel3DView-back-scroll,
+.carousel3DView-fwd-scroll-hidden,
+.carousel3DView-back-scroll-hidden {
+    top: calc(50% - 30px);
+}
+
+.carousel3DView-fwd,
+.carousel3DView-fwd-scroll,
+.carousel3DView-fwd-scroll-hidden {
     right: 0;
 }
 
-.carousel3DView-back {
-    top: 50%;
+.carousel3DView-back,
+.carousel3DView-back-scroll,
+.carousel3DView-back-scroll-hidden {
     left: 0;
 }
 
-.carousel3DView-fwd-scroll {
-    top: calc(50% - 30px);
-    right: 0;
+.carousel3DView-fwd-scroll-hidden,
+.carousel3DView-back-scroll-hidden {
+    opacity: 0;
+    transition: opacity 0.5s linear;
+    pointer-events: none;
 }
 
+.carousel3DView-fwd-scroll,
 .carousel3DView-back-scroll {
-    top: calc(50% - 30px);
-    left: 0;
+    opacity: 1;
 }
 
 .carousel3DView-back:hover,
diff --git a/src/client/views/collections/CollectionCarousel3DView.tsx b/src/client/views/collections/CollectionCarousel3DView.tsx
index 1fa96df65..a7d9c41c8 100644
--- a/src/client/views/collections/CollectionCarousel3DView.tsx
+++ b/src/client/views/collections/CollectionCarousel3DView.tsx
@@ -46,8 +46,7 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume
                 onClick={ScriptField.MakeScript(
                     "child._showCaption = 'caption'",
                     { child: Doc.name },
-                    { child: childPair.layout }
-                )}
+                    { child: childPair.layout })}
                 renderDepth={this.props.renderDepth + 1}
                 LayoutTemplate={this.props.ChildLayoutTemplate}
                 LayoutTemplateString={this.props.ChildLayoutString}
@@ -61,17 +60,16 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume
             />;
         };
 
-        return (
-            this.childLayoutPairs.map((childPair, index) => {
-                return (
-                    <div key={childPair.layout[Id]}
-                        className={`collectionCarousel3DView-item${index === currentIndex ? "-active" : ""} ${index}`}
-                        style={index === currentIndex ?
-                            { opacity: '1', transform: 'scale(1.3)' } :
-                            { opacity: '0.5', transform: 'scale(0.6)', userSelect: 'none' }}>
-                        {displayDoc(childPair)}
-                    </div>);
-            }));
+        return (this.childLayoutPairs.map((childPair, index) => {
+            return (
+                <div key={childPair.layout[Id]}
+                    className={`collectionCarousel3DView-item${index === currentIndex ? "-active" : ""} ${index}`}
+                    style={index === currentIndex ?
+                        { opacity: '1', transform: 'scale(1.3)' } :
+                        { opacity: '0.5', transform: 'scale(0.6)', userSelect: 'none' }}>
+                    {displayDoc(childPair)}
+                </div>);
+        }));
     }
 
     changeSlide = (direction: number) => {
@@ -81,6 +79,8 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume
     onArrowClick = (e: React.MouseEvent, direction: number) => {
         e.stopPropagation();
         this.changeSlide(direction);
+        !this.layoutDoc.autoScrollOn && (this.layoutDoc.showScrollButton = (direction === 1) ? "fwd" : "back"); // while autoscroll is on, keep the other autoscroll button hidden
+        !this.layoutDoc.autoScrollOn && this.fadeScrollButton(); // keep pause button visible while autoscroll is on
     }
 
     interval?: number;
@@ -93,6 +93,7 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume
     stopAutoScroll = () => {
         window.clearInterval(this.interval);
         this.interval = undefined;
+        this.fadeScrollButton();
     }
 
     toggleAutoScroll = (direction: number) => {
@@ -100,10 +101,10 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume
         this.layoutDoc.autoScrollOn ? this.startAutoScroll(direction) : this.stopAutoScroll();
     }
 
-    showAutoScrollButton = (direction: string) => {
-        // keep pause button visible while autoscroll is on, and don't show the other side's autoscroll button
-        !this.layoutDoc.autoScrollOn && (this.layoutDoc.showScrollButton = direction);
-
+    fadeScrollButton = () => {
+        window.setTimeout(() => {
+            !this.layoutDoc.autoScrollOn && (this.layoutDoc.showScrollButton = "none"); //fade away after 1.5s if it's not clicked.
+        }, 1500);
     }
 
     onContextMenu = (e: React.MouseEvent): void => {
@@ -142,15 +143,15 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume
 
     @computed get buttons() {
         if (!this.props.active()) return null;
-        return <div className="arrow-buttons" onMouseLeave={() => this.showAutoScrollButton("none")}>
+        return <div className="arrow-buttons" >
             <div key="back" className="carousel3DView-back" style={{ background: `${StrCast(this.props.Document.backgroundColor)}` }}
                 onClick={(e) => this.onArrowClick(e, -1)}
-                onMouseEnter={() => this.showAutoScrollButton("back")}>
+            >
                 <FontAwesomeIcon icon={"angle-left"} size={"2x"} />
             </div>
             <div key="fwd" className="carousel3DView-fwd" style={{ background: `${StrCast(this.props.Document.backgroundColor)}` }}
                 onClick={(e) => this.onArrowClick(e, 1)}
-                onMouseEnter={() => this.showAutoScrollButton("fwd")}>
+            >
                 <FontAwesomeIcon icon={"angle-right"} size={"2x"} />
             </div>
             {this.autoScrollButton}
@@ -158,18 +159,15 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume
     }
 
     @computed get autoScrollButton() {
-        const direction = this.layoutDoc.showScrollButton;
-        if (direction !== "back" && direction !== "fwd") return null;
-
-        const offset = (direction === "back") ? -1 : 1;
+        const whichButton = this.layoutDoc.showScrollButton;
         return <>
-            <div className={`carousel3DView-${direction}-scroll`} style={{ background: `${StrCast(this.props.Document.backgroundColor)}` }}
-                onClick={() => this.toggleAutoScroll(offset)}>
-                {this.layoutDoc.autoScrollOn ?
-                    <FontAwesomeIcon icon={"pause"} size={"1x"} /> :
-                    direction === "back" ?
-                        <FontAwesomeIcon icon={"angle-double-left"} size={"1x"} /> :
-                        <FontAwesomeIcon icon={"angle-double-right"} size={"1x"} />}
+            <div className={`carousel3DView-back-scroll${whichButton === "back" ? "" : "-hidden"}`} style={{ background: `${StrCast(this.props.Document.backgroundColor)}` }}
+                onClick={() => this.toggleAutoScroll(-1)}>
+                {this.layoutDoc.autoScrollOn ? <FontAwesomeIcon icon={"pause"} size={"1x"} /> : <FontAwesomeIcon icon={"angle-double-left"} size={"1x"} />}
+            </div>
+            <div className={`carousel3DView-fwd-scroll${whichButton === "fwd" ? "" : "-hidden"}`} style={{ background: `${StrCast(this.props.Document.backgroundColor)}` }}
+                onClick={() => this.toggleAutoScroll(1)}>
+                {this.layoutDoc.autoScrollOn ? <FontAwesomeIcon icon={"pause"} size={"1x"} /> : <FontAwesomeIcon icon={"angle-double-right"} size={"1x"} />}
             </div>
         </>;
     }
-- 
cgit v1.2.3-70-g09d2


From bcb2e70a5cd4628dd2909279ec61c4c644e07c37 Mon Sep 17 00:00:00 2001
From: Melissa Zhang <mzhang19096@gmail.com>
Date: Fri, 5 Jun 2020 19:35:32 -0700
Subject: minor fixes

---
 src/client/views/collections/CollectionCarousel3DView.tsx | 5 +++--
 src/client/views/collections/CollectionViewChromes.scss   | 2 +-
 2 files changed, 4 insertions(+), 3 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 a7d9c41c8..1344b70f4 100644
--- a/src/client/views/collections/CollectionCarousel3DView.tsx
+++ b/src/client/views/collections/CollectionCarousel3DView.tsx
@@ -1,9 +1,9 @@
-import { observable, computed } from 'mobx';
+import { computed } from 'mobx';
 import { observer } from 'mobx-react';
 import * as React from 'react';
 import { documentSchema, collectionSchema } from '../../../fields/documentSchemas';
 import { makeInterface } from '../../../fields/Schema';
-import { NumCast, StrCast, ScriptCast, Cast } from '../../../fields/Types';
+import { NumCast, StrCast, ScriptCast } from '../../../fields/Types';
 import { DragManager } from '../../util/DragManager';
 import { ContentFittingDocumentView } from '../nodes/ContentFittingDocumentView';
 import "./CollectionCarousel3DView.scss";
@@ -86,6 +86,7 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume
     interval?: number;
     startAutoScroll = (direction: number) => {
         this.interval = window.setInterval(() => {
+            console.log(this.interval, this.scrollSpeed);
             this.changeSlide(direction);
         }, this.scrollSpeed);
     }
diff --git a/src/client/views/collections/CollectionViewChromes.scss b/src/client/views/collections/CollectionViewChromes.scss
index b98dab707..2ab771089 100644
--- a/src/client/views/collections/CollectionViewChromes.scss
+++ b/src/client/views/collections/CollectionViewChromes.scss
@@ -226,7 +226,7 @@
                 .editableView-container-editing {
                     margin: auto;
                     border: 0px;
-                    color: grey;
+                    color: grey !important;
                     text-align: center;
                     letter-spacing: 2px;
                     outline-color: black;
-- 
cgit v1.2.3-70-g09d2

