aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/nodes/formattedText/EquationView.tsx
blob: 5e62d94c23964c0d5fc0421fc55e765037d43297 (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
import EquationEditor from 'equation-editor-react';
import { IReactionDisposer, trace } from 'mobx';
import { observer } from 'mobx-react';
import { TextSelection } from 'prosemirror-state';
import * as ReactDOM from 'react-dom/client';
import { Doc } from '../../../../fields/Doc';
import { StrCast } from '../../../../fields/Types';
import './DashFieldView.scss';
import { FormattedTextBox } from './FormattedTextBox';
import React = require('react');

export class EquationView {
    dom: HTMLDivElement; // container for label and value
    root: any;
    tbox: FormattedTextBox;
    view: any;
    constructor(node: any, view: any, getPos: any, tbox: FormattedTextBox) {
        this.tbox = tbox;
        this.view = view;
        this.dom = document.createElement('div');
        this.dom.style.width = node.attrs.width;
        this.dom.style.height = node.attrs.height;
        this.dom.style.position = 'relative';
        this.dom.style.display = 'inline-block';
        this.dom.onmousedown = function (e: any) {
            e.stopPropagation();
        };

        this.root = ReactDOM.createRoot(this.dom);
        this.root.render(<EquationViewInternal fieldKey={node.attrs.fieldKey} width={node.attrs.width} height={node.attrs.height} getPos={getPos} setEditor={this.setEditor} tbox={tbox} />);
    }
    _editor: EquationEditor | undefined;
    setEditor = (editor?: EquationEditor) => (this._editor = editor);
    destroy() {
        this.root.unmount();
    }
    setSelection() {
        this._editor?.mathField.focus();
    }
    selectNode() {
        this.tbox._applyingChange = this.tbox.fieldKey; // setting focus will make prosemirror lose focus, which will cause it to change its selection to a text selection, which causes this view to get rebuilt but it's no longer node selected, so the equationview won't have focus
        setTimeout(() => {
            this._editor?.mathField.focus();
            setTimeout(() => (this.tbox._applyingChange = ''));
        });
    }
    deselectNode() {}
}

interface IEquationViewInternal {
    fieldKey: string;
    tbox: FormattedTextBox;
    width: number;
    height: number;
    getPos: () => number;
    setEditor: (editor: EquationEditor | undefined) => void;
}

@observer
export class EquationViewInternal extends React.Component<IEquationViewInternal> {
    _reactionDisposer: IReactionDisposer | undefined;
    _textBoxDoc: Doc;
    _fieldKey: string;
    _ref: React.RefObject<EquationEditor> = React.createRef();

    constructor(props: IEquationViewInternal) {
        super(props);
        this._fieldKey = this.props.fieldKey;
        this._textBoxDoc = this.props.tbox.props.Document;
    }

    componentWillUnmount() {
        this._reactionDisposer?.();
    }
    componentDidMount() {
        this.props.setEditor(this._ref.current ?? undefined);
    }

    render() {
        return (
            <div
                className="equationView"
                onKeyDown={e => {
                    if (e.key === 'Enter') {
                        this.props.tbox.EditorView!.dispatch(this.props.tbox.EditorView!.state.tr.setSelection(new TextSelection(this.props.tbox.EditorView!.state.doc.resolve(this.props.getPos() + 1))));
                        this.props.tbox.EditorView!.focus();
                        e.preventDefault();
                    }
                    e.stopPropagation();
                }}
                onKeyPress={e => e.stopPropagation()}
                style={{
                    position: 'relative',
                    display: 'inline-block',
                    width: this.props.width,
                    height: this.props.height,
                    background: 'white',
                    borderRadius: '10%',
                    bottom: 3,
                }}>
                <EquationEditor
                    ref={this._ref}
                    value={StrCast(this._textBoxDoc[this._fieldKey], 'y=')}
                    onChange={str => (this._textBoxDoc[this._fieldKey] = str)}
                    autoCommands="pi theta sqrt sum prod alpha beta gamma rho"
                    autoOperatorNames="sin cos tan"
                    spaceBehavesLikeTab={true}
                />
            </div>
        );
    }
}