aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/client/documents/Documents.ts4
-rw-r--r--src/client/views/.DS_Storebin6148 -> 6148 bytes
-rw-r--r--src/client/views/collections/CollectionCarousel3DView.scss37
-rw-r--r--src/client/views/collections/CollectionCarousel3DView.tsx144
-rw-r--r--src/client/views/collections/CollectionView.tsx4
-rw-r--r--src/client/views/collections/CollectionViewChromes.tsx1
6 files changed, 190 insertions, 0 deletions
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index b4c11a81b..ef37bc62f 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -678,6 +678,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/.DS_Store b/src/client/views/.DS_Store
index 5008ddfcf..3717a2923 100644
--- a/src/client/views/.DS_Store
+++ b/src/client/views/.DS_Store
Binary files differ
diff --git a/src/client/views/collections/CollectionCarousel3DView.scss b/src/client/views/collections/CollectionCarousel3DView.scss
new file mode 100644
index 000000000..7da007ef3
--- /dev/null
+++ b/src/client/views/collections/CollectionCarousel3DView.scss
@@ -0,0 +1,37 @@
+.collectionCarouselView-outer {
+ background: white;
+ height: 100%;
+ perspective: 30em;
+
+ .collectionCarouselView-image {
+ position: absolute;
+ height: 100%;
+ 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)
+ }
+
+ .collectionCarouselView-next {
+ position: absolute;
+ height: 50%;
+ width: 25%;
+ right: 0;
+ top: 25%;
+ 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
new file mode 100644
index 000000000..649ca4eba
--- /dev/null
+++ b/src/client/views/collections/CollectionCarousel3DView.tsx
@@ -0,0 +1,144 @@
+import { observable, 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 { DragManager } from '../../util/DragManager';
+import { ContentFittingDocumentView } from '../nodes/ContentFittingDocumentView';
+import "./CollectionCarousel3DView.scss";
+import { CollectionSubView } from './CollectionSubView';
+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);
+
+@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);
+ }
+ }
+
+ @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;
+ const nextIndex = (index + 1 + this.childLayoutPairs.length) % this.childLayoutPairs.length;
+ return !(this.childLayoutPairs?.[index]?.layout instanceof Doc) ? (null) :
+ <>
+ <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}
+ />
+ </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}
+ />
+ </div>
+ <div className="collectionCarouselView-image" key="image">
+ <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.props.PanelHeight}
+ ScreenToLocalTransform={this.props.ScreenToLocalTransform}
+ bringToFront={returnFalse}
+ parentActive={this.props.active}
+ />
+ </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}
+ </div>;
+ }
+} \ No newline at end of file
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index ee4755355..191bbba3a 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",
@@ -182,6 +184,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} />); }
@@ -221,6 +224,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 [];
}