diff options
Diffstat (limited to 'src/client/views')
-rw-r--r-- | src/client/views/collections/CollectionCarousel3DView.scss | 68 | ||||
-rw-r--r-- | src/client/views/collections/CollectionCarousel3DView.tsx | 125 |
2 files changed, 193 insertions, 0 deletions
diff --git a/src/client/views/collections/CollectionCarousel3DView.scss b/src/client/views/collections/CollectionCarousel3DView.scss new file mode 100644 index 000000000..2142eca39 --- /dev/null +++ b/src/client/views/collections/CollectionCarousel3DView.scss @@ -0,0 +1,68 @@ +.collectionCarouselView-outer { + background: white; + height: 100%; + + .collectionCarouselView-center-container { + width: 70%; + 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; + } + } + + .collectionCarouselView-prev { + position: absolute; + height: 50%; + width: 50%; + background-color: lightgrey; + left: 0; + top: 25%; + } + + .collectionCarouselView-next { + position: absolute; + height: 50%; + width: 50%; + background-color: lightgrey; + right: 0; + top: 25%; + } +} + +.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; +}
\ 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..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 |