@neo4j-cypher/react-codemirror 2.0.0-next.40 → 2.0.0-next.41

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.
Files changed (67) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/dist/src/CypherEditor.d.ts +4 -2
  3. package/dist/src/CypherEditor.js +2 -2
  4. package/dist/src/CypherEditor.js.map +1 -1
  5. package/dist/src/CypherEditor.test.js +19 -11
  6. package/dist/src/CypherEditor.test.js.map +1 -1
  7. package/dist/src/e2e_tests/autoCompletion.spec.js +0 -1
  8. package/dist/src/e2e_tests/autoCompletion.spec.js.map +1 -1
  9. package/dist/src/e2e_tests/historyNavigation.spec.js.map +1 -1
  10. package/dist/src/e2e_tests/signatureHelp.spec.js +0 -1
  11. package/dist/src/e2e_tests/signatureHelp.spec.js.map +1 -1
  12. package/dist/src/editorActions.js +83 -18
  13. package/dist/src/editorActions.js.map +1 -1
  14. package/dist/src/historyNavigation.d.ts +1 -1
  15. package/dist/src/historyNavigation.js.map +1 -1
  16. package/dist/src/lang-cypher/autocomplete.d.ts +1 -1
  17. package/dist/src/lang-cypher/autocomplete.js +1 -1
  18. package/dist/src/lang-cypher/autocomplete.js.map +1 -1
  19. package/dist/src/lang-cypher/constants.d.ts +2 -2
  20. package/dist/src/lang-cypher/constants.js.map +1 -1
  21. package/dist/src/lang-cypher/createCypherTheme.d.ts +2 -2
  22. package/dist/src/lang-cypher/createCypherTheme.js +1 -1
  23. package/dist/src/lang-cypher/createCypherTheme.js.map +1 -1
  24. package/dist/src/lang-cypher/langCypher.d.ts +2 -1
  25. package/dist/src/lang-cypher/langCypher.js.map +1 -1
  26. package/dist/src/lang-cypher/lintWorker.mjs +144 -140
  27. package/dist/src/lang-cypher/parser-adapter.d.ts +6 -4
  28. package/dist/src/lang-cypher/parser-adapter.js +4 -1
  29. package/dist/src/lang-cypher/parser-adapter.js.map +1 -1
  30. package/dist/src/lang-cypher/prism-global.d.ts +1 -0
  31. package/dist/src/lang-cypher/prism-global.js +7 -0
  32. package/dist/src/lang-cypher/prism-global.js.map +1 -0
  33. package/dist/src/lang-cypher/signatureHelp.d.ts +2 -2
  34. package/dist/src/lang-cypher/signatureHelp.js +1 -1
  35. package/dist/src/lang-cypher/signatureHelp.js.map +1 -1
  36. package/dist/src/lang-cypher/syntaxValidation.d.ts +1 -1
  37. package/dist/src/lang-cypher/syntaxValidation.js +7 -2
  38. package/dist/src/lang-cypher/syntaxValidation.js.map +1 -1
  39. package/dist/src/neo4jSetup.d.ts +1 -1
  40. package/dist/src/neo4jSetup.js.map +1 -1
  41. package/dist/src/richClipboardCopier.js +2 -2
  42. package/dist/src/richClipboardCopier.js.map +1 -1
  43. package/dist/src/richClipboardCopier.test.js.map +1 -1
  44. package/dist/src/themes.d.ts +2 -2
  45. package/dist/src/themes.js.map +1 -1
  46. package/dist/tsconfig.tsbuildinfo +1 -1
  47. package/package.json +12 -10
  48. package/src/CypherEditor.test.tsx +27 -19
  49. package/src/CypherEditor.tsx +7 -16
  50. package/src/e2e_tests/autoCompletion.spec.tsx +0 -1
  51. package/src/e2e_tests/historyNavigation.spec.tsx +1 -1
  52. package/src/e2e_tests/signatureHelp.spec.tsx +1 -2
  53. package/src/editorActions.ts +103 -22
  54. package/src/historyNavigation.ts +5 -3
  55. package/src/lang-cypher/autocomplete.ts +3 -6
  56. package/src/lang-cypher/constants.ts +3 -2
  57. package/src/lang-cypher/createCypherTheme.ts +12 -10
  58. package/src/lang-cypher/langCypher.ts +2 -4
  59. package/src/lang-cypher/lintWorker.mjs +144 -140
  60. package/src/lang-cypher/parser-adapter.ts +10 -9
  61. package/src/lang-cypher/prism-global.ts +7 -0
  62. package/src/lang-cypher/signatureHelp.ts +7 -7
  63. package/src/lang-cypher/syntaxValidation.ts +9 -4
  64. package/src/neo4jSetup.tsx +3 -3
  65. package/src/richClipboardCopier.test.ts +7 -5
  66. package/src/richClipboardCopier.ts +2 -2
  67. package/src/themes.ts +2 -2
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neo4j-cypher/react-codemirror",
3
- "version": "2.0.0-next.40",
3
+ "version": "2.0.0-next.41",
4
4
  "keywords": [
5
5
  "codemirror",
6
6
  "codemirror 6",
@@ -26,7 +26,9 @@
26
26
  "CHANGELOG.md"
27
27
  ],
