@neo4j-cypher/react-codemirror 2.0.0-next.0 → 2.0.0-next.2

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/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @neo4j-cypher/react-codemirror
2
2
 
3
+ ## 2.0.0-next.2
4
+
5
+ ### Patch Changes
6
+
7
+ - 3866e43: Editor history is now a controlled prop
8
+
9
+ ## 2.0.0-next.1
10
+
11
+ ### Patch Changes
12
+
13
+ - Fix incorrect exports
14
+
3
15
  ## 2.0.0-next.0
4
16
 
5
17
  ### Major Changes
package/README.md CHANGED
@@ -4,7 +4,7 @@ This package can be built with `npm run build` and then published to npm with `n
4
4
 
5
5
  ## Usage
6
6
 
7
- `npm install @neo4j-cypher/reactcodemirror`
7
+ `npm install @neo4j-cypher/react-codemirror@next`
8
8
 
9
9
  ```tsx
10
10
  import { useState } from 'react';
@@ -26,6 +26,9 @@ For a full example, see the [react-codemirror-playground](https://github.com/neo
26
26
 
27
27
  Currently we only support using the codemirror editor via the react wrapper, but we plan to release the codemirror extensions separately as well.
28
28
 
29
+ ## Learning codemirror
30
+ It can take a little time to get into the CodeMirror6 ways of thinking, Trevor Harmon has a [great blog post](https://thetrevorharmon.com/blog/learning-codemirror/) explaining the cm6 "primitives". He also has a demo on how to integrate ANTLR4 with codemirror over [here](https://github.com/thetrevorharmon/zephyr-demo).
31
+
29
32
  ### Completion Icons
30
33
 
31
34
  We use unmodified copies of Visual Studio Code Icons from microsofts repository [here](https://github.com/microsoft/vscode-icons) licensed under creative commons.
@@ -1,8 +1,6 @@
1
- var __create = Object.create;
2
1
  var __defProp = Object.defineProperty;
3
2
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
3
  var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __getProtoOf = Object.getPrototypeOf;
6
4
  var __hasOwnProp = Object.prototype.hasOwnProperty;
7
5
  var __export = (target, all) => {
8
6
  for (var name in all)
@@ -16,14 +14,6 @@ var __copyProps = (to, from, except, desc) => {
16
14
  }
17
15
  return to;
18
16
  };
19
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
20
- // If the importer is in node compatibility mode or this is not an ESM
21
- // file that has been converted to a CommonJS file using a Babel-
22
- // compatible transform (i.e. "__esModule" has not been set), then set
23
- // "default" to the CommonJS "module.exports" for node compatibility.
24
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
25
- mod
26
- ));
27
17
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
28
18
 
29
19
  // src/index.ts
@@ -31,7 +21,6 @@ var src_exports = {};
31
21
  __export(src_exports, {
32
22
  CypherEditor: () => CypherEditor,
33
23
  CypherParser: () => import_language_support4.CypherParser,
34
- ReactCodemirror: () => ReactCodemirror,
35
24
  cypher: () => cypher,
36
25
  darkThemeConstants: () => darkThemeConstants,
37
26
  lightThemeConstants: () => lightThemeConstants,
@@ -39,13 +28,173 @@ __export(src_exports, {
39
28
  });
40
29
  module.exports = __toCommonJS(src_exports);
41
30
  var import_language_support4 = require("@neo4j-cypher/language-support");
42
- var ReactCodemirror = __toESM(require("@uiw/react-codemirror"));
43
31
 
44
32
  // src/CypherEditor.tsx
45
33
  var import_state4 = require("@codemirror/state");
46
34
  var import_view4 = require("@codemirror/view");
47
35
  var import_react = require("react");
48
36
 
37
+ // src/history-navigation.ts
38
+ var import_state = require("@codemirror/state");
39
+ var import_view = require("@codemirror/view");
40
+ var import_state2 = require("@codemirror/state");
41
+ var DRAFT_ENTRY_INDEX = -1;
42
+ var historyInitialState = {
43
+ history: [],
44
+ index: DRAFT_ENTRY_INDEX,
45
+ documentUpdate: null,
46
+ draft: ""
47
+ };
48
+ var historyState = import_state2.StateField.define({
49
+ create() {
50
+ return historyInitialState;
51
+ },
52
+ toJSON(value) {
53
+ return JSON.stringify(value);
54
+ },
55
+ update(value, transaction) {
56
+ for (const effect of transaction.effects) {
57
+ if (effect.is(moveInHistory)) {
58
+ if (value.history.length === 0) {
59
+ return {
60
+ ...value,
61
+ documentUpdate: null
62
+ };
63
+ }
64
+ const currentHistoryIndex = value.index;
65
+ if (effect.value === "BACK") {
66
+ const newHistoryIndex = currentHistoryIndex + 1;
67
+ if (newHistoryIndex === value.history.length) {
68
+ return {
69
+ ...value,
70
+ documentUpdate: null
71
+ };
72
+ }
73
+ let draft = value.draft;
74
+ if (currentHistoryIndex === DRAFT_ENTRY_INDEX) {
75
+ draft = transaction.state.doc.toString();
76
+ }
77
+ return {
78
+ ...value,
79
+ draft,
80
+ index: newHistoryIndex,
81
+ documentUpdate: value.history[newHistoryIndex]
82
+ };
83
+ } else if (effect.value === "FORWARDS") {
84
+ const newHistoryIndex = currentHistoryIndex - 1;
85
+ if (currentHistoryIndex === DRAFT_ENTRY_INDEX) {
86
+ return { ...value, documentUpdate: null };
87
+ }
88
+ if (newHistoryIndex === DRAFT_ENTRY_INDEX) {
89
+ return {
90
+ ...value,
91
+ index: newHistoryIndex,
92
+ documentUpdate: value.draft
93
+ };
94
+ } else {
95
+ return {
96
+ ...value,
97
+ index: newHistoryIndex,
98
+ documentUpdate: value.history[newHistoryIndex]
99
+ };
100
+ }
101
+ }
102
+ } else if (effect.is(replaceHistory)) {
103
+ return {
104
+ ...value,
105
+ index: DRAFT_ENTRY_INDEX,
106
+ history: effect.value
107
+ };
108
+ }
109
+ }
110
+ return value;
111
+ }
112
+ });
113
+ var moveInHistory = import_state.StateEffect.define();
114
+ var replaceHistory = import_state.StateEffect.define();
115
+ function navigateHistory(view, direction) {
116
+ view.dispatch(
117
+ view.state.update({
118
+ effects: moveInHistory.of(direction),
119
+ selection: { anchor: view.state.doc.length }
120
+ })
121
+ );
122
+ const updatedHistory = view.state.field(historyState, false);
123
+ if (updatedHistory.documentUpdate !== null) {
124
+ view.dispatch(
125
+ view.state.update({
126
+ changes: {
127
+ from: 0,
128
+ to: view.state.doc.length,
129
+ insert: updatedHistory.documentUpdate
130
+ }
131
+ })
132
+ );
133
+ }
134
+ }
135
+ var replMode = ({ history: history2 }) => {
136
+ return [
137
+ historyState.init(() => ({
138
+ ...historyInitialState,
139
+ history: history2
140
+ })),
141
+ import_view.keymap.of([
142
+ {
143
+ key: "ArrowUp",
144
+ preventDefault: true,
145
+ run: (view) => {
146
+ const { empty, head } = view.state.selection.main;
147
+ if (!empty || head !== 0) {
148
+ return false;
149
+ }
150
+ navigateHistory(view, "BACK");
151
+ return true;
152
+ }
153
+ },
154
+ {
155
+ mac: "Cmd-ArrowUp",
156
+ win: "Ctrl-ArrowUp",
157
+ linux: "Ctrl-ArrowUp",
158
+ preventDefault: true,
159
+ run: (view) => {
160
+ const { empty, head } = view.state.selection.main;
161
+ if (!empty || head !== 0) {
162
+ return false;
163
+ }
164
+ navigateHistory(view, "BACK");
165
+ return true;
166
+ }
167
+ },
168
+ {
169
+ key: "ArrowDown",
170
+ preventDefault: true,
171
+ run: (view) => {
172
+ const { empty, head } = view.state.selection.main;
173
+ if (!empty || head !== view.state.doc.length) {
174
+ return false;
175
+ }
176
+ navigateHistory(view, "FORWARDS");
177
+ return true;
178
+ }
179
+ },
180
+ {
181
+ mac: "Cmd-ArrowDown",
182
+ win: "Ctrl-ArrowDown",
183
+ linux: "Ctrl-ArrowDown",
184
+ preventDefault: true,
185
+ run: (view) => {
186
+ const { empty, head } = view.state.selection.main;
187
+ if (!empty || head !== view.state.doc.length) {
188
+ return false;
189
+ }
190
+ navigateHistory(view, "FORWARDS");
191
+ return true;
192
+ }
193
+ }
194
+ ])
195
+ ];
196
+ };
197
+
49
198
  // src/lang-cypher/lang-cypher.ts
50
199
  var import_language2 = require("@codemirror/language");
51
200
 
@@ -269,8 +418,8 @@ var import_autocomplete2 = require("@codemirror/autocomplete");
269
418
  var import_commands = require("@codemirror/commands");
270
419
  var import_language3 = require("@codemirror/language");
271
420
  var import_search = require("@codemirror/search");
272
- var import_state = require("@codemirror/state");
273
- var import_view = require("@codemirror/view");
421
+ var import_state3 = require("@codemirror/state");
422
+ var import_view2 = require("@codemirror/view");
274
423
  var import_lint2 = require("@codemirror/lint");
275
424
 
276
425
  // src/icons.ts
@@ -378,11 +527,11 @@ var basicNeo4jSetup = () => {
378
527
  }
379
528
  ].flat();
380
529
  const extensions = [];
381
- extensions.push((0, import_view.highlightSpecialChars)());
530
+ extensions.push((0, import_view2.highlightSpecialChars)());
382
531
  extensions.push((0, import_commands.history)());
383
- extensions.push((0, import_view.drawSelection)());
384
- extensions.push((0, import_view.dropCursor)());
385
- extensions.push(import_state.EditorState.allowMultipleSelections.of(true));
532
+ extensions.push((0, import_view2.drawSelection)());
533
+ extensions.push((0, import_view2.dropCursor)());
534
+ extensions.push(import_state3.EditorState.allowMultipleSelections.of(true));
386
535
  extensions.push((0, import_language3.indentOnInput)());
387
536
  extensions.push(
388
537
  (0, import_language3.syntaxHighlighting)(import_language3.defaultHighlightStyle, { fallback: true })
@@ -396,7 +545,7 @@ var basicNeo4jSetup = () => {
396
545
  addToOptions: [
397
546
  {
398
547
  render(completion, state) {
399
- const isDarkTheme = state.facet(import_view.EditorView.darkTheme);
548
+ const isDarkTheme = state.facet(import_view2.EditorView.darkTheme);
400
549
  const icon = document.createElement("span");
401
550
  icon.innerHTML = getIconForType(completion.type, isDarkTheme);
402
551
  const svgElement = icon.children[0];
@@ -409,194 +558,13 @@ var basicNeo4jSetup = () => {
409
558
  ]
410
559
  })
411
560
  );
412
- extensions.push((0, import_view.rectangularSelection)());
413
- extensions.push((0, import_view.crosshairCursor)());
561
+ extensions.push((0, import_view2.rectangularSelection)());
562
+ extensions.push((0, import_view2.crosshairCursor)());
414
563
  extensions.push((0, import_search.highlightSelectionMatches)());
415
- extensions.push(import_view.keymap.of(keymaps));
564
+ extensions.push(import_view2.keymap.of(keymaps));
416
565
  return extensions;
417
566
  };
418
567
 
419
- // src/repl-mode.ts
420
- var import_state2 = require("@codemirror/state");
421
- var import_view2 = require("@codemirror/view");
422
- var import_state3 = require("@codemirror/state");
423
- var DRAFT_ENTRY_INDEX = -1;
424
- var historyInitialState = {
425
- history: [],
426
- index: DRAFT_ENTRY_INDEX,
427
- documentUpdate: null,
428
- draft: ""
429
- };
430
- var historyState = import_state3.StateField.define({
431
- create() {
432
- return historyInitialState;
433
- },
434
- toJSON(value) {
435
- return JSON.stringify(value);
436
- },
437
- update(value, transaction) {
438
- for (const effect of transaction.effects) {
439
- if (effect.is(moveInHistory)) {
440
- if (value.history.length === 0) {
441
- return {
442
- ...value,
443
- documentUpdate: null
444
- };
445
- }
446
- const currentHistoryIndex = value.index;
447
- if (effect.value === "BACK") {
448
- const newHistoryIndex = currentHistoryIndex + 1;
449
- if (newHistoryIndex === value.history.length) {
450
- return {
451
- ...value,
452
- documentUpdate: null
453
- };
454
- }
455
- let draft = value.draft;
456
- if (currentHistoryIndex === DRAFT_ENTRY_INDEX) {
457
- draft = transaction.state.doc.toString();
458
- }
459
- return {
460
- ...value,
461
- draft,
462
- index: newHistoryIndex,
463
- documentUpdate: value.history[newHistoryIndex]
464
- };
465
- } else if (effect.value === "FORWARDS") {
466
- const newHistoryIndex = currentHistoryIndex - 1;
467
- if (currentHistoryIndex === DRAFT_ENTRY_INDEX) {
468
- return { ...value, documentUpdate: null };
469
- }
470
- if (newHistoryIndex === DRAFT_ENTRY_INDEX) {
471
- return {
472
- ...value,
473
- index: newHistoryIndex,
474
- documentUpdate: value.draft
475
- };
476
- } else {
477
- return {
478
- ...value,
479
- index: newHistoryIndex,
480
- documentUpdate: value.history[newHistoryIndex]
481
- };
482
- }
483
- }
484
- } else if (effect.is(pushToHistory)) {
485
- return {
486
- ...value,
487
- index: DRAFT_ENTRY_INDEX,
488
- history: [effect.value, ...value.history]
489
- };
490
- }
491
- }
492
- return value;
493
- }
494
- });
495
- var moveInHistory = import_state2.StateEffect.define();
496
- var pushToHistory = import_state2.StateEffect.define();
497
- function navigateHistory(view, direction) {
498
- view.dispatch(
499
- view.state.update({
500
- effects: moveInHistory.of(direction),
501
- selection: { anchor: view.state.doc.length }
502
- })
503
- );
504
- const updatedHistory = view.state.field(historyState, false);
505
- if (updatedHistory.documentUpdate !== null) {
506
- view.dispatch(
507
- view.state.update({
508
- changes: {
509
- from: 0,
510
- to: view.state.doc.length,
511
- insert: updatedHistory.documentUpdate
512
- }
513
- })
514
- );
515
- }
516
- }
517
- var replMode = ({
518
- onExecute,
519
- onNewHistoryEntry,
520
- initialHistory
521
- }) => {
522
- return [
523
- historyState.init(() => ({
524
- ...historyInitialState,
525
- history: initialHistory
526
- })),
527
- import_view2.keymap.of([
528
- {
529
- key: "Ctrl-Enter",
530
- mac: "Mod-Enter",
531
- preventDefault: true,
532
- run: (view) => {
533
- const doc = view.state.doc.toString();
534
- if (doc.trim() !== "") {
535
- onExecute?.(doc);
536
- onNewHistoryEntry?.(doc);
537
- view.dispatch({
538
- effects: pushToHistory.of(doc)
539
- });
540
- }
541
- return true;
542
- }
543
- },
544
- {
545
- key: "ArrowUp",
546
- preventDefault: true,
547
- run: (view) => {
548
- const { empty, head } = view.state.selection.main;
549
- if (!empty || head !== 0) {
550
- return false;
551
- }
552
- navigateHistory(view, "BACK");
553
- return true;
554
- }
555
- },
556
- {
557
- mac: "Cmd-ArrowUp",
558
- win: "Ctrl-ArrowUp",
559
- linux: "Ctrl-ArrowUp",
560
- preventDefault: true,
561
- run: (view) => {
562
- const { empty, head } = view.state.selection.main;
563
- if (!empty || head !== 0) {
564
- return false;
565
- }
566
- navigateHistory(view, "BACK");
567
- return true;
568
- }
569
- },
570
- {
571
- key: "ArrowDown",
572
- preventDefault: true,
573
- run: (view) => {
574
- const { empty, head } = view.state.selection.main;
575
- if (!empty || head !== view.state.doc.length) {
576
- return false;
577
- }
578
- navigateHistory(view, "FORWARDS");
579
- return true;
580
- }
581
- },
582
- {
583
- mac: "Cmd-ArrowDown",
584
- win: "Ctrl-ArrowDown",
585
- linux: "Ctrl-ArrowDown",
586
- preventDefault: true,
587
- run: (view) => {
588
- const { empty, head } = view.state.selection.main;
589
- if (!empty || head !== view.state.doc.length) {
590
- return false;
591
- }
592
- navigateHistory(view, "FORWARDS");
593
- return true;
594
- }
595
- }
596
- ])
597
- ];
598
- };
599
-
600
568
  // src/themes.ts
601
569
  var import_ayu = require("ayu");
602
570
 
@@ -1279,6 +1247,20 @@ function getThemeExtension(theme, inheritBgColor) {
1279
1247
 
1280
1248
  // src/CypherEditor.tsx
1281
1249
  var import_jsx_runtime = require("react/jsx-runtime");
1250
+ var executeKeybinding = (onExecute) => onExecute ? [
1251
+ {
1252
+ key: "Ctrl-Enter",
1253
+ mac: "Mod-Enter",
1254
+ preventDefault: true,
1255
+ run: (view) => {
1256
+ const doc = view.state.doc.toString();
1257
+ if (doc.trim() !== "") {
1258
+ onExecute(doc);
1259
+ }
1260
+ return true;
1261
+ }
1262
+ }
1263
+ ] : [];
1282
1264
  var themeCompartment = new import_state4.Compartment();
1283
1265
  var keyBindingCompartment = new import_state4.Compartment();
1284
1266
  var ExternalEdit = import_state4.Annotation.define();
@@ -1332,28 +1314,21 @@ var CypherEditor = class extends import_react.Component {
1332
1314
  overrideThemeBackgroundColor: false,
1333
1315
  lineWrap: false,
1334
1316
  extraKeybindings: [],
1335
- initialHistory: [],
1317
+ history: [],
1336
1318
  theme: "light"
1337
1319
  };
1338
1320
  componentDidMount() {
1339
1321
  const {
1340
1322
  theme,
1341
- onExecute,
1342
- initialHistory,
1343
- onNewHistoryEntry,
1344
1323
  extraKeybindings,
1345
1324
  lineWrap,
1346
1325
  overrideThemeBackgroundColor,
1347
1326
  schema,
1348
1327
  lint,
1349
- onChange
1328
+ onChange,
1329
+ onExecute
1350
1330
  } = this.props;
1351
1331
  this.schemaRef.current = { schema, lint };
1352
- const maybeReplMode = onExecute ? replMode({
1353
- onExecute,
1354
- initialHistory,
1355
- onNewHistoryEntry
1356
- }) : [];
1357
1332
  const themeExtension = getThemeExtension(
1358
1333
  theme,
1359
1334
  overrideThemeBackgroundColor
@@ -1372,12 +1347,14 @@ var CypherEditor = class extends import_react.Component {
1372
1347
  ] : [];
1373
1348
  this.editorState.current = import_state4.EditorState.create({
1374
1349
  extensions: [
1375
- maybeReplMode,
1350
+ keyBindingCompartment.of(
1351
+ import_view4.keymap.of([...executeKeybinding(onExecute), ...extraKeybindings])
1352
+ ),
1353
+ replMode(this.props),
1376
1354
  basicNeo4jSetup(),
1377
1355
  themeCompartment.of(themeExtension),
1378
1356
  changeListener,
1379
1357
  cypher(this.schemaRef.current),
1380
- keyBindingCompartment.of(import_view4.keymap.of(extraKeybindings)),
1381
1358
  lineWrap ? import_view4.EditorView.lineWrapping : [],
1382
1359
  (0, import_view4.lineNumbers)({
1383
1360
  formatNumber: (a, state) => {
@@ -1427,13 +1404,21 @@ var CypherEditor = class extends import_react.Component {
1427
1404
  )
1428
1405
  });
1429
1406
  }
1430
- if (prevProps.extraKeybindings !== this.props.extraKeybindings) {
1407
+ if (prevProps.extraKeybindings !== this.props.extraKeybindings || prevProps.onExecute !== this.props.onExecute) {
1431
1408
  this.editorView.current.dispatch({
1432
1409
  effects: keyBindingCompartment.reconfigure(
1433
- import_view4.keymap.of(this.props.extraKeybindings)
1410
+ import_view4.keymap.of([
1411
+ ...executeKeybinding(this.props.onExecute),
1412
+ ...this.props.extraKeybindings
1413
+ ])
1434
1414
  )
1435
1415
  });
1436
1416
  }
1417
+ if (prevProps.history?.length !== this.props.history?.length) {
1418
+ this.editorView.current.dispatch({
1419
+ effects: replaceHistory.of(this.props.history ?? [])
1420
+ });
1421
+ }
1437
1422
  this.schemaRef.current.schema = this.props.schema;
1438
1423
  this.schemaRef.current.lint = this.props.lint;
1439
1424
  }