aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--package-lock.json84
-rw-r--r--src/client/documents/Documents.ts4
-rw-r--r--src/client/views/.DS_Storebin6148 -> 6148 bytes
-rw-r--r--src/client/views/DocumentDecorations.tsx7
-rw-r--r--src/client/views/collections/CollectionCarousel3DView.scss107
-rw-r--r--src/client/views/collections/CollectionCarousel3DView.tsx197
-rw-r--r--src/client/views/collections/CollectionView.tsx4
-rw-r--r--src/client/views/collections/CollectionViewChromes.scss17
-rw-r--r--src/client/views/collections/CollectionViewChromes.tsx41
9 files changed, 421 insertions, 40 deletions
diff --git a/package-lock.json b/package-lock.json
index b2abac245..69e8b19f5 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -2838,7 +2838,8 @@
},
"ansi-regex": {
"version": "2.1.1",
- "bundled": true
+ "bundled": true,
+ "optional": true
},
"aproba": {
"version": "1.2.0",
@@ -2856,11 +2857,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"
@@ -2873,15 +2876,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",
@@ -2984,7 +2990,8 @@
},
"inherits": {
"version": "2.0.4",
- "bundled": true
+ "bundled": true,
+ "optional": true
},
"ini": {
"version": "1.3.5",
@@ -2994,6 +3001,7 @@
"is-fullwidth-code-point": {
"version": "1.0.0",
"bundled": true,
+ "optional": true,
"requires": {
"number-is-nan": "^1.0.0"
}
@@ -3006,17 +3014,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"
@@ -3033,6 +3044,7 @@
"mkdirp": {
"version": "0.5.3",
"bundled": true,
+ "optional": true,
"requires": {
"minimist": "^1.2.5"
}
@@ -3088,7 +3100,8 @@
},
"npm-normalize-package-bin": {
"version": "1.0.1",
- "bundled": true
+ "bundled": true,
+ "optional": true
},
"npm-packlist": {
"version": "1.4.8",
@@ -3113,7 +3126,8 @@
},
"number-is-nan": {
"version": "1.0.1",
- "bundled": true
+ "bundled": true,
+ "optional": true
},
"object-assign": {
"version": "4.1.1",
@@ -3123,6 +3137,7 @@
"once": {
"version": "1.4.0",
"bundled": true,
+ "optional": true,
"requires": {
"wrappy": "1"
}
@@ -3191,7 +3206,8 @@
},
"safe-buffer": {
"version": "5.1.2",
- "bundled": true
+ "bundled": true,
+ "optional": true
},
"safer-buffer": {
"version": "2.1.2",
@@ -3221,6 +3237,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",
@@ -3238,6 +3255,7 @@
"strip-ansi": {
"version": "3.0.1",
"bundled": true,
+ "optional": true,
"requires": {
"ansi-regex": "^2.0.0"
}
@@ -3276,11 +3294,13 @@
},
"wrappy": {
"version": "1.0.2",
- "bundled": true
+ "bundled": true,
+ "optional": true
},
"yallist": {
"version": "3.1.1",
- "bundled": true
+ "bundled": true,
+ "optional": true
}
}
}
@@ -9517,7 +9537,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": {
@@ -9823,7 +9843,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": {
@@ -10322,7 +10342,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",
@@ -10410,7 +10430,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": {
@@ -10546,7 +10566,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"
@@ -10622,7 +10642,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": {
@@ -11131,7 +11151,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"
@@ -11139,7 +11159,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=="
}
}
@@ -11191,7 +11211,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",
@@ -11305,7 +11325,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",
@@ -11325,7 +11345,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",
@@ -11335,7 +11355,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",
@@ -11770,7 +11790,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",
@@ -11781,7 +11801,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=="
}
}
@@ -11840,7 +11860,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",
@@ -11861,7 +11881,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",
@@ -11925,7 +11945,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"
@@ -12224,7 +12244,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"
@@ -12232,7 +12252,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=="
}
}
@@ -12544,7 +12564,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/documents/Documents.ts b/src/client/documents/Documents.ts
index dac3a1aaa..b642e18ab 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -710,6 +710,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.length ? schemaColumns : [new SchemaHeaderField("title", "#f1efeb")]), ...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/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 9b3c16a59..0d4667135 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
new file mode 100644
index 000000000..5f8895c1f
--- /dev/null
+++ b/src/client/views/collections/CollectionCarousel3DView.scss
@@ -0,0 +1,107 @@
+.collectionCarousel3DView-outer {
+ height: 100%;
+ position: relative;
+ background-color: white;
+}
+
+.carousel-wrapper {
+ display: flex;
+ position: absolute;
+ top: 15%;
+ align-items: center;
+ transition: transform 0.3s cubic-bezier(0.455, 0.03, 0.515, 0.955);
+
+ .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;
+ }
+
+ .collectionCarousel3DView-item-active {
+ pointer-events: unset;
+ }
+}
+
+.dot-bar {
+ display: flex;
+ position: absolute;
+ justify-content: center;
+ bottom: 5%;
+ width: 100%;
+
+ .dot,
+ .dot-active {
+ height: 10px;
+ width: 10px;
+ border-radius: 50%;
+ margin: 3px;
+ display: inline-block;
+ background-color: lightgrey;
+ cursor: pointer;
+ }
+
+ .dot-active {
+ background-color: grey;
+ }
+}
+
+.carousel3DView-back,
+.carousel3DView-fwd,
+.carousel3DView-back-scroll,
+.carousel3DView-fwd-scroll,
+.carousel3DView-back-scroll-hidden,
+.carousel3DView-fwd-scroll-hidden {
+ 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,
+.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,
+.carousel3DView-back-scroll,
+.carousel3DView-back-scroll-hidden {
+ left: 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 {
+ opacity: 1;
+}
+
+.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
new file mode 100644
index 000000000..1344b70f4
--- /dev/null
+++ b/src/client/views/collections/CollectionCarousel3DView.tsx
@@ -0,0 +1,197 @@
+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 } 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, 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);
+
+@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?.(); }
+
+ 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);
+ }
+ }
+
+ 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 }) => {
+ return <ContentFittingDocumentView {...this.props}
+ onDoubleClick={ScriptCast(this.layoutDoc.onChildDoubleClick)}
+ 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}
+ Document={childPair.layout}
+ DataDoc={childPair.data}
+ PanelWidth={this.panelWidth}
+ PanelHeight={this.panelHeight}
+ ScreenToLocalTransform={this.props.ScreenToLocalTransform}
+ bringToFront={returnFalse}
+ parentActive={this.props.active}
+ />;
+ };
+
+ 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) => {
+ this.layoutDoc._itemIndex = (NumCast(this.layoutDoc._itemIndex) + direction + this.childLayoutPairs.length) % this.childLayoutPairs.length;
+ }
+
+ 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;
+ startAutoScroll = (direction: number) => {
+ this.interval = window.setInterval(() => {
+ console.log(this.interval, this.scrollSpeed);
+ this.changeSlide(direction);
+ }, this.scrollSpeed);
+ }
+
+ stopAutoScroll = () => {
+ window.clearInterval(this.interval);
+ this.interval = undefined;
+ this.fadeScrollButton();
+ }
+
+ toggleAutoScroll = (direction: number) => {
+ this.layoutDoc.autoScrollOn = this.layoutDoc.autoScrollOn ? false : true;
+ this.layoutDoc.autoScrollOn ? this.startAutoScroll(direction) : this.stopAutoScroll();
+ }
+
+ 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 => {
+ // 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;
+ }
+ }
+
+ @computed get buttons() {
+ if (!this.props.active()) return null;
+ return <div className="arrow-buttons" >
+ <div key="back" className="carousel3DView-back" style={{ background: `${StrCast(this.props.Document.backgroundColor)}` }}
+ onClick={(e) => this.onArrowClick(e, -1)}
+ >
+ <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)}
+ >
+ <FontAwesomeIcon icon={"angle-right"} size={"2x"} />
+ </div>
+ {this.autoScrollButton}
+ </div>;
+ }
+
+ @computed get autoScrollButton() {
+ const whichButton = this.layoutDoc.showScrollButton;
+ return <>
+ <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>
+ </>;
+ }
+
+ @computed get dots() {
+ return (this.childLayoutPairs.map((_child, index) => {
+ return <div key={Utils.GenerateGuid()} className={`dot${index === NumCast(this.layoutDoc._itemIndex) ? "-active" : ""}`}
+ onClick={() => this.layoutDoc._itemIndex = index} />;
+ }));
+ }
+
+ render() {
+ const index = NumCast(this.layoutDoc._itemIndex);
+ const translateX = (1 - index) / this.childLayoutPairs.length * 100;
+
+ 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>
+ {this.props.Document._chromeStatus !== "replaced" ? this.buttons : (null)}
+ <div className="dot-bar">
+ {this.dots}
+ </div>
+ </div>;
+ }
+} \ No newline at end of file
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index 508b9e5e7..78b70b5fa 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -28,6 +28,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';
@@ -66,6 +67,7 @@ export enum CollectionViewType {
Multirow = "multirow",
Time = "time",
Carousel = "carousel",
+ Carousel3D = "3D Carousel",
Linear = "linear",
Staff = "staff",
Map = "map",
@@ -204,6 +206,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} />); }
@@ -244,6 +247,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" });
subItems.push({ description: "Grid", event: () => func(CollectionViewType.Grid), icon: "th-list" });
diff --git a/src/client/views/collections/CollectionViewChromes.scss b/src/client/views/collections/CollectionViewChromes.scss
index 77a12ed37..2885ac763 100644
--- a/src/client/views/collections/CollectionViewChromes.scss
+++ b/src/client/views/collections/CollectionViewChromes.scss
@@ -169,7 +169,8 @@
}
.collectionStackingViewChrome-cont,
- .collectionTreeViewChrome-cont {
+ .collectionTreeViewChrome-cont,
+ .collection3DCarouselViewChrome-cont {
display: flex;
justify-content: space-between;
}
@@ -234,21 +235,24 @@
.collectionStackingViewChrome-pivotField-cont,
- .collectionTreeViewChrome-pivotField-cont {
+ .collectionTreeViewChrome-pivotField-cont,
+ .collection3DCarouselViewChrome-scrollSpeed-cont {
justify-self: right;
display: flex;
font-size: 75%;
letter-spacing: 2px;
.collectionStackingViewChrome-pivotField-label,
- .collectionTreeViewChrome-pivotField-label {
+ .collectionTreeViewChrome-pivotField-label,
+ .collection3DCarouselViewChrome-scrollSpeed-label {
vertical-align: center;
padding-left: 10px;
margin: auto;
}
.collectionStackingViewChrome-pivotField,
- .collectionTreeViewChrome-pivotField {
+ .collectionTreeViewChrome-pivotField,
+ .collection3DCarouselViewChrome-scrollSpeed {
color: white;
width: 100%;
min-width: 100px;
@@ -262,7 +266,7 @@
.editableView-container-editing {
margin: auto;
border: 0px;
- color: grey;
+ color: grey !important;
text-align: center;
letter-spacing: 2px;
outline-color: black;
@@ -278,7 +282,8 @@
}
.collectionStackingViewChrome-pivotField:hover,
- .collectionTreeViewChrome-pivotField:hover {
+ .collectionTreeViewChrome-pivotField:hover,
+ .collection3DCarouselViewChrome-scrollSpeed:hover {
cursor: text;
}
diff --git a/src/client/views/collections/CollectionViewChromes.tsx b/src/client/views/collections/CollectionViewChromes.tsx
index 52fb63386..31a086d93 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 [];
}
@@ -200,6 +201,7 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewChro
case CollectionViewType.Schema: return (<CollectionSchemaViewChrome key="collchrome" PanelWidth={this.props.PanelWidth} CollectionView={this.props.CollectionView} type={this.props.type} />);
case CollectionViewType.Tree: return (<CollectionTreeViewChrome key="collchrome" PanelWidth={this.props.PanelWidth} CollectionView={this.props.CollectionView} type={this.props.type} />);
case CollectionViewType.Masonry: return (<CollectionStackingViewChrome key="collchrome" PanelWidth={this.props.PanelWidth} CollectionView={this.props.CollectionView} type={this.props.type} />);
+ case CollectionViewType.Carousel3D: return (<Collection3DCarouselViewChrome key="collchrome" PanelWidth={this.props.PanelWidth} CollectionView={this.props.CollectionView} type={this.props.type} />);
case CollectionViewType.Grid: return (<CollectionGridViewChrome key="collchrome" PanelWidth={this.props.PanelWidth} CollectionView={this.props.CollectionView} type={this.props.type} />);
default: return null;
}
@@ -561,6 +563,43 @@ export class CollectionTreeViewChrome extends React.Component<CollectionViewChro
}
}
+// Enter scroll speed for 3D Carousel
+@observer
+export class Collection3DCarouselViewChrome extends React.Component<CollectionViewChromeProps> {
+ @computed get scrollSpeed() {
+ return this.props.CollectionView.props.Document._autoScrollSpeed;
+ }
+
+ @action
+ setValue = (value: string) => {
+ const numValue = Number(StrCast(value));
+ if (numValue > 0) {
+ this.props.CollectionView.props.Document._autoScrollSpeed = numValue;
+ return true;
+ }
+ return false;
+ }
+
+ render() {
+ return (
+ <div className="collection3DCarouselViewChrome-cont">
+ <div className="collection3DCarouselViewChrome-scrollSpeed-cont">
+ <div className="collectionStackingViewChrome-scrollSpeed-label">
+ AUTOSCROLL SPEED:
+ </div>
+ <div className="collection3DCarouselViewChrome-scrollSpeed">
+ <EditableView
+ GetValue={() => StrCast(this.scrollSpeed)}
+ oneLine
+ SetValue={this.setValue}
+ contents={this.scrollSpeed ? this.scrollSpeed : 1000} />
+ </div>
+ </div>
+ </div>
+ );
+ }
+}
+
/**
* Chrome for grid view.
*/
@@ -738,4 +777,4 @@ export class CollectionGridViewChrome extends React.Component<CollectionViewChro
</div>
);
}
-} \ No newline at end of file
+}