aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/nodes/LabelBox.tsx
blob: 0015f0b71f5716c2224a0101fe6d9ae4258b0639 (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
import { action, computed, observable } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
import { Doc, DocListCast } from '../../../fields/Doc';
import { List } from '../../../fields/List';
import { listSpec } from '../../../fields/Schema';
import { Cast, StrCast } from '../../../fields/Types';
import { DragManager } from '../../util/DragManager';
import { undoBatch } from '../../util/UndoManager';
import { ContextMenu } from '../ContextMenu';
import { ContextMenuProps } from '../ContextMenuItem';
import { ViewBoxBaseComponent } from '../DocComponent';
import { StyleProp } from '../StyleProvider';
import { FieldView, FieldViewProps } from './FieldView';
import BigText from './LabelBigText';
import './LabelBox.scss';


export interface LabelBoxProps {
    label?: string;
}

@observer
export class LabelBox extends ViewBoxBaseComponent<(FieldViewProps & LabelBoxProps)>() {
    public static LayoutString(fieldKey: string) { return FieldView.LayoutString(LabelBox, fieldKey); }
    public static LayoutStringWithTitle(fieldType: { name: string }, fieldStr: string, label: string) {
        return `<${fieldType.name} fieldKey={'${fieldStr}'} label={'${label}'} {...props} />`;  //e.g., "<ImageBox {...props} fieldKey={"data} />"
    }
    private dropDisposer?: DragManager.DragDropDisposer;

    componentDidMount() {
        this.props.setContentView?.(this);
    }

    getTitle() {
        return this.rootDoc["title-custom"] ? StrCast(this.rootDoc.title) : this.props.label ? this.props.label :
            typeof this.rootDoc[this.fieldKey] === "string" ? StrCast(this.rootDoc[this.fieldKey]) : StrCast(this.rootDoc.title);
    }

    protected createDropTarget = (ele: HTMLDivElement) => {
        this.dropDisposer?.();
        if (ele) {
            this.dropDisposer = DragManager.MakeDropTarget(ele, this.drop.bind(this), this.props.Document);
        }
    }

    get paramsDoc() { return Doc.AreProtosEqual(this.layoutDoc, this.dataDoc) ? this.dataDoc : this.layoutDoc; }
    specificContextMenu = (e: React.MouseEvent): void => {
        const funcs: ContextMenuProps[] = [];
        !Doc.UserDoc().noviceMode && funcs.push({
            description: "Clear Script Params", event: () => {
                const params = Cast(this.paramsDoc["onClick-paramFieldKeys"], listSpec("string"), []);
                params?.map(p => this.paramsDoc[p] = undefined);
            }, icon: "trash"
        });

        funcs.length && ContextMenu.Instance.addItem({ description: "OnClick...", noexpand: true, subitems: funcs, icon: "mouse-pointer" });
    }

    @undoBatch
    @action
    drop = (e: Event, de: DragManager.DropEvent) => {
        const docDragData = de.complete.docDragData;
        const params = Cast(this.paramsDoc["onClick-paramFieldKeys"], listSpec("string"), []);
        const missingParams = params?.filter(p => !this.paramsDoc[p]);
        if (docDragData && missingParams?.includes((e.target as any).textContent)) {
            this.paramsDoc[(e.target as any).textContent] = new List<Doc>(docDragData.droppedDocuments.map((d, i) =>
                d.onDragStart ? docDragData.draggedDocuments[i] : d));
            e.stopPropagation();
        }
    }

    @observable _mouseOver = false;
    @computed get hoverColor() { return this._mouseOver ? StrCast(this.layoutDoc._hoverBackgroundColor) : "unset"; }

    // (!missingParams || !missingParams.length ? "" : "(" + missingParams.map(m => m + ":").join(" ") + ")")
    render() {
        const params = Cast(this.paramsDoc["onClick-paramFieldKeys"], listSpec("string"), []);
        const missingParams = params?.filter(p => !this.paramsDoc[p]);
        params?.map(p => DocListCast(this.paramsDoc[p])); // bcz: really hacky form of prefetching ...
        const label = this.getTitle();
        return (
            <div className="labelBox-outerDiv"
                onMouseLeave={action(() => this._mouseOver = false)}
                onMouseOver={action(() => this._mouseOver = true)}
                ref={this.createDropTarget} onContextMenu={this.specificContextMenu}
                style={{ boxShadow: this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.BoxShadow) }}>
                <div className="labelBox-mainButton" style={{
                    backgroundColor: this.hoverColor,
                    fontSize: StrCast(this.layoutDoc._fontSize),
                    fontFamily: StrCast(this.layoutDoc._fontFamily) || "inherit",
                    letterSpacing: StrCast(this.layoutDoc.letterSpacing),
                    textTransform: StrCast(this.layoutDoc.textTransform) as any,
                    width: this.props.PanelWidth(),
                    height: this.props.PanelHeight(),
                    whiteSpace: this.layoutDoc._singleLine ? "pre" : "pre-wrap"
                }} >
                    <span ref={r => {
                        if (r) {
                            BigText(r, {
                                rotateText: null,
                                fontSizeFactor: 1,
                                maximumFontSize: null,
                                limitingDimension: "both",
                                horizontalAlign: "center",
                                verticalAlign: "center",
                                textAlign: "center",
                                whiteSpace: "nowrap"
                            });
                        }
                    }}>{label.startsWith("#") ? (null) : label}</span>
                </div>
                <div className="labelBox-fieldKeyParams" >
                    {!missingParams?.length ? (null) : missingParams.map(m => <div key={m} className="labelBox-missingParam">{m}</div>)}
                </div>
            </div>
        );
    }
}