@neo4j-cypher/react-codemirror 0.0.0-canary-20250423075344

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 (138) hide show
  1. package/CHANGELOG.md +279 -0
  2. package/LICENSE.md +201 -0
  3. package/README.md +35 -0
  4. package/dist/CypherEditor.d.ts +192 -0
  5. package/dist/CypherEditor.js +326 -0
  6. package/dist/CypherEditor.js.map +1 -0
  7. package/dist/CypherEditor.test.d.ts +1 -0
  8. package/dist/CypherEditor.test.js +151 -0
  9. package/dist/CypherEditor.test.js.map +1 -0
  10. package/dist/constants.d.ts +1 -0
  11. package/dist/constants.js +2 -0
  12. package/dist/constants.js.map +1 -0
  13. package/dist/e2e_tests/autoCompletion.spec.d.ts +1 -0
  14. package/dist/e2e_tests/autoCompletion.spec.js +318 -0
  15. package/dist/e2e_tests/autoCompletion.spec.js.map +1 -0
  16. package/dist/e2e_tests/configuration.spec.d.ts +1 -0
  17. package/dist/e2e_tests/configuration.spec.js +83 -0
  18. package/dist/e2e_tests/configuration.spec.js.map +1 -0
  19. package/dist/e2e_tests/debounce.spec.d.ts +1 -0
  20. package/dist/e2e_tests/debounce.spec.js +66 -0
  21. package/dist/e2e_tests/debounce.spec.js.map +1 -0
  22. package/dist/e2e_tests/e2eUtils.d.ts +13 -0
  23. package/dist/e2e_tests/e2eUtils.js +71 -0
  24. package/dist/e2e_tests/e2eUtils.js.map +1 -0
  25. package/dist/e2e_tests/extraKeybindings.spec.d.ts +1 -0
  26. package/dist/e2e_tests/extraKeybindings.spec.js +43 -0
  27. package/dist/e2e_tests/extraKeybindings.spec.js.map +1 -0
  28. package/dist/e2e_tests/historyNavigation.spec.d.ts +1 -0
  29. package/dist/e2e_tests/historyNavigation.spec.js +227 -0
  30. package/dist/e2e_tests/historyNavigation.spec.js.map +1 -0
  31. package/dist/e2e_tests/performanceTest.spec.d.ts +6 -0
  32. package/dist/e2e_tests/performanceTest.spec.js +97 -0
  33. package/dist/e2e_tests/performanceTest.spec.js.map +1 -0
  34. package/dist/e2e_tests/sanityChecks.spec.d.ts +1 -0
  35. package/dist/e2e_tests/sanityChecks.spec.js +53 -0
  36. package/dist/e2e_tests/sanityChecks.spec.js.map +1 -0
  37. package/dist/e2e_tests/signatureHelp.spec.d.ts +1 -0
  38. package/dist/e2e_tests/signatureHelp.spec.js +228 -0
  39. package/dist/e2e_tests/signatureHelp.spec.js.map +1 -0
  40. package/dist/e2e_tests/snippets.spec.d.ts +1 -0
  41. package/dist/e2e_tests/snippets.spec.js +62 -0
  42. package/dist/e2e_tests/snippets.spec.js.map +1 -0
  43. package/dist/e2e_tests/syntaxHighlighting.spec.d.ts +1 -0
  44. package/dist/e2e_tests/syntaxHighlighting.spec.js +90 -0
  45. package/dist/e2e_tests/syntaxHighlighting.spec.js.map +1 -0
  46. package/dist/e2e_tests/syntaxValidation.spec.d.ts +1 -0
  47. package/dist/e2e_tests/syntaxValidation.spec.js +116 -0
  48. package/dist/e2e_tests/syntaxValidation.spec.js.map +1 -0
  49. package/dist/historyNavigation.d.ts +7 -0
  50. package/dist/historyNavigation.js +163 -0
  51. package/dist/historyNavigation.js.map +1 -0
  52. package/dist/icons.d.ts +2 -0
  53. package/dist/icons.js +62 -0
  54. package/dist/icons.js.map +1 -0
  55. package/dist/index.d.ts +4 -0
  56. package/dist/index.js +5 -0
  57. package/dist/index.js.map +1 -0
  58. package/dist/lang-cypher/autocomplete.d.ts +6 -0
  59. package/dist/lang-cypher/autocomplete.js +115 -0
  60. package/dist/lang-cypher/autocomplete.js.map +1 -0
  61. package/dist/lang-cypher/constants.d.ts +42 -0
  62. package/dist/lang-cypher/constants.js +69 -0
  63. package/dist/lang-cypher/constants.js.map +1 -0
  64. package/dist/lang-cypher/contants.test.d.ts +1 -0
  65. package/dist/lang-cypher/contants.test.js +103 -0
  66. package/dist/lang-cypher/contants.test.js.map +1 -0
  67. package/dist/lang-cypher/createCypherTheme.d.ts +26 -0
  68. package/dist/lang-cypher/createCypherTheme.js +182 -0
  69. package/dist/lang-cypher/createCypherTheme.js.map +1 -0
  70. package/dist/lang-cypher/langCypher.d.ts +14 -0
  71. package/dist/lang-cypher/langCypher.js +23 -0
  72. package/dist/lang-cypher/langCypher.js.map +1 -0
  73. package/dist/lang-cypher/lintWorker.d.ts +12 -0
  74. package/dist/lang-cypher/lintWorker.js +14 -0
  75. package/dist/lang-cypher/lintWorker.js.map +1 -0
  76. package/dist/lang-cypher/parser-adapter.d.ts +19 -0
  77. package/dist/lang-cypher/parser-adapter.js +113 -0
  78. package/dist/lang-cypher/parser-adapter.js.map +1 -0
  79. package/dist/lang-cypher/signatureHelp.d.ts +4 -0
  80. package/dist/lang-cypher/signatureHelp.js +109 -0
  81. package/dist/lang-cypher/signatureHelp.js.map +1 -0
  82. package/dist/lang-cypher/syntaxValidation.d.ts +4 -0
  83. package/dist/lang-cypher/syntaxValidation.js +52 -0
  84. package/dist/lang-cypher/syntaxValidation.js.map +1 -0
  85. package/dist/lang-cypher/themeIcons.d.ts +7 -0
  86. package/dist/lang-cypher/themeIcons.js +22 -0
  87. package/dist/lang-cypher/themeIcons.js.map +1 -0
  88. package/dist/lang-cypher/utils.d.ts +2 -0
  89. package/dist/lang-cypher/utils.js +10 -0
  90. package/dist/lang-cypher/utils.js.map +1 -0
  91. package/dist/ndlTokensCopy.d.ts +570 -0
  92. package/dist/ndlTokensCopy.js +571 -0
  93. package/dist/ndlTokensCopy.js.map +1 -0
  94. package/dist/ndlTokensCopy.test.d.ts +1 -0
  95. package/dist/ndlTokensCopy.test.js +12 -0
  96. package/dist/ndlTokensCopy.test.js.map +1 -0
  97. package/dist/neo4jSetup.d.ts +6 -0
  98. package/dist/neo4jSetup.js +120 -0
  99. package/dist/neo4jSetup.js.map +1 -0
  100. package/dist/themes.d.ts +11 -0
  101. package/dist/themes.js +93 -0
  102. package/dist/themes.js.map +1 -0
  103. package/dist/tsconfig.tsbuildinfo +1 -0
  104. package/package.json +82 -0
  105. package/src/CypherEditor.test.tsx +200 -0
  106. package/src/CypherEditor.tsx +607 -0
  107. package/src/constants.ts +1 -0
  108. package/src/e2e_tests/autoCompletion.spec.tsx +546 -0
  109. package/src/e2e_tests/configuration.spec.tsx +111 -0
  110. package/src/e2e_tests/debounce.spec.tsx +106 -0
  111. package/src/e2e_tests/e2eUtils.ts +97 -0
  112. package/src/e2e_tests/extraKeybindings.spec.tsx +55 -0
  113. package/src/e2e_tests/historyNavigation.spec.tsx +315 -0
  114. package/src/e2e_tests/performanceTest.spec.tsx +163 -0
  115. package/src/e2e_tests/sanityChecks.spec.tsx +72 -0
  116. package/src/e2e_tests/signatureHelp.spec.tsx +445 -0
  117. package/src/e2e_tests/snippets.spec.tsx +92 -0
  118. package/src/e2e_tests/syntaxHighlighting.spec.tsx +200 -0
  119. package/src/e2e_tests/syntaxValidation.spec.tsx +243 -0
  120. package/src/historyNavigation.ts +191 -0
  121. package/src/icons.ts +90 -0
  122. package/src/index.ts +4 -0
  123. package/src/lang-cypher/autocomplete.ts +147 -0
  124. package/src/lang-cypher/constants.ts +88 -0
  125. package/src/lang-cypher/contants.test.ts +108 -0
  126. package/src/lang-cypher/createCypherTheme.ts +249 -0
  127. package/src/lang-cypher/langCypher.ts +43 -0
  128. package/src/lang-cypher/lintWorker.ts +31 -0
  129. package/src/lang-cypher/parser-adapter.ts +145 -0
  130. package/src/lang-cypher/signatureHelp.ts +151 -0
  131. package/src/lang-cypher/syntaxValidation.ts +66 -0
  132. package/src/lang-cypher/themeIcons.ts +27 -0
  133. package/src/lang-cypher/utils.ts +9 -0
  134. package/src/ndlTokensCopy.test.ts +12 -0
  135. package/src/ndlTokensCopy.ts +570 -0
  136. package/src/neo4jSetup.tsx +190 -0
  137. package/src/themes.ts +105 -0
  138. package/src/viteEnv.d.ts +1 -0
