diff options
author | Kristóf Marussy <kristof@marussy.com> | 2021-10-11 01:03:21 +0200 |
---|---|---|
committer | Kristóf Marussy <kristof@marussy.com> | 2021-10-31 19:26:10 +0100 |
commit | 299c4d93597b3065e6a1017ebe692cde66fc5e39 (patch) | |
tree | 57d634cec30ca37f0af81a37c3011e027589c35c /language-web/src/main/js/editor/EditorArea.tsx | |
parent | feat(web): add CodeMirror 6 editor (diff) | |
download | refinery-299c4d93597b3065e6a1017ebe692cde66fc5e39.tar.gz refinery-299c4d93597b3065e6a1017ebe692cde66fc5e39.tar.zst refinery-299c4d93597b3065e6a1017ebe692cde66fc5e39.zip |
feat(web): experiment with Lezer parser
Diffstat (limited to 'language-web/src/main/js/editor/EditorArea.tsx')
-rw-r--r-- | language-web/src/main/js/editor/EditorArea.tsx | 49 |
1 files changed, 35 insertions, 14 deletions
diff --git a/language-web/src/main/js/editor/EditorArea.tsx b/language-web/src/main/js/editor/EditorArea.tsx index 58d65184..460005ce 100644 --- a/language-web/src/main/js/editor/EditorArea.tsx +++ b/language-web/src/main/js/editor/EditorArea.tsx | |||
@@ -1,8 +1,14 @@ | |||
1 | import { Command, EditorView } from '@codemirror/view'; | 1 | import { Command, EditorView } from '@codemirror/view'; |
2 | import { closeSearchPanel, openSearchPanel } from '@codemirror/search'; | 2 | import { closeSearchPanel, openSearchPanel } from '@codemirror/search'; |
3 | import { closeLintPanel, openLintPanel } from '@codemirror/lint'; | 3 | import { closeLintPanel, openLintPanel } from '@codemirror/lint'; |
4 | |||
4 | import { observer } from 'mobx-react-lite'; | 5 | import { observer } from 'mobx-react-lite'; |
5 | import React, { useEffect, useRef, useState } from 'react'; | 6 | import React, { |
7 | useCallback, | ||
8 | useEffect, | ||
9 | useRef, | ||
10 | useState, | ||
11 | } from 'react'; | ||
6 | 12 | ||
7 | import { EditorParent } from './EditorParent'; | 13 | import { EditorParent } from './EditorParent'; |
8 | import { getLogger } from '../logging'; | 14 | import { getLogger } from '../logging'; |
@@ -11,36 +17,49 @@ import { useRootStore } from '../RootStore'; | |||
11 | const log = getLogger('EditorArea'); | 17 | const log = getLogger('EditorArea'); |
12 | 18 | ||
13 | function usePanel( | 19 | function usePanel( |
14 | label: string, | 20 | panelId: string, |
15 | stateToSet: boolean, | 21 | stateToSet: boolean, |
16 | editorView: EditorView | null, | 22 | editorView: EditorView | null, |
17 | openCommand: Command, | 23 | openCommand: Command, |
18 | closeCommand: Command, | 24 | closeCommand: Command, |
25 | closeCallback: () => void, | ||
19 | ) { | 26 | ) { |
20 | const [cachedViewState, setCachedViewState] = useState<boolean>(false); | 27 | const [cachedViewState, setCachedViewState] = useState<boolean>(false); |
21 | useEffect(() => { | 28 | useEffect(() => { |
22 | if (editorView === null || cachedViewState === stateToSet) { | 29 | if (editorView === null || cachedViewState === stateToSet) { |
23 | return; | 30 | return; |
24 | } | 31 | } |
25 | const success = stateToSet ? openCommand(editorView) : closeCommand(editorView); | 32 | if (stateToSet) { |
26 | if (!success) { | 33 | openCommand(editorView); |
27 | log.error( | 34 | const buttonQuery = `.cm-${panelId}.cm-panel button[name="close"]`; |
28 | 'Failed to synchronize', | 35 | const closeButton = editorView.dom.querySelector(buttonQuery); |
29 | label, | 36 | if (closeButton) { |
30 | 'panel state - store state:', | 37 | log.debug('Addig close button callback to', panelId, 'panel'); |
31 | cachedViewState, | 38 | // We must remove the event listener added by CodeMirror from the button |
32 | 'view state:', | 39 | // that dispatches a transaction without going through `EditorStorre`. |
33 | stateToSet, | 40 | // Cloning a DOM node removes event listeners, |
34 | ); | 41 | // see https://stackoverflow.com/a/9251864 |
42 | const closeButtonWithoutListeners = closeButton.cloneNode(true); | ||
43 | closeButtonWithoutListeners.addEventListener('click', (event) => { | ||
44 | closeCallback(); | ||
45 | event.preventDefault(); | ||
46 | }); | ||
47 | closeButton.replaceWith(closeButtonWithoutListeners); | ||
48 | } else { | ||
49 | log.error('Opened', panelId, 'panel has no close button'); | ||
50 | } | ||
51 | } else { | ||
52 | closeCommand(editorView); | ||
35 | } | 53 | } |
36 | setCachedViewState(stateToSet); | 54 | setCachedViewState(stateToSet); |
37 | }, [ | 55 | }, [ |
38 | stateToSet, | 56 | stateToSet, |
39 | editorView, | 57 | editorView, |
40 | cachedViewState, | 58 | cachedViewState, |
41 | label, | 59 | panelId, |
42 | openCommand, | 60 | openCommand, |
43 | closeCommand, | 61 | closeCommand, |
62 | closeCallback, | ||
44 | ]); | 63 | ]); |
45 | return setCachedViewState; | 64 | return setCachedViewState; |
46 | } | 65 | } |
@@ -56,14 +75,16 @@ export const EditorArea = observer(() => { | |||
56 | editorViewState, | 75 | editorViewState, |
57 | openSearchPanel, | 76 | openSearchPanel, |
58 | closeSearchPanel, | 77 | closeSearchPanel, |
78 | useCallback(() => editorStore.setSearchPanelOpen(false), [editorStore]), | ||
59 | ); | 79 | ); |
60 | 80 | ||
61 | const setLintPanelOpen = usePanel( | 81 | const setLintPanelOpen = usePanel( |
62 | 'lint', | 82 | 'panel-lint', |
63 | editorStore.showLintPanel, | 83 | editorStore.showLintPanel, |
64 | editorViewState, | 84 | editorViewState, |
65 | openLintPanel, | 85 | openLintPanel, |
66 | closeLintPanel, | 86 | closeLintPanel, |
87 | useCallback(() => editorStore.setLintPanelOpen(false), [editorStore]), | ||
67 | ); | 88 | ); |
68 | 89 | ||
69 | useEffect(() => { | 90 | useEffect(() => { |