aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/collections/CollectionCarouselView.tsx
blob: 9c370bfbbcf1b6d8294794a62d7033d9f4d26f3d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { computed, makeObservable } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
import { StopEvent, emptyFunction, returnFalse, returnOne, returnZero } from '../../../Utils';
import { Doc, Opt } from '../../../fields/Doc';
import { DocCast, NumCast, ScriptCast, StrCast } from '../../../fields/Types';
import { DragManager } from '../../util/DragManager';
import { StyleProp } from '../StyleProvider';
import { DocumentView } from '../nodes/DocumentView';
import { FieldViewProps } from '../nodes/FieldView';
import { FormattedTextBox } from '../nodes/formattedText/FormattedTextBox';
import './CollectionCarouselView.scss';
import { CollectionSubView } from './CollectionSubView';
import { DocumentType } from '../../documents/DocumentTypes';

@observer
export class CollectionCarouselView extends CollectionSubView() {
    private _dropDisposer?: DragManager.DragDropDisposer;

    constructor(props: any) {
        super(props);
        makeObservable(this);
    }

    componentWillUnmount() {
        this._dropDisposer?.();
    }

    protected createDashEventsTarget = (ele: HTMLDivElement | null) => {
        this._dropDisposer?.();
        if (ele) {
            this._dropDisposer = DragManager.MakeDropTarget(ele, this.onInternalDrop.bind(this), this.layoutDoc);
        }
    };

    @computed get carouselItems() {
        return this.childLayoutPairs.filter(pair => pair.layout.type !== DocumentType.LINK);
    }

    advance = (e: React.MouseEvent) => {
        e.stopPropagation();
        this.layoutDoc._carousel_index = (NumCast(this.layoutDoc._carousel_index) + 1) % this.carouselItems.length;
    };
    goback = (e: React.MouseEvent) => {
        e.stopPropagation();
        this.layoutDoc._carousel_index = (NumCast(this.layoutDoc._carousel_index) - 1 + this.carouselItems.length) % this.carouselItems.length;
    };
    captionStyleProvider = (doc: Doc | undefined, captionProps: Opt<FieldViewProps>, property: string): any => {
        // first look for properties on the document in the carousel, then fallback to properties on the container
        const childValue = doc?.['caption-' + property] ? this._props.styleProvider?.(doc, captionProps, property) : undefined;
        return childValue ?? this._props.styleProvider?.(this.layoutDoc, captionProps, property);
    };
    panelHeight = () => this._props.PanelHeight() - (StrCast(this.layoutDoc._layout_showCaption) ? 50 : 0);
    onContentDoubleClick = () => ScriptCast(this.layoutDoc.onChildDoubleClick);
    onContentClick = () => ScriptCast(this.layoutDoc.onChildClick);
    @computed get marginX() {
        return NumCast(this.layoutDoc.caption_xMargin, 50);
    }
    captionWidth = () => this._props.PanelWidth() - 2 * this.marginX;
    @computed get content() {
        const index = NumCast(this.layoutDoc._carousel_index);
        const curDoc = this.carouselItems?.[index];
        const captionProps = { ...this._props, NativeScaling: returnOne, PanelWidth: this.captionWidth, fieldKey: 'caption', setHeight: undefined, setContentView: undefined };
        const carouselShowsCaptions = StrCast(this.layoutDoc._layout_showCaption);
        return !(curDoc?.layout instanceof Doc) ? null : (
            <>
                <div className="collectionCarouselView-image" key="image">
                    <DocumentView
                        {...this._props}
                        NativeWidth={returnZero}
                        NativeHeight={returnZero}
                        layout_fitWidth={undefined}
                        setContentViewBox={undefined}
                        onDoubleClickScript={this.onContentDoubleClick}
                        onClickScript={this.onContentClick}
                        isDocumentActive={this._props.childDocumentsActive?.() ? this._props.isDocumentActive : this._props.isContentActive}
                        isContentActive={this._props.childContentsActive ?? this._props.isContentActive() === false ? returnFalse : emptyFunction}
                        hideCaptions={!!carouselShowsCaptions} // hide captions if the carousel is configured to show the captions
                        renderDepth={this._props.renderDepth + 1}
                        LayoutTemplate={this._props.childLayoutTemplate}
                        LayoutTemplateString={this._props.childLayoutString}
                        Document={curDoc.layout}
                        TemplateDataDocument={DocCast(curDoc.layout.resolvedDataDoc)}
                        PanelHeight={this.panelHeight}
                    />
                </div>
                {!carouselShowsCaptions ? null : (
                    <div
                        className="collectionCarouselView-caption"
                        key="caption"
                        onWheel={StopEvent}
                        style={{
                            borderRadius: this._props.styleProvider?.(this.layoutDoc, captionProps, StyleProp.BorderRounding),
                            marginRight: this.marginX,
                            marginLeft: this.marginX,
                            width: `calc(100% - ${this.marginX * 2}px)`,
                        }}>
                        <FormattedTextBox key={index} {...captionProps} fieldKey={carouselShowsCaptions} styleProvider={this.captionStyleProvider} Document={curDoc.layout} TemplateDataDocument={undefined} />
                    </div>
                )}
            </>
        );
    }
    @computed get buttons() {
        return (
            <>
                <div key="back" className="carouselView-back" onClick={this.goback}>
                    <FontAwesomeIcon icon={'chevron-left'} size={'2x'} />
                </div>
                <div key="fwd" className="carouselView-fwd" onClick={this.advance}>
                    <FontAwesomeIcon icon={'chevron-right'} size={'2x'} />
                </div>
            </>
        );
    }

    render() {
        return (
            <div
                className="collectionCarouselView-outer"
                ref={this.createDashEventsTarget}
                style={{
                    background: this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.BackgroundColor),
                    color: this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.Color),
                }}>
                {this.content}
                {this.Document._chromeHidden ? null : this.buttons}
            </div>
        );
    }
}