@@ -0,0 +1,190 @@
1
+ import {
2
+ acceptCompletion,
3
+ autocompletion,
4
+ clearSnippet,
5
+ closeBrackets,
6
+ closeBracketsKeymap,
7
+ closeCompletion,
8
+ completionKeymap,
9
+ nextSnippetField,
10
+ prevSnippetField,
11
+ snippetKeymap,
12
+ } from '@codemirror/autocomplete';
13
+ import {
14
+ defaultKeymap,
15
+ history,
16
+ historyKeymap,
17
+ indentLess,
18
+ indentMore,
19
+ } from '@codemirror/commands';
20
+ import {
21
+ bracketMatching,
22
+ defaultHighlightStyle,
23
+ foldKeymap,
24
+ indentOnInput,
25
+ syntaxHighlighting,
26
+ } from '@codemirror/language';
27
+ import { highlightSelectionMatches, searchKeymap } from '@codemirror/search';
28
+ import { EditorState, Extension, StateCommand } from '@codemirror/state';
29
+ import {
30
+ Command,
31
+ crosshairCursor,
32
+ drawSelection,
33
+ dropCursor,
34
+ EditorView,
35
+ highlightSpecialChars,
36
+ KeyBinding,
37
+ keymap,
38
+ rectangularSelection,
39
+ } from '@codemirror/view';
40
+
41
+ import { lintKeymap } from '@codemirror/lint';
42
+ import { getIconForType } from './icons';
43
+
44
+ const insertTab: StateCommand = (cmd) => {
45
+ // if there is a selection we should indent the selected text, but if not insert
46
+ // two spaces as per the cypher style guide
47
+ if (cmd.state.selection.main.from === cmd.state.selection.main.to) {
48
+ cmd.dispatch(
49
+ cmd.state.update({
50
+ changes: {
51
+ from: cmd.state.selection.main.to,
52
+ to: cmd.state.selection.main.to,
53
+ insert: ' ',
54
+ },
55
+ selection: { anchor: cmd.state.selection.main.to + 2 },
56
+ }),
57
+ );
58
+ } else {
59
+ indentMore(cmd);
60
+ }
61
+ return true;
62
+ };
63
+
64
+ type SetupProps = {
65
+ moveFocusOnTab?: boolean;
66
+ };
67
+
68
+ export const basicNeo4jSetup = ({
69
+ moveFocusOnTab = false,
70
+ }: SetupProps): Extension[] => {
71
+ const keymaps: KeyBinding[] = [
72
+ closeBracketsKeymap,
73
+ defaultKeymap,
74
+ searchKeymap,
75
+ historyKeymap,
76
+ foldKeymap,
77
+ completionKeymap,
78
+ lintKeymap,
79
+ ].flat();
80
+
81
+ if (!moveFocusOnTab) {
82
+ keymaps.push(
83
+ {
84
+ key: 'Tab',
85
+ preventDefault: true,
86
+ run: acceptCompletion,
87
+ },
88
+ {
89
+ key: 'Tab',
90
+ preventDefault: true,
91
+ run: insertTab,
92
+ },
93
+ {
94
+ key: 'Shift-Tab',
95
+ preventDefault: true,
96
+ run: indentLess,
97
+ },
98
+ );
99
+ }
100
+
101
+ const extensions: Extension[] = [];
102
+
103
+ extensions.push(highlightSpecialChars());
104
+ extensions.push(history());
105
+
106
+ extensions.push(drawSelection());
107
+ extensions.push(dropCursor());
108
+ extensions.push(EditorState.allowMultipleSelections.of(true));
109
+ extensions.push(indentOnInput());
110
+ extensions.push(
111
+ syntaxHighlighting(defaultHighlightStyle, { fallback: true }),
112
+ );
113
+
114
+ extensions.push(bracketMatching());
115
+ extensions.push(closeBrackets());
116
+ extensions.push(
117
+ autocompletion({
118
+ icons: false,
119
+ interactionDelay: 5,
120
+ addToOptions: [
121
+ {
122
+ render(completion, state) {
123
+ const isDarkTheme = state.facet(EditorView.darkTheme);
124
+ const icon = document.createElement('span');
125
+
126
+ icon.innerHTML = getIconForType(completion.type, isDarkTheme);
127
+
128
+ const svgElement = icon.children[0] as SVGElement;
129
+
130
+ svgElement.style.display = 'inline';
131
+ svgElement.style.marginRight = '5px';
132
+ return icon;
133
+ },
134
+ position: 20,
135
+ },
136
+ ],
137
+ }),
138
+ );
139
+
140
+ extensions.push(rectangularSelection());
141
+ extensions.push(crosshairCursor());
142
+ extensions.push(highlightSelectionMatches());
143
+
144
+ extensions.push(keymap.of(keymaps));
145
+
146
+ extensions.push(
147
+ snippetKeymap.of([
148
+ {
149
+ key: 'Tab',
150
+ run: acceptCompletionOrGotoNextSnippet,
151
+ shift: acceptCompletionOrGotoPrevSnippet,
152
+ },
153
+ { key: 'Escape', run: closeCompletionsOrClearSnippets },
154
+ ]),
155
+ );
156
+
157
+ return extensions;
158
+ };
159
+
160
+ // The logic to check if there's a completion open is surprisingly complex
161
+ // https://github.com/codemirror/autocomplete/blob/5ad2ebc861f2f61cdc943fc087a5bfb756a7d0fa/src/view.ts#L31
162
+ // For example it respects an interaction delay, so we can't just check if the completion is open
163
+ // instead we just run the acceptCompletion command which returns true if a completion was accepted
164
+ // in that case we know that we shouldn't move to the next snippet field
165
+ const acceptCompletionOrGotoNextSnippet: Command = (view: EditorView) => {
166
+ const didCompletion = acceptCompletion(view);
167
+ if (didCompletion) {
168
+ return true;
169
+ }
170
+
171
+ return nextSnippetField(view);
172
+ };
173
+
174
+ const acceptCompletionOrGotoPrevSnippet: Command = (view: EditorView) => {
175
+ const didCompletion = acceptCompletion(view);
176
+ if (didCompletion) {
177
+ return true;
178
+ }
179
+
180
+ return prevSnippetField(view);
181
+ };
182
+
183
+ const closeCompletionsOrClearSnippets: Command = (view: EditorView) => {
184
+ const closedCompletions = closeCompletion(view);
185
+ if (closedCompletions) {
186
+ return true;
187
+ }
188
+
189
+ return clearSnippet(view);
190
+ };
package/src/themes.ts ADDED
@@ -0,0 +1,105 @@
1
+ import { Extension } from '@codemirror/state';
2
+ import {
3
+ createCypherTheme,
4
+ ThemeOptions,
5
+ } from './lang-cypher/createCypherTheme';
6
+ import { tokens } from './ndlTokensCopy';
7
+
8
+ export const lightThemeConstants: ThemeOptions = {
9
+ dark: false,
10
+ editorSettings: {
11
+ background: '#FEFEFE',
12
+ foreground: '#545454',
13
+ gutterForeground: '#a3a7ae',
14
+ selection: tokens.colors.neutral['20'],
15
+ textMatchingSelection: tokens.colors.lavender['15'],
16
+ cursor: '#000000',
17
+ autoCompletionPanel: {
18
+ selectedColor: '#cce2ff',
19
+ matchingTextColor: '#0066bf',
20
+ backgroundColor: '#F3F4F5',
21
+ },
22
+ searchPanel: {
23
+ background: '#FEFEFE',
24
+ text: '#545454',
25
+ buttonHoverBackground: tokens.theme.light.palette.neutral.bg.strong,
26
+ },
27
+ },
28
+ highlightStyles: {
29
+ comment: tokens.palette.code.light.comment,
30
+ keyword: tokens.palette.code.light.keyword,
31
+ keywordLiteral: tokens.palette.code.light.keywordLiteral,
32
+ label: tokens.palette.code.light.label,
33
+ predicateFunction: tokens.palette.code.light.predicateFunction,
34
+ function: tokens.palette.code.light.function,
35
+ procedure: tokens.palette.code.light.procedure,
36
+ stringLiteral: tokens.palette.code.light.stringLiteral,
37
+ numberLiteral: tokens.palette.code.light.numberLiteral,
38
+ booleanLiteral: tokens.palette.code.light.booleanLiteral,
39
+ operator: tokens.palette.code.light.operator,
40
+ property: tokens.palette.code.light.property,
41
+ paramValue: tokens.palette.code.light.paramValue,
42
+ },
43
+ };
44
+
45
+ export const darkThemeConstants: ThemeOptions = {
46
+ dark: true,
47
+ editorSettings: {
48
+ background: '#242936',
49
+ foreground: '#cccac2',
50
+ gutterForeground: '#8a919966',
51
+ selection: '#409fff40',
52
+ textMatchingSelection: '#695380',
53
+ cursor: tokens.colors.neutral['10'],
54
+ autoCompletionPanel: {
55
+ selectedColor: '#062f4a',
56
+ matchingTextColor: '#0097fb',
57
+ backgroundColor: '#1C212B',
58
+ },
59
+ searchPanel: {
60
+ background: tokens.theme.dark.palette.neutral.bg.default,
61
+ text: tokens.theme.dark.palette.neutral.text.default,
62
+ buttonHoverBackground: tokens.theme.dark.palette.neutral.bg.strong,
63
+ },
64
+ },
65
+ highlightStyles: {
66
+ comment: tokens.palette.code.dark.comment,
67
+ keyword: tokens.palette.code.dark.keyword,
68
+ keywordLiteral: tokens.palette.code.dark.keywordLiteral,
69
+ label: tokens.palette.code.dark.label,
70
+ predicateFunction: tokens.palette.code.dark.predicateFunction,
71
+ function: tokens.palette.code.dark.function,
72
+ procedure: tokens.palette.code.dark.procedure,
73
+ stringLiteral: tokens.palette.code.dark.stringLiteral,
74
+ numberLiteral: tokens.palette.code.dark.numberLiteral,
75
+ booleanLiteral: tokens.palette.code.dark.booleanLiteral,
76
+ operator: tokens.palette.code.dark.operator,
77
+ property: tokens.palette.code.dark.property,
78
+ paramValue: tokens.palette.code.dark.paramValue,
79
+ },
80
+ };
81
+
82
+ type ExtraThemeOptions = { inheritBgColor?: boolean };
83
+ export const ayuLightTheme = ({ inheritBgColor }: ExtraThemeOptions) => {
84
+ return createCypherTheme({ ...lightThemeConstants, inheritBgColor });
85
+ };
86
+
87
+ export const ayuDarkTheme = ({ inheritBgColor }: ExtraThemeOptions) => {
88
+ return createCypherTheme({ ...darkThemeConstants, inheritBgColor });
89
+ };
90
+
91
+ export function getThemeExtension(
92
+ theme: 'light' | 'dark' | 'none' | Extension,
93
+ inheritBgColor?: boolean,
94
+ ): Extension | Extension[] {
95
+ switch (theme) {
96
+ case 'light':
97
+ return ayuLightTheme({ inheritBgColor });
98
+ case 'dark':
99
+ return ayuDarkTheme({ inheritBgColor });
100
+ case 'none':
101
+ return [];
102
+ default:
103
+ return theme;
104
+ }
105
+ }
@@ -0,0 +1 @@
1
+ /// <reference types="vite/client" />