aboutsummaryrefslogtreecommitdiffstats
path: root/subprojects/frontend/src
diff options
context:
space:
mode:
authorLibravatar Kristóf Marussy <kristof@marussy.com>2022-08-21 03:19:03 +0200
committerLibravatar Kristóf Marussy <kristof@marussy.com>2022-08-21 03:19:03 +0200
commit70dd02be202ae1b87ef8f7a2563ba09a3e7b0947 (patch)
treeddd34efea882a00e324000f84062c4cce28da814 /subprojects/frontend/src
parentfeat(frontend): overlay window controls (diff)
downloadrefinery-70dd02be202ae1b87ef8f7a2563ba09a3e7b0947.tar.gz
refinery-70dd02be202ae1b87ef8f7a2563ba09a3e7b0947.tar.zst
refinery-70dd02be202ae1b87ef8f7a2563ba09a3e7b0947.zip
refactor(frontend): improve code splitting
Diffstat (limited to 'subprojects/frontend/src')
-rw-r--r--subprojects/frontend/src/App.tsx19
-rw-r--r--subprojects/frontend/src/Loading.tsx4
-rw-r--r--subprojects/frontend/src/RootStore.tsx21
-rw-r--r--subprojects/frontend/src/editor/EditorArea.tsx22
-rw-r--r--subprojects/frontend/src/editor/EditorButtons.tsx52
-rw-r--r--subprojects/frontend/src/editor/EditorPane.tsx38
-rw-r--r--subprojects/frontend/src/editor/EditorTheme.ts8
-rw-r--r--subprojects/frontend/src/editor/GenerateButton.tsx17
-rw-r--r--subprojects/frontend/src/editor/SearchPanelPortal.tsx25
-rw-r--r--subprojects/frontend/src/editor/SearchToolbar.tsx46
-rw-r--r--subprojects/frontend/src/editor/createEditorState.ts9
-rw-r--r--subprojects/frontend/src/editor/editorClassNames.ts10
-rw-r--r--subprojects/frontend/src/index.tsx9
13 files changed, 179 insertions, 101 deletions
diff --git a/subprojects/frontend/src/App.tsx b/subprojects/frontend/src/App.tsx
index 12c66eb9..3a25f43a 100644
--- a/subprojects/frontend/src/App.tsx
+++ b/subprojects/frontend/src/App.tsx
@@ -1,23 +1,14 @@
1import Box from '@mui/material/Box'; 1import Stack from '@mui/material/Stack';
2import Toolbar from '@mui/material/Toolbar';
3import React from 'react'; 2import React from 'react';
4 3
5import TopBar from './TopBar'; 4import TopBar from './TopBar';
6import EditorArea from './editor/EditorArea'; 5import EditorPane from './editor/EditorPane';
7import EditorButtons from './editor/EditorButtons';
8import GenerateButton from './editor/GenerateButton';
9 6
10export default function App(): JSX.Element { 7export default function App(): JSX.Element {
11 return ( 8 return (
12 <Box display="flex" flexDirection="column" sx={{ height: '100vh' }}> 9 <Stack direction="column" height="100vh" overflow="auto">
13 <TopBar /> 10 <TopBar />
14 <Toolbar variant="dense"> 11 <EditorPane />
15 <EditorButtons /> 12 </Stack>
16 <GenerateButton />
17 </Toolbar>
18 <Box flexGrow={1} flexShrink={1} overflow="auto">
19 <EditorArea />
20 </Box>
21 </Box>
22 ); 13 );
23} 14}
diff --git a/subprojects/frontend/src/Loading.tsx b/subprojects/frontend/src/Loading.tsx
index a699adca..72020a43 100644
--- a/subprojects/frontend/src/Loading.tsx
+++ b/subprojects/frontend/src/Loading.tsx
@@ -3,8 +3,8 @@ import { styled } from '@mui/material/styles';
3import React from 'react'; 3import React from 'react';
4 4
5const LoadingRoot = styled('div')({ 5const LoadingRoot = styled('div')({
6 width: '100vw', 6 width: '100%',
7 height: '100vh', 7 height: '100%',
8 display: 'flex', 8 display: 'flex',
9 alignItems: 'center', 9 alignItems: 'center',
10 justifyContent: 'center', 10 justifyContent: 'center',
diff --git a/subprojects/frontend/src/RootStore.tsx b/subprojects/frontend/src/RootStore.tsx
index 4a267b0e..e08dd750 100644
--- a/subprojects/frontend/src/RootStore.tsx
+++ b/subprojects/frontend/src/RootStore.tsx
@@ -1,16 +1,31 @@
1import { getLogger } from 'loglevel';
2import { makeObservable, observable, runInAction } from 'mobx';
1import React, { createContext, useContext } from 'react'; 3import React, { createContext, useContext } from 'react';
2 4
3import EditorStore from './editor/EditorStore'; 5import type EditorStore from './editor/EditorStore';
4import ThemeStore from './theme/ThemeStore'; 6import ThemeStore from './theme/ThemeStore';
5 7
8const log = getLogger('RootStore');
9
6export default class RootStore { 10export default class RootStore {
7 readonly editorStore: EditorStore; 11 editorStore: EditorStore | undefined;
8 12
9 readonly themeStore: ThemeStore; 13 readonly themeStore: ThemeStore;
10 14
11 constructor(initialValue: string) { 15 constructor(initialValue: string) {
12 this.editorStore = new EditorStore(initialValue);
13 this.themeStore = new ThemeStore(); 16 this.themeStore = new ThemeStore();
17 makeObservable(this, {
18 editorStore: observable,
19 });
20 import('./editor/EditorStore')
21 .then(({ default: EditorStore }) => {
22 runInAction(() => {
23 this.editorStore = new EditorStore(initialValue);
24 });
25 })
26 .catch((error) => {
27 log.error('Failed to load EditorStore', error);
28 });
14 } 29 }
15} 30}
16 31
diff --git a/subprojects/frontend/src/editor/EditorArea.tsx b/subprojects/frontend/src/editor/EditorArea.tsx
index 915ec657..1c9b031b 100644
--- a/subprojects/frontend/src/editor/EditorArea.tsx
+++ b/subprojects/frontend/src/editor/EditorArea.tsx
@@ -1,17 +1,15 @@
1import Portal from '@mui/material/Portal';
2import { useTheme } from '@mui/material/styles'; 1import { useTheme } from '@mui/material/styles';
3import { observer } from 'mobx-react-lite'; 2import { observer } from 'mobx-react-lite';
4import React, { useCallback, useEffect } from 'react'; 3import React, { useCallback, useEffect } from 'react';
5 4
6import { useRootStore } from '../RootStore'; 5import type EditorStore from './EditorStore';
7
8import EditorTheme from './EditorTheme'; 6import EditorTheme from './EditorTheme';
9import SearchToolbar from './SearchToolbar';
10 7
11function EditorArea(): JSX.Element { 8function EditorArea({
12 const { editorStore } = useRootStore(); 9 editorStore,
13 const { searchPanel: searchPanelStore } = editorStore; 10}: {
14 const { element: searchPanelContainer } = searchPanelStore; 11 editorStore: EditorStore;
12}): JSX.Element {
15 const { 13 const {
16 palette: { mode: paletteMode }, 14 palette: { mode: paletteMode },
17 } = useTheme(); 15 } = useTheme();
@@ -32,13 +30,7 @@ function EditorArea(): JSX.Element {
32 <EditorTheme 30 <EditorTheme
33 showLineNumbers={editorStore.showLineNumbers} 31 showLineNumbers={editorStore.showLineNumbers}
34 ref={editorParentRef} 32 ref={editorParentRef}
35 > 33 />
36 {searchPanelContainer !== undefined && (
37 <Portal container={searchPanelContainer}>
38 <SearchToolbar store={searchPanelStore} />
39 </Portal>
40 )}
41 </EditorTheme>
42 ); 34 );
43} 35}
44 36
diff --git a/subprojects/frontend/src/editor/EditorButtons.tsx b/subprojects/frontend/src/editor/EditorButtons.tsx
index 8db9dfb7..cbe7c424 100644
--- a/subprojects/frontend/src/editor/EditorButtons.tsx
+++ b/subprojects/frontend/src/editor/EditorButtons.tsx
@@ -15,7 +15,7 @@ import ToggleButtonGroup from '@mui/material/ToggleButtonGroup';
15import { observer } from 'mobx-react-lite'; 15import { observer } from 'mobx-react-lite';
16import React from 'react'; 16import React from 'react';
17 17
18import { useRootStore } from '../RootStore'; 18import type EditorStore from './EditorStore';
19 19
20// Exhastive switch as proven by TypeScript. 20// Exhastive switch as proven by TypeScript.
21// eslint-disable-next-line consistent-return 21// eslint-disable-next-line consistent-return
@@ -32,22 +32,24 @@ function getLintIcon(severity: Diagnostic['severity'] | undefined) {
32 } 32 }
33} 33}
34 34
35function EditorButtons(): JSX.Element { 35function EditorButtons({
36 const { editorStore } = useRootStore(); 36 editorStore,
37 37}: {
38 editorStore: EditorStore | undefined;
39}): JSX.Element {
38 return ( 40 return (
39 <Stack direction="row" flexGrow={1}> 41 <Stack direction="row" flexGrow={1}>
40 <IconButton 42 <IconButton
41 disabled={!editorStore.canUndo} 43 disabled={editorStore === undefined || !editorStore.canUndo}
42 onClick={() => editorStore.undo()} 44 onClick={() => editorStore?.undo()}
43 aria-label="Undo" 45 aria-label="Undo"
44 color="inherit" 46 color="inherit"
45 > 47 >
46 <UndoIcon fontSize="small" /> 48 <UndoIcon fontSize="small" />
47 </IconButton> 49 </IconButton>
48 <IconButton 50 <IconButton
49 disabled={!editorStore.canRedo} 51 disabled={editorStore === undefined || !editorStore.canRedo}
50 onClick={() => editorStore.redo()} 52 onClick={() => editorStore?.redo()}
51 aria-label="Redo" 53 aria-label="Redo"
52 color="inherit" 54 color="inherit"
53 > 55 >
@@ -55,38 +57,44 @@ function EditorButtons(): JSX.Element {
55 </IconButton> 57 </IconButton>
56 <ToggleButtonGroup size="small" className="rounded" sx={{ mx: 1 }}> 58 <ToggleButtonGroup size="small" className="rounded" sx={{ mx: 1 }}>
57 <ToggleButton 59 <ToggleButton
58 selected={editorStore.showLineNumbers} 60 selected={editorStore?.showLineNumbers ?? false}
59 onClick={() => editorStore.toggleLineNumbers()} 61 disabled={editorStore === undefined}
62 onClick={() => editorStore?.toggleLineNumbers()}
60 aria-label="Show line numbers" 63 aria-label="Show line numbers"
61 value="show-line-numbers" 64 value="show-line-numbers"
62 > 65 >
63 <FormatListNumberedIcon fontSize="small" /> 66 <FormatListNumberedIcon fontSize="small" />
64 </ToggleButton> 67 </ToggleButton>
65 <ToggleButton 68 <ToggleButton
66 selected={editorStore.searchPanel.state} 69 selected={editorStore?.searchPanel?.state ?? false}
67 onClick={() => editorStore.searchPanel.toggle()} 70 disabled={editorStore === undefined}
71 onClick={() => editorStore?.searchPanel?.toggle()}
68 aria-label="Show find/replace" 72 aria-label="Show find/replace"
69 {...(editorStore.searchPanel.state && { 73 {...(editorStore !== undefined &&
70 'aria-controls': editorStore.searchPanel.id, 74 editorStore.searchPanel.state && {
71 })} 75 'aria-controls': editorStore.searchPanel.id,
76 })}
72 value="show-search-panel" 77 value="show-search-panel"
73 > 78 >
74 <SearchIcon fontSize="small" /> 79 <SearchIcon fontSize="small" />
75 </ToggleButton> 80 </ToggleButton>
76 <ToggleButton 81 <ToggleButton
77 selected={editorStore.lintPanel.state} 82 selected={editorStore?.lintPanel?.state ?? false}
78 onClick={() => editorStore.lintPanel.toggle()} 83 disabled={editorStore === undefined}
84 onClick={() => editorStore?.lintPanel.toggle()}
79 aria-label="Show diagnostics panel" 85 aria-label="Show diagnostics panel"
80 {...(editorStore.lintPanel.state && { 86 {...(editorStore !== undefined &&
81 'aria-controls': editorStore.lintPanel.id, 87 editorStore.lintPanel.state && {
82 })} 88 'aria-controls': editorStore.lintPanel.id,
89 })}
83 value="show-lint-panel" 90 value="show-lint-panel"
84 > 91 >
85 {getLintIcon(editorStore.highestDiagnosticLevel)} 92 {getLintIcon(editorStore?.highestDiagnosticLevel)}
86 </ToggleButton> 93 </ToggleButton>
87 </ToggleButtonGroup> 94 </ToggleButtonGroup>
88 <IconButton 95 <IconButton
89 onClick={() => editorStore.formatText()} 96 disabled={editorStore === undefined}
97 onClick={() => editorStore?.formatText()}
90 aria-label="Automatic format" 98 aria-label="Automatic format"
91 color="inherit" 99 color="inherit"
92 > 100 >
diff --git a/subprojects/frontend/src/editor/EditorPane.tsx b/subprojects/frontend/src/editor/EditorPane.tsx
new file mode 100644
index 00000000..935a84e8
--- /dev/null
+++ b/subprojects/frontend/src/editor/EditorPane.tsx
@@ -0,0 +1,38 @@
1import Box from '@mui/material/Box';
2import Stack from '@mui/material/Stack';
3import Toolbar from '@mui/material/Toolbar';
4import { observer } from 'mobx-react-lite';
5import React from 'react';
6
7import Loading from '../Loading';
8import { useRootStore } from '../RootStore';
9
10import EditorArea from './EditorArea';
11import EditorButtons from './EditorButtons';
12import GenerateButton from './GenerateButton';
13import SearchPanelPortal from './SearchPanelPortal';
14
15function EditorPane(): JSX.Element {
16 const { editorStore } = useRootStore();
17
18 return (
19 <Stack direction="column" flexGrow={1} flexShrink={1} overflow="auto">
20 <Toolbar variant="dense">
21 <EditorButtons editorStore={editorStore} />
22 <GenerateButton editorStore={editorStore} />
23 </Toolbar>
24 <Box flexGrow={1} flexShrink={1} overflow="auto">
25 {editorStore === undefined ? (
26 <Loading />
27 ) : (
28 <>
29 <SearchPanelPortal editorStore={editorStore} />
30 <EditorArea editorStore={editorStore} />
31 </>
32 )}
33 </Box>
34 </Stack>
35 );
36}
37
38export default observer(EditorPane);
diff --git a/subprojects/frontend/src/editor/EditorTheme.ts b/subprojects/frontend/src/editor/EditorTheme.ts
index d8680070..ca07d602 100644
--- a/subprojects/frontend/src/editor/EditorTheme.ts
+++ b/subprojects/frontend/src/editor/EditorTheme.ts
@@ -4,8 +4,6 @@ import infoSVG from '@material-icons/svg/svg/info/baseline.svg?raw';
4import warningSVG from '@material-icons/svg/svg/warning/baseline.svg?raw'; 4import warningSVG from '@material-icons/svg/svg/warning/baseline.svg?raw';
5import { alpha, styled, type CSSObject } from '@mui/material/styles'; 5import { alpha, styled, type CSSObject } from '@mui/material/styles';
6 6
7import editorClassNames from './editorClassNames';
8
9function svgURL(svg: string): string { 7function svgURL(svg: string): string {
10 return `url('data:image/svg+xml;utf8,${svg}')`; 8 return `url('data:image/svg+xml;utf8,${svg}')`;
11} 9}
@@ -315,7 +313,7 @@ export default styled('div', {
315 '.cm-gutters:hover .cm-foldGutter': { 313 '.cm-gutters:hover .cm-foldGutter': {
316 opacity: 1, 314 opacity: 1,
317 }, 315 },
318 [`.${editorClassNames.foldMarker}`]: { 316 '.problem-editor-foldMarker': {
319 display: 'block', 317 display: 'block',
320 margin: '4px 0', 318 margin: '4px 0',
321 padding: 0, 319 padding: 0,
@@ -330,10 +328,10 @@ export default styled('div', {
330 margin: '2px 0', 328 margin: '2px 0',
331 }, 329 },
332 }, 330 },
333 [`.${editorClassNames.foldMarkerClosed}`]: { 331 '.problem-editor-foldMarker-closed': {
334 transform: 'rotate(-90deg)', 332 transform: 'rotate(-90deg)',
335 }, 333 },
336 [`.${editorClassNames.foldPlaceholder}`]: { 334 '.problem-editor-foldPlaceholder': {
337 ...editorFontStyle, 335 ...editorFontStyle,
338 padding: 0, 336 padding: 0,
339 fontFamily: 'inherit', 337 fontFamily: 'inherit',
diff --git a/subprojects/frontend/src/editor/GenerateButton.tsx b/subprojects/frontend/src/editor/GenerateButton.tsx
index 4b998af6..a28f6b4b 100644
--- a/subprojects/frontend/src/editor/GenerateButton.tsx
+++ b/subprojects/frontend/src/editor/GenerateButton.tsx
@@ -3,12 +3,23 @@ import Button from '@mui/material/Button';
3import { observer } from 'mobx-react-lite'; 3import { observer } from 'mobx-react-lite';
4import React from 'react'; 4import React from 'react';
5 5
6import { useRootStore } from '../RootStore'; 6import type EditorStore from './EditorStore';
7 7
8const GENERATE_LABEL = 'Generate'; 8const GENERATE_LABEL = 'Generate';
9 9
10function GenerateButton(): JSX.Element { 10function GenerateButton({
11 const { editorStore } = useRootStore(); 11 editorStore,
12}: {
13 editorStore: EditorStore | undefined;
14}): JSX.Element {
15 if (editorStore === undefined) {
16 return (
17 <Button color="inherit" className="rounded" disabled>
18 Loading&hellip;
19 </Button>
20 );
21 }
22
12 const { errorCount, warningCount } = editorStore; 23 const { errorCount, warningCount } = editorStore;
13 24
14 const diagnostics: string[] = []; 25 const diagnostics: string[] = [];
diff --git a/subprojects/frontend/src/editor/SearchPanelPortal.tsx b/subprojects/frontend/src/editor/SearchPanelPortal.tsx
new file mode 100644
index 00000000..e8301489
--- /dev/null
+++ b/subprojects/frontend/src/editor/SearchPanelPortal.tsx
@@ -0,0 +1,25 @@
1import Portal from '@mui/material/Portal';
2import { observer } from 'mobx-react-lite';
3import React from 'react';
4
5import type EditorStore from './EditorStore';
6import SearchToolbar from './SearchToolbar';
7
8function SearchPanelPortal({
9 editorStore: { searchPanel: searchPanelStore },
10}: {
11 editorStore: EditorStore;
12}): JSX.Element | null {
13 const { element: searchPanelContainer } = searchPanelStore;
14
15 if (searchPanelContainer === undefined) {
16 return null;
17 }
18 return (
19 <Portal container={searchPanelContainer}>
20 <SearchToolbar searchPanelStore={searchPanelStore} />
21 </Portal>
22 );
23}
24
25export default observer(SearchPanelPortal);
diff --git a/subprojects/frontend/src/editor/SearchToolbar.tsx b/subprojects/frontend/src/editor/SearchToolbar.tsx
index 45f1336d..7e6ff4f7 100644
--- a/subprojects/frontend/src/editor/SearchToolbar.tsx
+++ b/subprojects/frontend/src/editor/SearchToolbar.tsx
@@ -20,12 +20,16 @@ import type SearchPanelStore from './SearchPanelStore';
20const SPLIT_MEDIA_QUERY = '@media (max-width: 1200px)'; 20const SPLIT_MEDIA_QUERY = '@media (max-width: 1200px)';
21const ABBREVIATE_MEDIA_QUERY = '@media (max-width: 720px)'; 21const ABBREVIATE_MEDIA_QUERY = '@media (max-width: 720px)';
22 22
23function SearchToolbar({ store }: { store: SearchPanelStore }): JSX.Element { 23function SearchToolbar({
24 searchPanelStore,
25}: {
26 searchPanelStore: SearchPanelStore;
27}): JSX.Element {
24 const { 28 const {
25 id: panelId, 29 id: panelId,
26 query: { search, valid, caseSensitive, literal, regexp, replace }, 30 query: { search, valid, caseSensitive, literal, regexp, replace },
27 invalidRegexp, 31 invalidRegexp,
28 } = store; 32 } = searchPanelStore;
29 const split = useMediaQuery(SPLIT_MEDIA_QUERY); 33 const split = useMediaQuery(SPLIT_MEDIA_QUERY);
30 const abbreviate = useMediaQuery(ABBREVIATE_MEDIA_QUERY); 34 const abbreviate = useMediaQuery(ABBREVIATE_MEDIA_QUERY);
31 const [showRepalceState, setShowReplaceState] = useState(false); 35 const [showRepalceState, setShowReplaceState] = useState(false);
@@ -37,8 +41,8 @@ function SearchToolbar({ store }: { store: SearchPanelStore }): JSX.Element {
37 41
38 const searchFieldRef = useCallback( 42 const searchFieldRef = useCallback(
39 (element: HTMLInputElement | null) => 43 (element: HTMLInputElement | null) =>
40 store.setSearchField(element ?? undefined), 44 searchPanelStore.setSearchField(element ?? undefined),
41 [store], 45 [searchPanelStore],
42 ); 46 );
43 47
44 return ( 48 return (
@@ -68,15 +72,15 @@ function SearchToolbar({ store }: { store: SearchPanelStore }): JSX.Element {
68 value={search} 72 value={search}
69 error={invalidRegexp} 73 error={invalidRegexp}
70 onChange={(event) => 74 onChange={(event) =>
71 store.updateQuery({ search: event.target.value }) 75 searchPanelStore.updateQuery({ search: event.target.value })
72 } 76 }
73 onKeyDown={(event) => { 77 onKeyDown={(event) => {
74 if (event.key === 'Enter') { 78 if (event.key === 'Enter') {
75 event.preventDefault(); 79 event.preventDefault();
76 if (event.shiftKey) { 80 if (event.shiftKey) {
77 store.findPrevious(); 81 searchPanelStore.findPrevious();
78 } else { 82 } else {
79 store.findNext(); 83 searchPanelStore.findNext();
80 } 84 }
81 } 85 }
82 }} 86 }}
@@ -108,7 +112,7 @@ function SearchToolbar({ store }: { store: SearchPanelStore }): JSX.Element {
108 <IconButton 112 <IconButton
109 aria-label="Previous" 113 aria-label="Previous"
110 disabled={!valid} 114 disabled={!valid}
111 onClick={() => store.findPrevious()} 115 onClick={() => searchPanelStore.findPrevious()}
112 color="inherit" 116 color="inherit"
113 > 117 >
114 <KeyboardArrowUpIcon fontSize="small" /> 118 <KeyboardArrowUpIcon fontSize="small" />
@@ -116,7 +120,7 @@ function SearchToolbar({ store }: { store: SearchPanelStore }): JSX.Element {
116 <IconButton 120 <IconButton
117 aria-label="Next" 121 aria-label="Next"
118 disabled={!valid} 122 disabled={!valid}
119 onClick={() => store.findNext()} 123 onClick={() => searchPanelStore.findNext()}
120 color="inherit" 124 color="inherit"
121 > 125 >
122 <KeyboardArrowDownIcon fontSize="small" /> 126 <KeyboardArrowDownIcon fontSize="small" />
@@ -133,7 +137,9 @@ function SearchToolbar({ store }: { store: SearchPanelStore }): JSX.Element {
133 <Checkbox 137 <Checkbox
134 checked={caseSensitive} 138 checked={caseSensitive}
135 onChange={(event) => 139 onChange={(event) =>
136 store.updateQuery({ caseSensitive: event.target.checked }) 140 searchPanelStore.updateQuery({
141 caseSensitive: event.target.checked,
142 })
137 } 143 }
138 size="small" 144 size="small"
139 /> 145 />
@@ -146,7 +152,9 @@ function SearchToolbar({ store }: { store: SearchPanelStore }): JSX.Element {
146 <Checkbox 152 <Checkbox
147 checked={literal} 153 checked={literal}
148 onChange={(event) => 154 onChange={(event) =>
149 store.updateQuery({ literal: event.target.checked }) 155 searchPanelStore.updateQuery({
156 literal: event.target.checked,
157 })
150 } 158 }
151 size="small" 159 size="small"
152 /> 160 />
@@ -159,7 +167,9 @@ function SearchToolbar({ store }: { store: SearchPanelStore }): JSX.Element {
159 <Checkbox 167 <Checkbox
160 checked={regexp} 168 checked={regexp}
161 onChange={(event) => 169 onChange={(event) =>
162 store.updateQuery({ regexp: event.target.checked }) 170 searchPanelStore.updateQuery({
171 regexp: event.target.checked,
172 })
163 } 173 }
164 size="small" 174 size="small"
165 /> 175 />
@@ -172,7 +182,7 @@ function SearchToolbar({ store }: { store: SearchPanelStore }): JSX.Element {
172 selected={showReplace} 182 selected={showReplace}
173 onClick={() => { 183 onClick={() => {
174 if (showReplace) { 184 if (showReplace) {
175 store.updateQuery({ replace: '' }); 185 searchPanelStore.updateQuery({ replace: '' });
176 setShowReplaceState(false); 186 setShowReplaceState(false);
177 } else { 187 } else {
178 setShowReplaceState(true); 188 setShowReplaceState(true);
@@ -201,12 +211,12 @@ function SearchToolbar({ store }: { store: SearchPanelStore }): JSX.Element {
201 aria-label="Replace with" 211 aria-label="Replace with"
202 value={replace} 212 value={replace}
203 onChange={(event) => 213 onChange={(event) =>
204 store.updateQuery({ replace: event.target.value }) 214 searchPanelStore.updateQuery({ replace: event.target.value })
205 } 215 }
206 onKeyDown={(event) => { 216 onKeyDown={(event) => {
207 if (event.key === 'Enter') { 217 if (event.key === 'Enter') {
208 event.preventDefault(); 218 event.preventDefault();
209 store.replaceNext(); 219 searchPanelStore.replaceNext();
210 } 220 }
211 }} 221 }}
212 variant="standard" 222 variant="standard"
@@ -221,7 +231,7 @@ function SearchToolbar({ store }: { store: SearchPanelStore }): JSX.Element {
221 > 231 >
222 <Button 232 <Button
223 disabled={!valid} 233 disabled={!valid}
224 onClick={() => store.replaceNext()} 234 onClick={() => searchPanelStore.replaceNext()}
225 color="inherit" 235 color="inherit"
226 startIcon={<FindReplaceIcon fontSize="inherit" />} 236 startIcon={<FindReplaceIcon fontSize="inherit" />}
227 > 237 >
@@ -229,7 +239,7 @@ function SearchToolbar({ store }: { store: SearchPanelStore }): JSX.Element {
229 </Button> 239 </Button>
230 <Button 240 <Button
231 disabled={!valid} 241 disabled={!valid}
232 onClick={() => store.replaceAll()} 242 onClick={() => searchPanelStore.replaceAll()}
233 color="inherit" 243 color="inherit"
234 startIcon={<FindReplaceIcon fontSize="inherit" />} 244 startIcon={<FindReplaceIcon fontSize="inherit" />}
235 > 245 >
@@ -241,7 +251,7 @@ function SearchToolbar({ store }: { store: SearchPanelStore }): JSX.Element {
241 <Stack direction="row" alignSelf="stretch" alignItems="start" mt="1px"> 251 <Stack direction="row" alignSelf="stretch" alignItems="start" mt="1px">
242 <IconButton 252 <IconButton
243 aria-label="Close find/replace" 253 aria-label="Close find/replace"
244 onClick={() => store.close()} 254 onClick={() => searchPanelStore.close()}
245 color="inherit" 255 color="inherit"
246 > 256 >
247 <CloseIcon fontSize="small" /> 257 <CloseIcon fontSize="small" />
diff --git a/subprojects/frontend/src/editor/createEditorState.ts b/subprojects/frontend/src/editor/createEditorState.ts
index 7b0f3c07..c61f4a22 100644
--- a/subprojects/frontend/src/editor/createEditorState.ts
+++ b/subprojects/frontend/src/editor/createEditorState.ts
@@ -36,7 +36,6 @@ import problemLanguageSupport from '../language/problemLanguageSupport';
36 36
37import type EditorStore from './EditorStore'; 37import type EditorStore from './EditorStore';
38import SearchPanel from './SearchPanel'; 38import SearchPanel from './SearchPanel';
39import editorClassNames from './editorClassNames';
40import findOccurrences from './findOccurrences'; 39import findOccurrences from './findOccurrences';
41import semanticHighlighting from './semanticHighlighting'; 40import semanticHighlighting from './semanticHighlighting';
42 41
@@ -75,7 +74,7 @@ export default function createEditorState(
75 codeFolding({ 74 codeFolding({
76 placeholderDOM(_view, onClick) { 75 placeholderDOM(_view, onClick) {
77 const button = document.createElement('button'); 76 const button = document.createElement('button');
78 button.className = editorClassNames.foldPlaceholder; 77 button.className = 'problem-editor-foldPlaceholder';
79 button.ariaLabel = 'Unfold lines'; 78 button.ariaLabel = 'Unfold lines';
80 const span = document.createElement('span'); 79 const span = document.createElement('span');
81 span.innerText = '...'; 80 span.innerText = '...';
@@ -88,10 +87,8 @@ export default function createEditorState(
88 markerDOM(open) { 87 markerDOM(open) {
89 const div = document.createElement('div'); 88 const div = document.createElement('div');
90 div.className = [ 89 div.className = [
91 editorClassNames.foldMarker, 90 'problem-editor-foldMarker',
92 open 91 `problem-editor-foldMarker-${open ? 'open' : 'closed'}`,
93 ? editorClassNames.foldMarkerOpen
94 : editorClassNames.foldMarkerClosed,
95 ].join(' '); 92 ].join(' ');
96 return div; 93 return div;
97 }, 94 },
diff --git a/subprojects/frontend/src/editor/editorClassNames.ts b/subprojects/frontend/src/editor/editorClassNames.ts
deleted file mode 100644
index 5584e8c2..00000000
--- a/subprojects/frontend/src/editor/editorClassNames.ts
+++ /dev/null
@@ -1,10 +0,0 @@
1const PREFIX = 'problem-editor-';
2
3const editorClassNames = {
4 foldPlaceholder: `${PREFIX}fold-placeholder`,
5 foldMarker: `${PREFIX}fold-marker`,
6 foldMarkerClosed: `${PREFIX}fold-marker-closed`,
7 foldMarkerOpen: `${PREFIX}fold-marker-open`,
8};
9
10export default editorClassNames;
diff --git a/subprojects/frontend/src/index.tsx b/subprojects/frontend/src/index.tsx
index 460f6f77..3f06b332 100644
--- a/subprojects/frontend/src/index.tsx
+++ b/subprojects/frontend/src/index.tsx
@@ -1,3 +1,4 @@
1import Box from '@mui/material/Box';
1import CssBaseline from '@mui/material/CssBaseline'; 2import CssBaseline from '@mui/material/CssBaseline';
2import { SnackbarProvider } from 'notistack'; 3import { SnackbarProvider } from 'notistack';
3import React, { Suspense, lazy } from 'react'; 4import React, { Suspense, lazy } from 'react';
@@ -71,9 +72,11 @@ const app = (
71 <WindowControlsOverlayColor /> 72 <WindowControlsOverlayColor />
72 <SnackbarProvider> 73 <SnackbarProvider>
73 <RegisterServiceWorker /> 74 <RegisterServiceWorker />
74 <Suspense fallback={<Loading />}> 75 <Box height="100vh" overflow="auto">
75 <App /> 76 <Suspense fallback={<Loading />}>
76 </Suspense> 77 <App />
78 </Suspense>
79 </Box>
77 </SnackbarProvider> 80 </SnackbarProvider>
78 </ThemeProvider> 81 </ThemeProvider>
79 </RootStoreProvider> 82 </RootStoreProvider>