28
28
  "type": "module",
29
- "sideEffects": false,
29
+ "sideEffects": [
30
+ "**/lang-cypher/prism-global.js"
31
+ ],
30
32
  "main": "./dist/src/index.js",
31
33
  "types": "./dist/src/index.d.ts",
32
34
  "dependencies": {
@@ -46,23 +48,23 @@
46
48
  "style-mod": "^4.1.2",
47
49
  "vscode-languageserver-types": "^3.17.3",
48
50
  "workerpool": "^9.3.3",
49
- "@neo4j-cypher/language-support": "2.0.0-next.37",
50
- "@neo4j-cypher/lint-worker": "1.10.1-next.14"
51
+ "@neo4j-cypher/language-support": "2.0.0-next.38",
52
+ "@neo4j-cypher/lint-worker": "1.10.1-next.15"
51
53
  },
52
54
  "devDependencies": {
53
55
  "@neo4j-ndl/base": "^3.2.10",
54
- "@playwright/experimental-ct-react": "^1.55.1",
55
- "@playwright/test": "^1.55.1",
56
+ "@playwright/experimental-ct-react": "1.62.1",
57
+ "@playwright/test": "1.62.1",
56
58
  "@types/lodash.debounce": "^4.0.9",
57
59
  "@types/react": "^18.0.28",
58
60
  "@types/react-dom": "^18.0.11",
59
- "@vitejs/plugin-react": "^4.3.1",
61
+ "@vitejs/plugin-react": "^6.1.1",
60
62
  "copyfiles": "^2.4.1",
61
63
  "jsdom": "^24.1.1",
62
- "playwright": "^1.55.1",
64
+ "playwright": "1.62.1",
63
65
  "react": "^18.2.0",
64
66
  "react-dom": "^18.2.0",
65
- "vite": "^4.5.10"
67
+ "vite": "^8.2.2"
66
68
  },
