@neo4j-cypher/react-codemirror 1.0.0-next.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +32 -0
- package/es/CypherEditor.js +196 -0
- package/es/CypherEditorStyled.js +22 -0
- package/es/react-codemirror.js +22 -0
- package/lib/CypherEditor.js +206 -0
- package/lib/CypherEditorStyled.js +14 -0
- package/lib/react-codemirror.js +20 -0
- package/package.json +46 -0
- package/src/CypherEditor.d.ts +188 -0
- package/src/CypherEditorStyled.d.ts +10 -0
- package/src/react-codemirror.d.ts +22 -0
package/README.md
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
### @neo4j-cypher/react-codemirror
|
|
2
|
+
|
|
3
|
+
This package exports a React component that provides a cypher editor using codemirror 6.
|
|
4
|
+
|
|
5
|
+
You can use this package like the following:
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
import React from 'react';
|
|
9
|
+
import CypherEditor from '@neo4j-cypher/react-codemirror';
|
|
10
|
+
|
|
11
|
+
const editorProps = {
|
|
12
|
+
onValueChanged: value => {}, // optional
|
|
13
|
+
onFocusChanged: focused => {}, // optional
|
|
14
|
+
onScrollChanged: scrollInfo => {}, // optional
|
|
15
|
+
onPositionChanged: ({ line, column, position }) => {}, // optional
|
|
16
|
+
initialOptions: {
|
|
17
|
+
theme: 'light', // optional, defaults to light
|
|
18
|
+
extensions: [ /* override extensions */ ] // optional, defaults to a sensible list of extensions.
|
|
19
|
+
},
|
|
20
|
+
initialSchema: { /* ... */ }, // optional, see example in demos
|
|
21
|
+
initialValue: 'this is the text to show in the editor',
|
|
22
|
+
initialPosition: { row: 2, column: 3}, // optional, rows are 1 based, columns are 0 based
|
|
23
|
+
classNames: [], // optional, array of classnames to add to the root dom element.
|
|
24
|
+
theme: 'light' // optional, should be light or dark, defaults to light
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const MyReactComponent = () => {
|
|
28
|
+
return (
|
|
29
|
+
<CypherEditor {...editorProps} />
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
```
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
2
|
+
/*
|
|
3
|
+
* Copyright (c) "Neo4j"
|
|
4
|
+
* Neo4j Sweden AB [http://neo4j.com]
|
|
5
|
+
*
|
|
6
|
+
* This file is part of Neo4j.
|
|
7
|
+
*
|
|
8
|
+
* Neo4j is free software: you can redistribute it and/or modify
|
|
9
|
+
* it under the terms of the GNU General Public License as published by
|
|
10
|
+
* the Free Software Foundation, either version 3 of the License, or
|
|
11
|
+
* (at your option) any later version.
|
|
12
|
+
*
|
|
13
|
+
* This program is distributed in the hope that it will be useful,
|
|
14
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
15
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
16
|
+
* GNU General Public License for more details.
|
|
17
|
+
*
|
|
18
|
+
* You should have received a copy of the GNU General Public License
|
|
19
|
+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
import React, { Component } from "react";
|
|
23
|
+
import { createCypherEditor, reactiveOptionKeys, defaultOptions } from "@neo4j-cypher/codemirror";
|
|
24
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
25
|
+
class CypherEditor extends Component {
|
|
26
|
+
constructor(props) {
|
|
27
|
+
super(props);
|
|
28
|
+
_defineProperty(this, "setEditorRef", ref => {
|
|
29
|
+
this.editorRef = ref;
|
|
30
|
+
});
|
|
31
|
+
_defineProperty(this, "valueChanged", (value, changes) => {
|
|
32
|
+
this.innerValue = value;
|
|
33
|
+
this.value = value;
|
|
34
|
+
const {
|
|
35
|
+
onValueChanged
|
|
36
|
+
} = this.props;
|
|
37
|
+
onValueChanged && onValueChanged(value, changes);
|
|
38
|
+
});
|
|
39
|
+
_defineProperty(this, "focusChanged", focused => {
|
|
40
|
+
const {
|
|
41
|
+
onFocusChanged
|
|
42
|
+
} = this.props;
|
|
43
|
+
this.setState({
|
|
44
|
+
focused
|
|
45
|
+
});
|
|
46
|
+
onFocusChanged && onFocusChanged(focused);
|
|
47
|
+
});
|
|
48
|
+
_defineProperty(this, "scrollChanged", scrollInfo => {
|
|
49
|
+
const {
|
|
50
|
+
onScrollChanged
|
|
51
|
+
} = this.props;
|
|
52
|
+
onScrollChanged && onScrollChanged(scrollInfo);
|
|
53
|
+
});
|
|
54
|
+
_defineProperty(this, "positionChanged", positionObject => {
|
|
55
|
+
const {
|
|
56
|
+
onPositionChanged
|
|
57
|
+
} = this.props;
|
|
58
|
+
onPositionChanged && onPositionChanged(positionObject);
|
|
59
|
+
});
|
|
60
|
+
_defineProperty(this, "autocompleteChanged", (autocompleteOpen, from, options) => {
|
|
61
|
+
const {
|
|
62
|
+
onAutocompleteChanged
|
|
63
|
+
} = this.props;
|
|
64
|
+
onAutocompleteChanged && onAutocompleteChanged(autocompleteOpen, from, options);
|
|
65
|
+
});
|
|
66
|
+
_defineProperty(this, "lineNumberClick", (line, event) => {
|
|
67
|
+
const {
|
|
68
|
+
onLineNumberClick
|
|
69
|
+
} = this.props;
|
|
70
|
+
onLineNumberClick && onLineNumberClick(line, event);
|
|
71
|
+
});
|
|
72
|
+
_defineProperty(this, "keyDown", event => {
|
|
73
|
+
const {
|
|
74
|
+
onKeyDown
|
|
75
|
+
} = this.props;
|
|
76
|
+
onKeyDown && onKeyDown(event);
|
|
77
|
+
});
|
|
78
|
+
this.state = {
|
|
79
|
+
focused: false
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
componentDidMount() {
|
|
83
|
+
const {
|
|
84
|
+
autocomplete,
|
|
85
|
+
autocompleteCloseOnBlur,
|
|
86
|
+
autocompleteOpen,
|
|
87
|
+
autocompleteTriggerStrings,
|
|
88
|
+
autofocus,
|
|
89
|
+
history,
|
|
90
|
+
lineNumberFormatter,
|
|
91
|
+
lineNumbers,
|
|
92
|
+
lineWrapping,
|
|
93
|
+
lint,
|
|
94
|
+
placeholder,
|
|
95
|
+
position,
|
|
96
|
+
readOnly,
|
|
97
|
+
readOnlyCursor,
|
|
98
|
+
schema,
|
|
99
|
+
theme,
|
|
100
|
+
parseOnSetValue,
|
|
101
|
+
value,
|
|
102
|
+
onEditorCreated
|
|
103
|
+
} = this.props;
|
|
104
|
+
this.value = this.innerValue = value;
|
|
105
|
+
const {
|
|
106
|
+
editor
|
|
107
|
+
} = createCypherEditor(this.editorRef, {
|
|
108
|
+
autocomplete,
|
|
109
|
+
autocompleteCloseOnBlur,
|
|
110
|
+
autocompleteOpen,
|
|
111
|
+
autocompleteTriggerStrings,
|
|
112
|
+
autofocus,
|
|
113
|
+
history,
|
|
114
|
+
lineNumberFormatter,
|
|
115
|
+
lineNumbers,
|
|
116
|
+
lineWrapping,
|
|
117
|
+
lint,
|
|
118
|
+
placeholder,
|
|
119
|
+
position,
|
|
120
|
+
readOnly,
|
|
121
|
+
readOnlyCursor,
|
|
122
|
+
schema,
|
|
123
|
+
theme,
|
|
124
|
+
parseOnSetValue,
|
|
125
|
+
value
|
|
126
|
+
});
|
|
127
|
+
this.cypherEditor = editor;
|
|
128
|
+
this.cypherEditor.onValueChanged(this.valueChanged);
|
|
129
|
+
this.cypherEditor.onFocusChanged(this.focusChanged);
|
|
130
|
+
this.cypherEditor.onScrollChanged(this.scrollChanged);
|
|
131
|
+
this.cypherEditor.onPositionChanged(this.positionChanged);
|
|
132
|
+
this.cypherEditor.onAutocompleteChanged(this.autocompleteChanged);
|
|
133
|
+
this.cypherEditor.onLineNumberClick(this.lineNumberClick);
|
|
134
|
+
this.cypherEditor.onKeyDown(this.keyDown);
|
|
135
|
+
onEditorCreated && onEditorCreated(this.cypherEditor);
|
|
136
|
+
}
|
|
137
|
+
componentWillUnmount() {
|
|
138
|
+
if (this.cypherEditor) {
|
|
139
|
+
this.cypherEditor.offValueChanged(this.valueChanged);
|
|
140
|
+
this.cypherEditor.offFocusChanged(this.focusChanged);
|
|
141
|
+
this.cypherEditor.offScrollChanged(this.scrollChanged);
|
|
142
|
+
this.cypherEditor.offPositionChanged(this.positionChanged);
|
|
143
|
+
this.cypherEditor.offAutocompleteChanged(this.autocompleteChanged);
|
|
144
|
+
this.cypherEditor.offLineNumberClick(this.lineNumberClick);
|
|
145
|
+
this.cypherEditor.offKeyDown(this.keyDown);
|
|
146
|
+
this.cypherEditor.destroy();
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
componentDidUpdate(prevProps) {
|
|
150
|
+
if (prevProps.value !== this.props.value) {
|
|
151
|
+
this.value = this.props.value;
|
|
152
|
+
}
|
|
153
|
+
for (let key of reactiveOptionKeys) {
|
|
154
|
+
if (prevProps[key] !== this.props[key]) {
|
|
155
|
+
this.updateOption({
|
|
156
|
+
[key]: this.props[key]
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
updateOption(prop) {
|
|
162
|
+
if (!this.cypherEditor) {
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
const key = Object.keys(prop).pop();
|
|
166
|
+
|
|
167
|
+
// Call setValue only if the change comes from the outside
|
|
168
|
+
if (key === "value" && this.innerValue === this.value) {
|
|
169
|
+
return; // TODO - this probably isn't needed for React (only needed for bind:value in Svelte?)
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
const methodName = "set" + key[0].toUpperCase() + key.slice(1);
|
|
173
|
+
if (this.cypherEditor[methodName]) {
|
|
174
|
+
this.cypherEditor[methodName](prop[key]);
|
|
175
|
+
}
|
|
176
|
+
const autofocusProps = this.props.autofocusProps !== undefined ? this.props.autofocusProps : defaultOptions.autofocusProps;
|
|
177
|
+
if (autofocusProps.includes(key)) {
|
|
178
|
+
this.cypherEditor.focus();
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
render() {
|
|
182
|
+
const {
|
|
183
|
+
className,
|
|
184
|
+
focusedClassName
|
|
185
|
+
} = this.props;
|
|
186
|
+
const {
|
|
187
|
+
focused
|
|
188
|
+
} = this.state;
|
|
189
|
+
const editorClassName = (className ? className + " " : "") + (focused && focusedClassName ? focusedClassName : "");
|
|
190
|
+
return /*#__PURE__*/_jsx("div", {
|
|
191
|
+
className: editorClassName,
|
|
192
|
+
ref: this.setEditorRef
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
export default CypherEditor;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) "Neo4j"
|
|
3
|
+
* Neo4j Sweden AB [http://neo4j.com]
|
|
4
|
+
*
|
|
5
|
+
* This file is part of Neo4j.
|
|
6
|
+
*
|
|
7
|
+
* Neo4j is free software: you can redistribute it and/or modify
|
|
8
|
+
* it under the terms of the GNU General Public License as published by
|
|
9
|
+
* the Free Software Foundation, either version 3 of the License, or
|
|
10
|
+
* (at your option) any later version.
|
|
11
|
+
*
|
|
12
|
+
* This program is distributed in the hope that it will be useful,
|
|
13
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
14
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
15
|
+
* GNU General Public License for more details.
|
|
16
|
+
*
|
|
17
|
+
* You should have received a copy of the GNU General Public License
|
|
18
|
+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
import "@neo4j-cypher/codemirror/css/cypher-codemirror.css";
|
|
22
|
+
export { default } from "./CypherEditor";
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) "Neo4j"
|
|
3
|
+
* Neo4j Sweden AB [http://neo4j.com]
|
|
4
|
+
*
|
|
5
|
+
* This file is part of Neo4j.
|
|
6
|
+
*
|
|
7
|
+
* Neo4j is free software: you can redistribute it and/or modify
|
|
8
|
+
* it under the terms of the GNU General Public License as published by
|
|
9
|
+
* the Free Software Foundation, either version 3 of the License, or
|
|
10
|
+
* (at your option) any later version.
|
|
11
|
+
*
|
|
12
|
+
* This program is distributed in the hope that it will be useful,
|
|
13
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
14
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
15
|
+
* GNU General Public License for more details.
|
|
16
|
+
*
|
|
17
|
+
* You should have received a copy of the GNU General Public License
|
|
18
|
+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
export { default as UnstyledCypherEditor } from "./CypherEditor";
|
|
22
|
+
export { default as CypherEditor } from "./CypherEditorStyled";
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports.default = void 0;
|
|
8
|
+
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
9
|
+
var _react = _interopRequireWildcard(require("react"));
|
|
10
|
+
var _codemirror = require("@neo4j-cypher/codemirror");
|
|
11
|
+
var _jsxRuntime = require("react/jsx-runtime");
|
|
12
|
+
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
|
13
|
+
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
|
14
|
+
/*
|
|
15
|
+
* Copyright (c) "Neo4j"
|
|
16
|
+
* Neo4j Sweden AB [http://neo4j.com]
|
|
17
|
+
*
|
|
18
|
+
* This file is part of Neo4j.
|
|
19
|
+
*
|
|
20
|
+
* Neo4j is free software: you can redistribute it and/or modify
|
|
21
|
+
* it under the terms of the GNU General Public License as published by
|
|
22
|
+
* the Free Software Foundation, either version 3 of the License, or
|
|
23
|
+
* (at your option) any later version.
|
|
24
|
+
*
|
|
25
|
+
* This program is distributed in the hope that it will be useful,
|
|
26
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
27
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
28
|
+
* GNU General Public License for more details.
|
|
29
|
+
*
|
|
30
|
+
* You should have received a copy of the GNU General Public License
|
|
31
|
+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
class CypherEditor extends _react.Component {
|
|
35
|
+
constructor(props) {
|
|
36
|
+
super(props);
|
|
37
|
+
(0, _defineProperty2.default)(this, "setEditorRef", ref => {
|
|
38
|
+
this.editorRef = ref;
|
|
39
|
+
});
|
|
40
|
+
(0, _defineProperty2.default)(this, "valueChanged", (value, changes) => {
|
|
41
|
+
this.innerValue = value;
|
|
42
|
+
this.value = value;
|
|
43
|
+
const {
|
|
44
|
+
onValueChanged
|
|
45
|
+
} = this.props;
|
|
46
|
+
onValueChanged && onValueChanged(value, changes);
|
|
47
|
+
});
|
|
48
|
+
(0, _defineProperty2.default)(this, "focusChanged", focused => {
|
|
49
|
+
const {
|
|
50
|
+
onFocusChanged
|
|
51
|
+
} = this.props;
|
|
52
|
+
this.setState({
|
|
53
|
+
focused
|
|
54
|
+
});
|
|
55
|
+
onFocusChanged && onFocusChanged(focused);
|
|
56
|
+
});
|
|
57
|
+
(0, _defineProperty2.default)(this, "scrollChanged", scrollInfo => {
|
|
58
|
+
const {
|
|
59
|
+
onScrollChanged
|
|
60
|
+
} = this.props;
|
|
61
|
+
onScrollChanged && onScrollChanged(scrollInfo);
|
|
62
|
+
});
|
|
63
|
+
(0, _defineProperty2.default)(this, "positionChanged", positionObject => {
|
|
64
|
+
const {
|
|
65
|
+
onPositionChanged
|
|
66
|
+
} = this.props;
|
|
67
|
+
onPositionChanged && onPositionChanged(positionObject);
|
|
68
|
+
});
|
|
69
|
+
(0, _defineProperty2.default)(this, "autocompleteChanged", (autocompleteOpen, from, options) => {
|
|
70
|
+
const {
|
|
71
|
+
onAutocompleteChanged
|
|
72
|
+
} = this.props;
|
|
73
|
+
onAutocompleteChanged && onAutocompleteChanged(autocompleteOpen, from, options);
|
|
74
|
+
});
|
|
75
|
+
(0, _defineProperty2.default)(this, "lineNumberClick", (line, event) => {
|
|
76
|
+
const {
|
|
77
|
+
onLineNumberClick
|
|
78
|
+
} = this.props;
|
|
79
|
+
onLineNumberClick && onLineNumberClick(line, event);
|
|
80
|
+
});
|
|
81
|
+
(0, _defineProperty2.default)(this, "keyDown", event => {
|
|
82
|
+
const {
|
|
83
|
+
onKeyDown
|
|
84
|
+
} = this.props;
|
|
85
|
+
onKeyDown && onKeyDown(event);
|
|
86
|
+
});
|
|
87
|
+
this.state = {
|
|
88
|
+
focused: false
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
componentDidMount() {
|
|
92
|
+
const {
|
|
93
|
+
autocomplete,
|
|
94
|
+
autocompleteCloseOnBlur,
|
|
95
|
+
autocompleteOpen,
|
|
96
|
+
autocompleteTriggerStrings,
|
|
97
|
+
autofocus,
|
|
98
|
+
history,
|
|
99
|
+
lineNumberFormatter,
|
|
100
|
+
lineNumbers,
|
|
101
|
+
lineWrapping,
|
|
102
|
+
lint,
|
|
103
|
+
placeholder,
|
|
104
|
+
position,
|
|
105
|
+
readOnly,
|
|
106
|
+
readOnlyCursor,
|
|
107
|
+
schema,
|
|
108
|
+
theme,
|
|
109
|
+
parseOnSetValue,
|
|
110
|
+
value,
|
|
111
|
+
onEditorCreated
|
|
112
|
+
} = this.props;
|
|
113
|
+
this.value = this.innerValue = value;
|
|
114
|
+
const {
|
|
115
|
+
editor
|
|
116
|
+
} = (0, _codemirror.createCypherEditor)(this.editorRef, {
|
|
117
|
+
autocomplete,
|
|
118
|
+
autocompleteCloseOnBlur,
|
|
119
|
+
autocompleteOpen,
|
|
120
|
+
autocompleteTriggerStrings,
|
|
121
|
+
autofocus,
|
|
122
|
+
history,
|
|
123
|
+
lineNumberFormatter,
|
|
124
|
+
lineNumbers,
|
|
125
|
+
lineWrapping,
|
|
126
|
+
lint,
|
|
127
|
+
placeholder,
|
|
128
|
+
position,
|
|
129
|
+
readOnly,
|
|
130
|
+
readOnlyCursor,
|
|
131
|
+
schema,
|
|
132
|
+
theme,
|
|
133
|
+
parseOnSetValue,
|
|
134
|
+
value
|
|
135
|
+
});
|
|
136
|
+
this.cypherEditor = editor;
|
|
137
|
+
this.cypherEditor.onValueChanged(this.valueChanged);
|
|
138
|
+
this.cypherEditor.onFocusChanged(this.focusChanged);
|
|
139
|
+
this.cypherEditor.onScrollChanged(this.scrollChanged);
|
|
140
|
+
this.cypherEditor.onPositionChanged(this.positionChanged);
|
|
141
|
+
this.cypherEditor.onAutocompleteChanged(this.autocompleteChanged);
|
|
142
|
+
this.cypherEditor.onLineNumberClick(this.lineNumberClick);
|
|
143
|
+
this.cypherEditor.onKeyDown(this.keyDown);
|
|
144
|
+
onEditorCreated && onEditorCreated(this.cypherEditor);
|
|
145
|
+
}
|
|
146
|
+
componentWillUnmount() {
|
|
147
|
+
if (this.cypherEditor) {
|
|
148
|
+
this.cypherEditor.offValueChanged(this.valueChanged);
|
|
149
|
+
this.cypherEditor.offFocusChanged(this.focusChanged);
|
|
150
|
+
this.cypherEditor.offScrollChanged(this.scrollChanged);
|
|
151
|
+
this.cypherEditor.offPositionChanged(this.positionChanged);
|
|
152
|
+
this.cypherEditor.offAutocompleteChanged(this.autocompleteChanged);
|
|
153
|
+
this.cypherEditor.offLineNumberClick(this.lineNumberClick);
|
|
154
|
+
this.cypherEditor.offKeyDown(this.keyDown);
|
|
155
|
+
this.cypherEditor.destroy();
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
componentDidUpdate(prevProps) {
|
|
159
|
+
if (prevProps.value !== this.props.value) {
|
|
160
|
+
this.value = this.props.value;
|
|
161
|
+
}
|
|
162
|
+
for (let key of _codemirror.reactiveOptionKeys) {
|
|
163
|
+
if (prevProps[key] !== this.props[key]) {
|
|
164
|
+
this.updateOption({
|
|
165
|
+
[key]: this.props[key]
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
updateOption(prop) {
|
|
171
|
+
if (!this.cypherEditor) {
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
const key = Object.keys(prop).pop();
|
|
175
|
+
|
|
176
|
+
// Call setValue only if the change comes from the outside
|
|
177
|
+
if (key === "value" && this.innerValue === this.value) {
|
|
178
|
+
return; // TODO - this probably isn't needed for React (only needed for bind:value in Svelte?)
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
const methodName = "set" + key[0].toUpperCase() + key.slice(1);
|
|
182
|
+
if (this.cypherEditor[methodName]) {
|
|
183
|
+
this.cypherEditor[methodName](prop[key]);
|
|
184
|
+
}
|
|
185
|
+
const autofocusProps = this.props.autofocusProps !== undefined ? this.props.autofocusProps : _codemirror.defaultOptions.autofocusProps;
|
|
186
|
+
if (autofocusProps.includes(key)) {
|
|
187
|
+
this.cypherEditor.focus();
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
render() {
|
|
191
|
+
const {
|
|
192
|
+
className,
|
|
193
|
+
focusedClassName
|
|
194
|
+
} = this.props;
|
|
195
|
+
const {
|
|
196
|
+
focused
|
|
197
|
+
} = this.state;
|
|
198
|
+
const editorClassName = (className ? className + " " : "") + (focused && focusedClassName ? focusedClassName : "");
|
|
199
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
|
|
200
|
+
className: editorClassName,
|
|
201
|
+
ref: this.setEditorRef
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
var _default = CypherEditor;
|
|
206
|
+
exports.default = _default;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
Object.defineProperty(exports, "default", {
|
|
8
|
+
enumerable: true,
|
|
9
|
+
get: function () {
|
|
10
|
+
return _CypherEditor.default;
|
|
11
|
+
}
|
|
12
|
+
});
|
|
13
|
+
require("@neo4j-cypher/codemirror/css/cypher-codemirror.css");
|
|
14
|
+
var _CypherEditor = _interopRequireDefault(require("./CypherEditor"));
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
Object.defineProperty(exports, "CypherEditor", {
|
|
8
|
+
enumerable: true,
|
|
9
|
+
get: function () {
|
|
10
|
+
return _CypherEditorStyled.default;
|
|
11
|
+
}
|
|
12
|
+
});
|
|
13
|
+
Object.defineProperty(exports, "UnstyledCypherEditor", {
|
|
14
|
+
enumerable: true,
|
|
15
|
+
get: function () {
|
|
16
|
+
return _CypherEditor.default;
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
var _CypherEditor = _interopRequireDefault(require("./CypherEditor"));
|
|
20
|
+
var _CypherEditorStyled = _interopRequireDefault(require("./CypherEditorStyled"));
|
package/package.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@neo4j-cypher/react-codemirror",
|
|
3
|
+
"description": "React CodeMirror 6 Cypher editor",
|
|
4
|
+
"keywords": [
|
|
5
|
+
"react",
|
|
6
|
+
"cypher",
|
|
7
|
+
"codemirror",
|
|
8
|
+
"codemirror 6"
|
|
9
|
+
],
|
|
10
|
+
"version": "1.0.0-next.0",
|
|
11
|
+
"author": "Neo4j Inc.",
|
|
12
|
+
"license": "GPL-3.0",
|
|
13
|
+
"main": "./lib/react-codemirror.js",
|
|
14
|
+
"module": "./es/react-codemirror.js",
|
|
15
|
+
"types": "src/react-codemirror.d.ts",
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "git://github.com/neo4j-contrib/cypher-editor.git"
|
|
19
|
+
},
|
|
20
|
+
"bugs": {
|
|
21
|
+
"url": "https://github.com/neo4j-contrib/cypher-editor/issues"
|
|
22
|
+
},
|
|
23
|
+
"scripts": {
|
|
24
|
+
"build-lib": "babel --config-file ../../babel.react.config.js --extensions \".js\" --out-dir lib ./src",
|
|
25
|
+
"build-es": "cross-env ES=true babel --config-file ../../babel.react.config.js --extensions \".js\" --out-dir es ./src",
|
|
26
|
+
"build": "npm run build-lib && npm run build-es",
|
|
27
|
+
"clean:build": "rimraf lib && rimraf es"
|
|
28
|
+
},
|
|
29
|
+
"files": [
|
|
30
|
+
"src/*.d.ts",
|
|
31
|
+
"es/",
|
|
32
|
+
"lib/",
|
|
33
|
+
"README.md"
|
|
34
|
+
],
|
|
35
|
+
"engineStrict": true,
|
|
36
|
+
"engines": {
|
|
37
|
+
"node": ">=16"
|
|
38
|
+
},
|
|
39
|
+
"dependencies": {
|
|
40
|
+
"@neo4j-cypher/codemirror": "1.0.0-next.0",
|
|
41
|
+
"codemirror": "^6.0.1"
|
|
42
|
+
},
|
|
43
|
+
"peerDependencies": {
|
|
44
|
+
"react": ">=16"
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
// import type { Extension } from "@codemirror/state";
|
|
3
|
+
import type { EditorSupportSchema } from "@neo4j-cypher/editor-support";
|
|
4
|
+
import type {
|
|
5
|
+
PositionAny,
|
|
6
|
+
Theme,
|
|
7
|
+
AutofocusProp,
|
|
8
|
+
EditorCreatedListener,
|
|
9
|
+
AutocompleteChangedListener,
|
|
10
|
+
PositionChangedListener,
|
|
11
|
+
FocusChangedListener,
|
|
12
|
+
ScrollChangedListener,
|
|
13
|
+
ValueChangedListener,
|
|
14
|
+
KeyDownListener,
|
|
15
|
+
LineNumberClickListener,
|
|
16
|
+
LineNumberFormatter
|
|
17
|
+
} from "@neo4j-cypher/codemirror";
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Interface for React Cypher Editor component props
|
|
21
|
+
*/
|
|
22
|
+
export interface CypherEditorProps {
|
|
23
|
+
/**
|
|
24
|
+
* Whether the autocomplete feature is enabled
|
|
25
|
+
*
|
|
26
|
+
* @defaultValue `true`
|
|
27
|
+
*/
|
|
28
|
+
autocomplete?: boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Whether the autocomplete auto closes whenever the editor loses focus
|
|
31
|
+
*
|
|
32
|
+
* @defaultValue `true`
|
|
33
|
+
*/
|
|
34
|
+
autocompleteCloseOnBlur?: boolean;
|
|
35
|
+
/**
|
|
36
|
+
* Whether the autocomplete window is open
|
|
37
|
+
*
|
|
38
|
+
* @remarks
|
|
39
|
+
*
|
|
40
|
+
* Changing this can be used to manually control the autocomplete open state
|
|
41
|
+
*
|
|
42
|
+
* @defaultValue `false`
|
|
43
|
+
*/
|
|
44
|
+
autocompleteOpen?: boolean;
|
|
45
|
+
/**
|
|
46
|
+
* The keys that when typed will automatically open the autocomplete menu
|
|
47
|
+
*
|
|
48
|
+
* @defaultValue [".",":","[]","()","{}","[","(","{","$"]
|
|
49
|
+
*/
|
|
50
|
+
autocompleteTriggerStrings?: string[];
|
|
51
|
+
/**
|
|
52
|
+
* Whether the editor should be auto focused on first creation
|
|
53
|
+
*
|
|
54
|
+
* @defaultValue true
|
|
55
|
+
*/
|
|
56
|
+
autofocus?: boolean;
|
|
57
|
+
/**
|
|
58
|
+
* setting any of these props will trigger the editor gaining focus
|
|
59
|
+
*
|
|
60
|
+
* @defaultValue ["position", "readOnly", "value"]
|
|
61
|
+
*/
|
|
62
|
+
autofocusProps?: AutofocusProp[];
|
|
63
|
+
/**
|
|
64
|
+
* Whether the editor maintains an undo/redo history
|
|
65
|
+
*
|
|
66
|
+
* @defaultValue true
|
|
67
|
+
*/
|
|
68
|
+
history?: boolean;
|
|
69
|
+
/**
|
|
70
|
+
* The formatter for the line numbers of the editor
|
|
71
|
+
*
|
|
72
|
+
* @defaultValue (line, lineCount) => lineCount === 1 ? "$" : line + "";
|
|
73
|
+
*/
|
|
74
|
+
lineNumberFormatter?: LineNumberFormatter;
|
|
75
|
+
/**
|
|
76
|
+
* Whether line numbers are shown to the left of the editor ui
|
|
77
|
+
*
|
|
78
|
+
* @defaultValue true
|
|
79
|
+
*/
|
|
80
|
+
lineNumbers?: boolean;
|
|
81
|
+
/**
|
|
82
|
+
* Whether the editor wraps lines vs using a horizontal scrollbar
|
|
83
|
+
*
|
|
84
|
+
* @defaultValue false
|
|
85
|
+
*/
|
|
86
|
+
lineWrapping?: boolean;
|
|
87
|
+
/**
|
|
88
|
+
* Whether the editor should display lint errors to the user
|
|
89
|
+
*
|
|
90
|
+
* @defaultValue false
|
|
91
|
+
*/
|
|
92
|
+
lint?: boolean;
|
|
93
|
+
/**
|
|
94
|
+
* Whether to run the cypher language parser immediately after every call to set the value
|
|
95
|
+
*
|
|
96
|
+
* @defaultValue true
|
|
97
|
+
*/
|
|
98
|
+
parseOnSetValue?: boolean;
|
|
99
|
+
/**
|
|
100
|
+
* The text to be shown to the user when the editor value is empty
|
|
101
|
+
*/
|
|
102
|
+
placeholder?: string;
|
|
103
|
+
/**
|
|
104
|
+
* The editor cursor position
|
|
105
|
+
*/
|
|
106
|
+
position?: PositionAny;
|
|
107
|
+
/**
|
|
108
|
+
* Whether the editor is read only or the user can edit the editor's value
|
|
109
|
+
*
|
|
110
|
+
* @defaultValue false
|
|
111
|
+
*/
|
|
112
|
+
readOnly?: boolean;
|
|
113
|
+
/**
|
|
114
|
+
* Whether to show the cursor when the editor readOnly is true
|
|
115
|
+
*
|
|
116
|
+
* @defaultValue false
|
|
117
|
+
*/
|
|
118
|
+
readOnlyCursor?: boolean;
|
|
119
|
+
/**
|
|
120
|
+
* The schema making the editor aware of things such as node labels & relationship types & procedures in the current graph database
|
|
121
|
+
*/
|
|
122
|
+
schema?: EditorSupportSchema;
|
|
123
|
+
/**
|
|
124
|
+
* Whether to use the light or dark theme for the editor
|
|
125
|
+
*
|
|
126
|
+
* @defaultValue "light"
|
|
127
|
+
*/
|
|
128
|
+
theme?: Theme;
|
|
129
|
+
/**
|
|
130
|
+
* The editor text value
|
|
131
|
+
*
|
|
132
|
+
* @defaultValue ""
|
|
133
|
+
*/
|
|
134
|
+
value?: string;
|
|
135
|
+
/**
|
|
136
|
+
* A css class name to be added to the root editor dom element
|
|
137
|
+
*/
|
|
138
|
+
className?: string;
|
|
139
|
+
/**
|
|
140
|
+
* A css class name to be added to the root editor dom element when it is focused
|
|
141
|
+
*/
|
|
142
|
+
focusedClassName?: string;
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* A listener for when the editor api gets created
|
|
146
|
+
*/
|
|
147
|
+
onEditorCreated?: EditorCreatedListener;
|
|
148
|
+
/**
|
|
149
|
+
* A listener for when the editor value changes
|
|
150
|
+
*/
|
|
151
|
+
onValueChanged?: ValueChangedListener;
|
|
152
|
+
/**
|
|
153
|
+
* A listener for when the editor focus changes
|
|
154
|
+
*/
|
|
155
|
+
onFocusChanged?: FocusChangedListener;
|
|
156
|
+
/**
|
|
157
|
+
* A listener for when the editor scroll position changes
|
|
158
|
+
*/
|
|
159
|
+
onScrollChanged?: ScrollChangedListener;
|
|
160
|
+
/**
|
|
161
|
+
* A listener for when the editor cursor position changes
|
|
162
|
+
*/
|
|
163
|
+
onPositionChanged?: PositionChangedListener;
|
|
164
|
+
/**
|
|
165
|
+
* A listener for when the editor autocompletion state changes
|
|
166
|
+
*/
|
|
167
|
+
onAutocompleteChanged?: AutocompleteChangedListener;
|
|
168
|
+
/**
|
|
169
|
+
* A listener for when the user clicks an editor line number
|
|
170
|
+
*/
|
|
171
|
+
onLineNumberClick?: LineNumberClickListener;
|
|
172
|
+
/**
|
|
173
|
+
* A listener for when the user presses a key down in the editor
|
|
174
|
+
*/
|
|
175
|
+
onKeyDown?: KeyDownListener;
|
|
176
|
+
|
|
177
|
+
// TODO - add these props
|
|
178
|
+
// preExtensions?: Extension[],
|
|
179
|
+
// postExtensions?: Extension[]
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Cypher Editor React Component
|
|
184
|
+
*/
|
|
185
|
+
export default class CypherEditor extends React.Component<
|
|
186
|
+
CypherEditorProps,
|
|
187
|
+
any
|
|
188
|
+
> {}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import type { CypherEditorProps } from "./CypherEditor";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Cypher Editor React Component (with css styles included)
|
|
6
|
+
*/
|
|
7
|
+
export default class CypherEditorStyled extends React.Component<
|
|
8
|
+
CypherEditorProps,
|
|
9
|
+
any
|
|
10
|
+
> {}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This package provides a React Cypher Editor component
|
|
3
|
+
*
|
|
4
|
+
* @remarks
|
|
5
|
+
*
|
|
6
|
+
* The props for this component are defined by the {@link react-codemirror#CypherEditorProps | CypherEditorProps} interface
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* Here's some example code using the props:
|
|
10
|
+
*
|
|
11
|
+
* ```ts
|
|
12
|
+
* const props = { autocomplete: false };
|
|
13
|
+
* <CypherEditor {...props} />
|
|
14
|
+
* ```
|
|
15
|
+
*
|
|
16
|
+
* @packageDocumentation
|
|
17
|
+
*/
|
|
18
|
+
export type {
|
|
19
|
+
default as UnstyledCypherEditor,
|
|
20
|
+
CypherEditorProps
|
|
21
|
+
} from "./CypherEditor";
|
|
22
|
+
export type { default as CypherEditor } from "./CypherEditorStyled";
|