aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/nodes/SliderBox.tsx
blob: 844d95d110b434c3009d3a4b738cc5d0b5d1b474 (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
import { library } from '@fortawesome/fontawesome-svg-core';
import { faEdit } from '@fortawesome/free-regular-svg-icons';
import { computed, runInAction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
import { Handles, Rail, Slider, Tracks, Ticks } from 'react-compound-slider';
import { Doc } from '../../../new_fields/Doc';
import { documentSchema } from '../../../new_fields/documentSchemas';
import { createSchema, listSpec, makeInterface } from '../../../new_fields/Schema';
import { ScriptField } from '../../../new_fields/ScriptField';
import { BoolCast, FieldValue, StrCast, NumCast, Cast } from '../../../new_fields/Types';
import { DragManager } from '../../util/DragManager';
import { ContextMenu } from '../ContextMenu';
import { ContextMenuProps } from '../ContextMenuItem';
import { DocComponent } from '../DocComponent';
import './SliderBox.scss';
import { Handle, TooltipRail, Track, Tick } from './SliderBox-components';
import { FieldView, FieldViewProps } from './FieldView';
import { ScriptBox } from '../ScriptBox';


library.add(faEdit as any);

const SliderSchema = createSchema({
    _sliderMin: "number",
    _sliderMax: "number",
    _sliderMinThumb: "number",
    _sliderMaxThumb: "number",
});

type SliderDocument = makeInterface<[typeof SliderSchema, typeof documentSchema]>;
const SliderDocument = makeInterface(SliderSchema, documentSchema);

@observer
export class SliderBox extends DocComponent<FieldViewProps, SliderDocument>(SliderDocument) {
    public static LayoutString(fieldKey: string) { return FieldView.LayoutString(SliderBox, fieldKey); }
    private dropDisposer?: DragManager.DragDropDisposer;

    @computed get dataDoc() {
        return this.props.DataDoc &&
            (this.Document.isTemplateForField || BoolCast(this.props.DataDoc.isTemplateForField) ||
                this.props.DataDoc.layout === this.Document) ? this.props.DataDoc : Doc.GetProto(this.Document);
    }

    specificContextMenu = (e: React.MouseEvent): void => {
        const funcs: ContextMenuProps[] = [];
        funcs.push({ description: "Edit Thumb Change Script", icon: "edit", event: (obj: any) => ScriptBox.EditButtonScript("On Thumb Change ...", this.props.Document, "onThumbChange", obj.x, obj.y) });
        ContextMenu.Instance.addItem({ description: "Slider Funcs...", subitems: funcs, icon: "asterisk" });
    }
    onChange = (values: readonly number[]) => runInAction(() => {
        this.Document._sliderMinThumb = values[0];
        this.Document._sliderMaxThumb = values[1];
        Cast(this.Document.onThumbChanged, ScriptField, null)?.script.run({ range: values, this: this.props.Document });
    })

    render() {
        const domain = [NumCast(this.props.Document._sliderMin), NumCast(this.props.Document._sliderMax)];
        const defaultValues = [NumCast(this.props.Document._sliderMinThumb), NumCast(this.props.Document._sliderMaxThumb)];
        return (
            <div className="sliderBox-outerDiv" onContextMenu={this.specificContextMenu} onPointerDown={e => e.stopPropagation()}
                style={{ boxShadow: this.Document.opacity === 0 ? undefined : StrCast(this.Document.boxShadow, "") }}>
                <div className="sliderBox-mainButton" onContextMenu={this.specificContextMenu} style={{
                    background: this.Document.backgroundColor, color: this.Document.color || "black",
                    fontSize: this.Document.fontSize, letterSpacing: this.Document.letterSpacing || ""
                }} >
                    <Slider
                        mode={2}
                        step={1}
                        domain={domain}
                        rootStyle={{ position: "relative", width: "100%" }}
                        onChange={this.onChange}
                        values={defaultValues}
                    >

                        <Rail>{railProps => <TooltipRail {...railProps} />}</Rail>
                        <Handles>
                            {({ handles, activeHandleID, getHandleProps }) => (
                                <div className="slider-handles">
                                    {handles.map((handle, i) => {
                                        const value = i === 0 ? this.Document._sliderMinThumb : this.Document._sliderMaxThumb;
                                        return (
                                            <div title={String(value)}>
                                                <Handle
                                                    key={handle.id}
                                                    handle={handle}
                                                    domain={domain}
                                                    isActive={handle.id === activeHandleID}
                                                    getHandleProps={getHandleProps}
                                                />
                                            </div>
                                        );
                                    })}
                                </div>
                            )}
                        </Handles>
                        <Tracks left={false} right={false}>
                            {({ tracks, getTrackProps }) => (
                                <div className="slider-tracks">
                                    {tracks.map(({ id, source, target }) => (
                                        <Track
                                            key={id}
                                            source={source}
                                            target={target}
                                            disabled={false}
                                            getTrackProps={getTrackProps}
                                        />
                                    ))}
                                </div>
                            )}
                        </Tracks>
                        <Ticks count={5}>
                            {({ ticks }) => (
                                <div className="slider-tracks">
                                    {ticks.map((tick) => (
                                        <Tick
                                            key={tick.id}
                                            tick={tick}
                                            count={ticks.length}
                                            format={(val: number) => val.toString()}
                                        />
                                    ))}
                                </div>
                            )}
                        </Ticks>
                    </Slider>
                </div>
            </div>
        );
    }
}