67
69
  "peerDependencies": {
68
70
  "react": "^16.8.0 || ^17.0.0 || ^18.0.0",
@@ -75,7 +77,7 @@
75
77
  "dev": "tsc --watch",
76
78
  "build": "pnpm copy-lint-worker && tsc --declaration --outDir dist/",
77
79
  "copy-lint-worker": "copyfiles -u 4 ../lint-worker/dist/esm/lintWorker.mjs dist/src/lang-cypher && copyfiles -u 4 ../lint-worker/dist/esm/lintWorker.mjs src/lang-cypher",
78
- "clean": "rm -rf {dist,tsconfig.tsbuildinfo}",
80
+ "clean": "rm -rf dist tsconfig*.tsbuildinfo",
79
81
  "test": "vitest run",
80
82
  "test:e2e": "playwright test -c playwright-ct.config.ts",
81
83
  "test:e2e-ui": "playwright test -c playwright-ct.config.ts --ui",
@@ -1,6 +1,6 @@
1
1
  // @vitest-environment jsdom
2
2
 
3
- import { EditorView } from '@codemirror/view';
3
+ import type { EditorView } from '@codemirror/view';
4
4
  import { createRef } from 'react';
5
5
  import { createRoot } from 'react-dom/client';
6
6
  import { act } from 'react-dom/test-utils';
@@ -13,22 +13,24 @@ let root: ReturnType<typeof createRoot>;
13
13
 
14
14
  const ref = createRef<CypherEditor>();
15
15
  let value = '';
16
- const onChange = vi.fn((v: string) => {
16
+ const onChange = vi.fn<(v: string) => void>((v) => {
17
17
  value = v;
18
18
  rerender();
19
19
  });
20
20
 
21
- global.IS_REACT_ACT_ENVIRONMENT = true;
21
+ (global as any).IS_REACT_ACT_ENVIRONMENT = true;
22
22
  const DEBOUNCE_TIME_WITH_MARGIN = DEBOUNCE_TIME + 100;
23
23
 
24
24
  /** Avoids crash in test environment */
25
25
  function mockEditorView(editorView: EditorView) {
26
- editorView.coordsAtPos = vi.fn().mockReturnValue({
27
- left: 0,
28
- top: 0,
29
- right: 0,
30
- bottom: 0,
31
- });
26
+ editorView.coordsAtPos = vi
27
+ .fn<() => { left: number; top: number; right: number; bottom: number }>()
28
+ .mockReturnValue({
29
+ left: 0,
30
+ top: 0,
31
+ right: 0,
32
+ bottom: 0,
33
+ });
32
34
  }
33
35
 
34
36
  async function debounce() {
@@ -107,24 +109,28 @@ test('props.value set to undefined preserves editorValue', () => {
107
109
  expect(getEditorValue()).toBe('initial');
108
110
  });
109
111
 
110
- // value updates from outside onExecute are overwritten by pending updates
111
- test.fails('new props.value should cancel onChange', async () => {
112
+ // This test documents unexpected behaviour:
113
+ // value updates (from outside onExecute) are overwritten by pending updates.
114
+ test('new props.value should cancel onChange', async () => {
112
115
  // 1. value is updated internally
113
116
  ref.current.setValueAndFocus('update');
114
117
 
115
118
  // 2. editor is rerendered with a new value while a value update is still pending
119
+ // the update to 'new external value' is overwritten by the pending update to 'update'
116
120
  value = 'new external value';
117
121
  rerender();
118
122
 
119
123
  await debounce();
120
124
 
121
- // expect(onChange).not.toHaveBeenCalled();
122
- expect(getEditorValue()).toBe('new external value');
123
- expect(value).toBe('new external value');
125
+ // NOTE: These assertions currently check for the WRONG behavior (they are inverted).
126
+ expect(onChange).toHaveBeenCalled();
127
+ expect(getEditorValue()).not.toBe('new external value');
128
+ expect(value).not.toBe('new external value');
124
129
  });
125
130
 
126
- // value updates from outside onExecute are overwritten by pending updates
127
- test.fails('new props.value set to same value should cancel onChange', async () => {
131
+ // This test documents unexpected behaviour:
132
+ // value updates (from outside onExecute) are overwritten by pending updates
133
+ test('new props.value set to same value should cancel onChange', async () => {
128
134
  // 1. value is set initially
129
135
  value = 'same value';
130
136
  rerender();
@@ -133,14 +139,16 @@ test.fails('new props.value set to same value should cancel onChange', async ()
133
139
  ref.current.setValueAndFocus('update');
134
140
 
135
141
  // 3. editor is rerendered with a new value while a value update is still pending
142
+ // the update to 'same value' is overwritten by the pending update to 'update'
136
143
  value = 'same value';
137
144
  rerender();
138
145
 
139
146
  await debounce();
140
147
 
141
- // expect(onChange).not.toHaveBeenCalled();
142
- expect(getEditorValue()).toBe('same value');
143
- expect(value).toBe('same value');
148
+ // NOTE: These assertions currently check for the WRONG behavior (they are inverted).
149
+ expect(onChange).toHaveBeenCalled();
150
+ expect(getEditorValue()).not.toBe('same value');
151
+ expect(value).not.toBe('same value');
144
152
  });
145
153
 
146
154
  test('rerender should not cancel onChange', async () => {
@@ -1,18 +1,8 @@
1
1
  import { insertNewline } from '@codemirror/commands';
2
- import {
3
- Annotation,
4
- Compartment,
5
- EditorState,
6
- Extension,
7
- } from '@codemirror/state';
8
- import {
9
- EditorView,
10
- KeyBinding,
11
- keymap,
12
- lineNumbers,
13
- placeholder,
14
- ViewUpdate,
15
- } from '@codemirror/view';
2
+ import type { Extension } from '@codemirror/state';
3
+ import { Annotation, Compartment, EditorState } from '@codemirror/state';
4
+ import type { KeyBinding, ViewUpdate } from '@codemirror/view';
5
+ import { EditorView, keymap, lineNumbers, placeholder } from '@codemirror/view';
16
6
  import {
17
7
  createInlinePanelController,
18
8
  type InlinePanelCallbacks,
@@ -37,12 +27,13 @@ import {
37
27
  replaceHistory,
38
28
  replMode as historyNavigation,
39
29
  } from './historyNavigation';
40
- import { cypher, CypherConfig } from './lang-cypher/langCypher';
30
+ import type { CypherConfig } from './lang-cypher/langCypher';
31
+ import { cypher } from './lang-cypher/langCypher';
41
32
  import { cleanupWorkers } from './lang-cypher/syntaxValidation';
42
33
  import { basicNeo4jSetup } from './neo4jSetup';
43
34
  import { getThemeExtension } from './themes';
44
35
  import { richClipboardCopier } from './richClipboardCopier';
45
- import { LintWorker } from '@neo4j-cypher/lint-worker';
36
+ import type { LintWorker } from '@neo4j-cypher/lint-worker';
46
37
  import workerpool from 'workerpool';
47
38
 
48
39
  type DomEventHandlers = Parameters<typeof EditorView.domEventHandlers>[0];
@@ -1,4 +1,3 @@
1
- /* eslint-disable @typescript-eslint/unbound-method */
2
1
  import { testData } from '@neo4j-cypher/language-support';
3
2
  import { expect, test } from '@playwright/experimental-ct-react';
4
3
  import type { Page } from '@playwright/test';
@@ -284,7 +284,7 @@ test('test onExecute', async ({ page, mount }) => {
284
284
  const execButton = isMac ? 'Meta+Enter' : 'Control+Enter';
285
285
 
286
286
  const initialValue = 'MATCH (n) RETURN n;';
287
- const history = [];
287
+ const history: string[] = [];
288
288
 
289
289
  const onExecute = (cmd: string) => {
290
290
  history.unshift(cmd);
@@ -1,7 +1,6 @@
1
- /* eslint-disable @typescript-eslint/unbound-method */
2
1
  import { testData } from '@neo4j-cypher/language-support';
3
2
  import { expect, test } from '@playwright/experimental-ct-react';
4
- import { Locator } from 'playwright/test';
3
+ import type { Locator } from 'playwright/test';
5
4
  import { CypherEditor } from '../CypherEditor';
6
5
 
7
6
  test.use({ viewport: { width: 1000, height: 500 } });
@@ -2,6 +2,7 @@ import { StateEffect, StateField, type Extension } from '@codemirror/state';
2
2
  import {
3
3
  Decoration,
4
4
  EditorView,
5
+ type Rect,
5
6
  ViewPlugin,
6
7
  type ViewUpdate,
7
8
  WidgetType,
@@ -40,10 +41,23 @@ export type EditorActionsController = {
40
41
  * `absolute` on the editor element (which does not scroll). It never moves
41
42
  * when the document grows, when an inline panel opens above the first line,
42
43
  * or when the content scrolls — content simply scrolls behind it.
44
+ *
45
+ * The overlay is measured against the scroller's visible box rather than
46
+ * against the spacer or the content: the spacer moves down the document
47
+ * whenever something renders above the first line (an inline panel, the
48
+ * deleted lines of a diff), and the content reaches past the right edge as
49
+ * soon as it overflows.
50
+ * Vertically the cluster is centred on the first line.
43
51
  */
44
52
 
45
53
  const SPACER_BOTTOM_GAP = 2;
46
54
  const SPACER_LEFT_GAP = 4;
55
+ /**
56
+ * Floor for the overlay's inset from the visible right edge, so it stays off
57
+ * the content's last pixel even if a theme zeroes `.cm-line`'s right padding
58
+ * (the base theme's 2px, which is what normally provides the inset).
59
+ */
60
+ const MIN_OVERLAY_RIGHT_INSET = 2;
47
61
 
48
62
  export function createEditorActionsController(): EditorActionsController {
49
63
  const setActiveEffect = StateEffect.define<boolean>();
@@ -74,6 +88,38 @@ export function createEditorActionsController(): EditorActionsController {
74
88
  return true;
75
89
  }
76
90
 
91
+ /**
92
+ * The spacer floats right, so CodeMirror's default — the widget's own box —
93
+ * puts the caret at the right edge of the cluster whenever the spacer is
94
+ * the only thing it can measure on the first line (an empty document).
95
+ * Report the start of the line's inline content instead: the node after
96
+ * the spacer (text, a placeholder, or CodeMirror's trailing `<br>`).
97
+ */
98
+ coordsAt(dom: HTMLElement): Rect | null {
99
+ const next = dom.nextSibling;
100
+ if (!next) {
101
+ return null;
102
+ }
103
+ let rects: DOMRectList;
104
+ if (next instanceof Element) {
105
+ rects = next.getClientRects();
106
+ } else {
107
+ const range = document.createRange();
108
+ range.selectNodeContents(next);
109
+ rects = range.getClientRects();
110
+ }
111
+ const rect = rects[0];
112
+ if (!rect) {
113
+ return null;
114
+ }
115
+ return {
116
+ left: rect.left,
117
+ right: rect.left,
118
+ top: rect.top,
119
+ bottom: rect.bottom,
120
+ };
121
+ }
122
+
77
123
  ignoreEvent(): boolean {
78
124
  return true;
79
125
  }
@@ -136,13 +182,11 @@ export function createEditorActionsController(): EditorActionsController {
136
182
  `${container.offsetWidth}px`,
137
183
  );
138
184
  view.dom.style.setProperty(
139
- '--cm-editor-actions-height',
140
- `${container.offsetHeight}px`,
141
- );
142
- view.dom.style.setProperty(
143
- '--cm-editor-actions-content-min-height',
144
- `${container.offsetHeight + SPACER_BOTTOM_GAP}px`,
185
+ '--cm-editor-actions-reserved-width',
186
+ `${container.offsetWidth + SPACER_LEFT_GAP}px`,
145
187
  );
188
+ // The spacer's height follows the overlay's position, so `align`
189
+ // owns it.
146
190
  this.align(view);
147
191
  });
148
192
  this.resizeObserver.observe(container);
@@ -153,28 +197,52 @@ export function createEditorActionsController(): EditorActionsController {
153
197
  }
154
198
 
155
199
  private align(view: EditorView): void {
156
- view.requestMeasure<{ top: number; right: number } | null>({
200
+ view.requestMeasure<{
201
+ top: number;
202
+ right: number;
203
+ spacerHeight: number;
204
+ contentMinHeight: number;
205
+ } | null>({
157
206
  read: () => {
158
207
  if (!this.dom) {
159
208
  return null;
160
209
  }
161
210
  const editorRect = view.dom.getBoundingClientRect();
162
- const spacer = view.dom.querySelector('.cm-editor-actions-spacer');
163
- let topClient: number;
164
- let rightClient: number;
165
- if (spacer) {
166
- const rect = spacer.getBoundingClientRect();
167
- topClient = rect.top;
168
- rightClient = rect.right;
169
- } else {
170
- const rect = view.contentDOM.getBoundingClientRect();
171
- const style = window.getComputedStyle(view.contentDOM);
172
- topClient = rect.top + (parseFloat(style.paddingTop) || 0);
173
- rightClient = rect.right - (parseFloat(style.paddingRight) || 0);
174
- }
211
+ const scrollerRect = view.scrollDOM.getBoundingClientRect();
212
+ const style = window.getComputedStyle(view.contentDOM);
213
+ const visibleRight = scrollerRect.left + view.scrollDOM.clientWidth;
214
+ // Match the inset `.cm-line`'s right padding gives the spacer, so
215
+ // the overlay lands on the space the spacer reserves and stays off
216
+ // `contentRect.right - 1`, the pixel CodeMirror hit-tests to
217
+ // measure a wrapped line's selection. Cover it and the first
218
+ // line's highlight collapses to zero width — hence the floor.
219
+ const line = view.contentDOM.querySelector('.cm-line');
220
+ const lineRightPadding = line
221
+ ? parseFloat(window.getComputedStyle(line).paddingRight) || 0
222
+ : 0;
223
+
224
+ const contentPaddingTop = parseFloat(style.paddingTop) || 0;
225
+ const height = this.dom.offsetHeight;
226
+ // How far the cluster has to rise above the first line's top to
227
+ // sit centred on it, limited to the padding it can rise into.
228
+ const lift = Math.min(
229
+ Math.max((height - view.defaultLineHeight) / 2, 0),
230
+ contentPaddingTop,
231
+ );
232
+
175
233
  return {
176
- top: topClient - editorRect.top + view.scrollDOM.scrollTop,
177
- right: editorRect.right - rightClient - view.scrollDOM.scrollLeft,
234
+ top: scrollerRect.top - editorRect.top + contentPaddingTop - lift,
235
+ right:
236
+ editorRect.right -
237
+ visibleRight +
238
+ (parseFloat(style.paddingRight) || 0) +
239
+ Math.max(lineRightPadding, MIN_OVERLAY_RIGHT_INSET),
240
+ // The spacer starts at the first line's top, so it only needs to
241
+ // clear the part of the cluster that hangs below it.
242
+ spacerHeight: height - lift,
243
+ // A floor under the content, so an empty document is still tall
244
+ // enough to hold the overlay.
245
+ contentMinHeight: contentPaddingTop - lift + height,
178
246
  };
179
247
  },
180
248
  write: (pos) => {
@@ -189,6 +257,14 @@ export function createEditorActionsController(): EditorActionsController {
189
257
  '--cm-editor-actions-right',
190
258
  `${pos.right}px`,
191
259
  );
260
+ view.dom.style.setProperty(
261
+ '--cm-editor-actions-height',
262
+ `${pos.spacerHeight}px`,
263
+ );
264
+ view.dom.style.setProperty(
265
+ '--cm-editor-actions-content-min-height',
266
+ `${pos.contentMinHeight}px`,
267
+ );
192
268
  },
193
269
  });
194
270
  }
@@ -206,6 +282,7 @@ export function createEditorActionsController(): EditorActionsController {
206
282
  root.style.removeProperty('--cm-editor-actions-width');
207
283
  root.style.removeProperty('--cm-editor-actions-height');
208
284
  root.style.removeProperty('--cm-editor-actions-content-min-height');
285
+ root.style.removeProperty('--cm-editor-actions-reserved-width');
209
286
  root.style.removeProperty('--cm-editor-actions-top');
210
287
  root.style.removeProperty('--cm-editor-actions-right');
211
288
  }
@@ -230,6 +307,10 @@ export function createEditorActionsController(): EditorActionsController {
230
307
  WebkitUserSelect: 'none',
231
308
  pointerEvents: 'none',
232
309
  },
310
+ // The spacer only clears the first line, so a panel above it makes its own room.
311
+ '.cm-inline-panel': {
312
+ paddingRight: 'var(--cm-editor-actions-reserved-width, 0px)',
313
+ },
233
314
  '.cm-placeholder': {
234
315
  display: 'inline',
235
316
  },
@@ -1,5 +1,7 @@
1
- import { Extension, StateEffect } from '@codemirror/state';
2
- import { EditorView, keymap } from '@codemirror/view';
1
+ import type { Extension } from '@codemirror/state';
2
+ import { StateEffect } from '@codemirror/state';
3
+ import type { EditorView } from '@codemirror/view';
4
+ import { keymap } from '@codemirror/view';
3
5
 
4
6
  import { StateField } from '@codemirror/state';
5
7
 
@@ -10,7 +12,7 @@ type HistoryState = {
10
12
  documentUpdate: string | null;
11
13
  };
12
14
  const DRAFT_ENTRY_INDEX = -1;
13
- const historyInitialState = {
15
+ const historyInitialState: HistoryState = {
14
16
  history: [],
15
17
  index: DRAFT_ENTRY_INDEX,
16
18
  documentUpdate: null,
@@ -1,14 +1,11 @@
1
- import {
2
- Completion,
3
- CompletionSource,
4
- snippet,
5
- } from '@codemirror/autocomplete';
1
+ import type { Completion, CompletionSource } from '@codemirror/autocomplete';
2
+ import { snippet } from '@codemirror/autocomplete';
6
3
  import { shouldAutoCompleteYield } from '@neo4j-cypher/language-support';
7
4
  import {
8
5
  CompletionItemKind,
9
6
  CompletionItemTag,
10
7
  } from 'vscode-languageserver-types';
11
- import { CompletionItemIcons } from '../icons';
8
+ import type { CompletionItemIcons } from '../icons';
12
9
  import type { CypherConfig } from './langCypher';
13
10
  import { getDocString } from './utils';
14
11
 
@@ -1,8 +1,9 @@
1
1
  import { languageDataProp } from '@codemirror/language';
2
2
  import type { Facet } from '@codemirror/state';
3
3
  import { NodeSet, NodeType } from '@lezer/common';
4
- import { styleTags, Tag, tags } from '@lezer/highlight';
5
- import { CypherTokenType } from '@neo4j-cypher/language-support';
4
+ import type { Tag } from '@lezer/highlight';
5
+ import { styleTags, tags } from '@lezer/highlight';
6
+ import type { CypherTokenType } from '@neo4j-cypher/language-support';
6
7
 
7
8
  export const cypherTokenTypeToNode = (facet: Facet<unknown>) => ({
8
9
  topNode: NodeType.define({
@@ -1,13 +1,11 @@
1
- import {
2
- HighlightStyle,
3
- syntaxHighlighting,
4
- TagStyle,
5
- } from '@codemirror/language';
6
- import { Extension } from '@codemirror/state';
1
+ import type { TagStyle } from '@codemirror/language';
2
+ import { HighlightStyle, syntaxHighlighting } from '@codemirror/language';
3
+ import type { Extension } from '@codemirror/state';
7
4
  import { EditorView } from '@codemirror/view';
8
5
  import { CypherTokenType } from '@neo4j-cypher/language-support';
9
- import { StyleSpec } from 'style-mod';
10
- import { HighlightedCypherTokenTypes, tokenTypeToStyleTag } from './constants';
6
+ import type { StyleSpec } from 'style-mod';
7
+ import type { HighlightedCypherTokenTypes } from './constants';
8
+ import { tokenTypeToStyleTag } from './constants';
11
9
  import {
12
10
  byWordSvg,
13
11
  caseSensitiveSvg,
@@ -255,8 +253,12 @@ export const createCypherTheme = ({
255
253
 
256
254
  const themeExtension = EditorView.theme(themeOptions, { dark });
257
255
 
258
- const styles = Object.entries(highlightStyles).map(
259
- ([token, color]: [HighlightedCypherTokenTypes, string]): TagStyle => ({
256
+ const styles = (
257
+ Object.entries(highlightStyles) as Array<
258
+ [HighlightedCypherTokenTypes, string]
259
+ >
260
+ ).map(
261
+ ([token, color]): TagStyle => ({
260
262
  tag: tokenTypeToStyleTag[token],
261
263
  color,
262
264
  class: token === CypherTokenType.consoleCommand ? 'cm-bold' : undefined,
@@ -4,10 +4,8 @@ import {
4
4
  Language,
5
5
  LanguageSupport,
6
6
  } from '@codemirror/language';
7
- import {
8
- CypherLanguageService,
9
- type DbSchema,
10
- } from '@neo4j-cypher/language-support';
7
+ import type { CypherLanguageService } from '@neo4j-cypher/language-support';
8
+ import { type DbSchema } from '@neo4j-cypher/language-support';
11
9
  import { completionStyles, cypherAutocomplete } from './autocomplete';
12
10
  import { ParserAdapter } from './parser-adapter';
13
11
  import { signatureHelpTooltip } from './signatureHelp';