diff options
author | Kristóf Marussy <kristof@marussy.com> | 2022-08-27 13:02:22 +0200 |
---|---|---|
committer | Kristóf Marussy <kristof@marussy.com> | 2022-08-27 14:50:27 +0200 |
commit | 072621cee0f858236163ce11d42eca5adb84d205 (patch) | |
tree | 701686d051cb3a8a75be9075d404508be093a2a2 | |
parent | refactor(frontend): custom mutex implementation (diff) | |
download | refinery-072621cee0f858236163ce11d42eca5adb84d205.tar.gz refinery-072621cee0f858236163ce11d42eca5adb84d205.tar.zst refinery-072621cee0f858236163ce11d42eca5adb84d205.zip |
refactor(frontend): add eslint-plugin-mobx
-rw-r--r-- | package.json | 2 | ||||
-rw-r--r-- | subprojects/frontend/.eslintrc.cjs | 5 | ||||
-rw-r--r-- | subprojects/frontend/package.json | 5 | ||||
-rw-r--r-- | subprojects/frontend/src/RootStore.tsx | 6 | ||||
-rw-r--r-- | subprojects/frontend/src/ToggleDarkModeButton.tsx | 6 | ||||
-rw-r--r-- | subprojects/frontend/src/editor/EditorArea.tsx | 6 | ||||
-rw-r--r-- | subprojects/frontend/src/editor/EditorButtons.tsx | 6 | ||||
-rw-r--r-- | subprojects/frontend/src/editor/EditorPane.tsx | 6 | ||||
-rw-r--r-- | subprojects/frontend/src/editor/EditorStore.ts | 42 | ||||
-rw-r--r-- | subprojects/frontend/src/editor/GenerateButton.tsx | 6 | ||||
-rw-r--r-- | subprojects/frontend/src/editor/PanelStore.ts | 18 | ||||
-rw-r--r-- | subprojects/frontend/src/editor/SearchPanelPortal.tsx | 6 | ||||
-rw-r--r-- | subprojects/frontend/src/editor/SearchPanelStore.ts | 3 | ||||
-rw-r--r-- | subprojects/frontend/src/editor/SearchToolbar.tsx | 6 | ||||
-rw-r--r-- | subprojects/frontend/src/index.tsx | 6 | ||||
-rw-r--r-- | subprojects/frontend/src/theme/ThemeProvider.tsx | 10 | ||||
-rw-r--r-- | subprojects/frontend/src/theme/ThemeStore.ts | 9 | ||||
-rw-r--r-- | yarn.lock | 70 |
18 files changed, 112 insertions, 106 deletions
diff --git a/package.json b/package.json index c4094e60..ca82d409 100644 --- a/package.json +++ b/package.json | |||
@@ -10,7 +10,7 @@ | |||
10 | }, | 10 | }, |
11 | "packageManager": "yarn@3.2.3", | 11 | "packageManager": "yarn@3.2.3", |
12 | "devDependencies": { | 12 | "devDependencies": { |
13 | "eslint": "^8.22.0", | 13 | "eslint": "^8.23.0", |
14 | "typescript": "~4.8.2" | 14 | "typescript": "~4.8.2" |
15 | } | 15 | } |
16 | } | 16 | } |
diff --git a/subprojects/frontend/.eslintrc.cjs b/subprojects/frontend/.eslintrc.cjs index 442ed4cd..1db67c11 100644 --- a/subprojects/frontend/.eslintrc.cjs +++ b/subprojects/frontend/.eslintrc.cjs | |||
@@ -8,13 +8,14 @@ const project = [ | |||
8 | 8 | ||
9 | /** @type {import('eslint').Linter.Config} */ | 9 | /** @type {import('eslint').Linter.Config} */ |
10 | module.exports = { | 10 | module.exports = { |
11 | plugins: ['@typescript-eslint'], | 11 | plugins: ['@typescript-eslint', 'mobx'], |
12 | extends: [ | 12 | extends: [ |
13 | 'airbnb', | 13 | 'airbnb', |
14 | 'airbnb-typescript', | 14 | 'airbnb-typescript', |
15 | 'airbnb/hooks', | 15 | 'airbnb/hooks', |
16 | 'plugin:@typescript-eslint/recommended', | 16 | 'plugin:@typescript-eslint/recommended', |
17 | 'plugin:@typescript-eslint/recommended-requiring-type-checking', | 17 | 'plugin:@typescript-eslint/recommended-requiring-type-checking', |
18 | 'plugin:mobx/recommended', | ||
18 | 'plugin:prettier/recommended', | 19 | 'plugin:prettier/recommended', |
19 | ], | 20 | ], |
20 | parserOptions: { | 21 | parserOptions: { |
@@ -53,6 +54,8 @@ module.exports = { | |||
53 | 'newlines-between': 'always', | 54 | 'newlines-between': 'always', |
54 | }, | 55 | }, |
55 | ], | 56 | ], |
57 | // Not all components depend on observable state. | ||
58 | 'mobx/missing-observer': 'off', | ||
56 | // A dangling underscore, while not neccessary for all private fields, | 59 | // A dangling underscore, while not neccessary for all private fields, |
57 | // is useful for backing fields of properties that should be read-only from outside the class. | 60 | // is useful for backing fields of properties that should be read-only from outside the class. |
58 | 'no-underscore-dangle': [ | 61 | 'no-underscore-dangle': [ |
diff --git a/subprojects/frontend/package.json b/subprojects/frontend/package.json index f47ced13..b80e0561 100644 --- a/subprojects/frontend/package.json +++ b/subprojects/frontend/package.json | |||
@@ -65,15 +65,16 @@ | |||
65 | "@typescript-eslint/parser": "^5.35.1", | 65 | "@typescript-eslint/parser": "^5.35.1", |
66 | "@vitejs/plugin-react": "^2.0.1", | 66 | "@vitejs/plugin-react": "^2.0.1", |
67 | "cross-env": "^7.0.3", | 67 | "cross-env": "^7.0.3", |
68 | "eslint": "^8.22.0", | 68 | "eslint": "^8.23.0", |
69 | "eslint-config-airbnb": "^19.0.4", | 69 | "eslint-config-airbnb": "^19.0.4", |
70 | "eslint-config-airbnb-typescript": "^17.0.0", | 70 | "eslint-config-airbnb-typescript": "^17.0.0", |
71 | "eslint-config-prettier": "^8.5.0", | 71 | "eslint-config-prettier": "^8.5.0", |
72 | "eslint-import-resolver-typescript": "^3.5.0", | 72 | "eslint-import-resolver-typescript": "^3.5.0", |
73 | "eslint-plugin-import": "^2.26.0", | 73 | "eslint-plugin-import": "^2.26.0", |
74 | "eslint-plugin-jsx-a11y": "^6.6.1", | 74 | "eslint-plugin-jsx-a11y": "^6.6.1", |
75 | "eslint-plugin-mobx": "^0.0.9", | ||
75 | "eslint-plugin-prettier": "^4.2.1", | 76 | "eslint-plugin-prettier": "^4.2.1", |
76 | "eslint-plugin-react": "^7.31.0", | 77 | "eslint-plugin-react": "^7.31.1", |
77 | "eslint-plugin-react-hooks": "^4.6.0", | 78 | "eslint-plugin-react-hooks": "^4.6.0", |
78 | "html-minifier-terser": "^7.0.0", | 79 | "html-minifier-terser": "^7.0.0", |
79 | "prettier": "^2.7.1", | 80 | "prettier": "^2.7.1", |
diff --git a/subprojects/frontend/src/RootStore.tsx b/subprojects/frontend/src/RootStore.tsx index e08dd750..5aa580d1 100644 --- a/subprojects/frontend/src/RootStore.tsx +++ b/subprojects/frontend/src/RootStore.tsx | |||
@@ -1,5 +1,5 @@ | |||
1 | import { getLogger } from 'loglevel'; | 1 | import { getLogger } from 'loglevel'; |
2 | import { makeObservable, observable, runInAction } from 'mobx'; | 2 | import { makeAutoObservable, runInAction } from 'mobx'; |
3 | import React, { createContext, useContext } from 'react'; | 3 | import React, { createContext, useContext } from 'react'; |
4 | 4 | ||
5 | import type EditorStore from './editor/EditorStore'; | 5 | import type EditorStore from './editor/EditorStore'; |
@@ -14,8 +14,8 @@ export default class RootStore { | |||
14 | 14 | ||
15 | constructor(initialValue: string) { | 15 | constructor(initialValue: string) { |
16 | this.themeStore = new ThemeStore(); | 16 | this.themeStore = new ThemeStore(); |
17 | makeObservable(this, { | 17 | makeAutoObservable(this, { |
18 | editorStore: observable, | 18 | themeStore: false, |
19 | }); | 19 | }); |
20 | import('./editor/EditorStore') | 20 | import('./editor/EditorStore') |
21 | .then(({ default: EditorStore }) => { | 21 | .then(({ default: EditorStore }) => { |
diff --git a/subprojects/frontend/src/ToggleDarkModeButton.tsx b/subprojects/frontend/src/ToggleDarkModeButton.tsx index 1685ec80..5602f3bc 100644 --- a/subprojects/frontend/src/ToggleDarkModeButton.tsx +++ b/subprojects/frontend/src/ToggleDarkModeButton.tsx | |||
@@ -6,7 +6,7 @@ import React from 'react'; | |||
6 | 6 | ||
7 | import { useRootStore } from './RootStore'; | 7 | import { useRootStore } from './RootStore'; |
8 | 8 | ||
9 | function ToggleDarkModeButton(): JSX.Element { | 9 | export default observer(function ToggleDarkModeButton(): JSX.Element { |
10 | const { themeStore } = useRootStore(); | 10 | const { themeStore } = useRootStore(); |
11 | const { darkMode } = themeStore; | 11 | const { darkMode } = themeStore; |
12 | 12 | ||
@@ -19,6 +19,4 @@ function ToggleDarkModeButton(): JSX.Element { | |||
19 | {darkMode ? <LightModeIcon /> : <DarkModeIcon />} | 19 | {darkMode ? <LightModeIcon /> : <DarkModeIcon />} |
20 | </IconButton> | 20 | </IconButton> |
21 | ); | 21 | ); |
22 | } | 22 | }); |
23 | |||
24 | export default observer(ToggleDarkModeButton); | ||
diff --git a/subprojects/frontend/src/editor/EditorArea.tsx b/subprojects/frontend/src/editor/EditorArea.tsx index 1c9b031b..7c5ac5fb 100644 --- a/subprojects/frontend/src/editor/EditorArea.tsx +++ b/subprojects/frontend/src/editor/EditorArea.tsx | |||
@@ -5,7 +5,7 @@ import React, { useCallback, useEffect } from 'react'; | |||
5 | import type EditorStore from './EditorStore'; | 5 | import type EditorStore from './EditorStore'; |
6 | import EditorTheme from './EditorTheme'; | 6 | import EditorTheme from './EditorTheme'; |
7 | 7 | ||
8 | function EditorArea({ | 8 | export default observer(function EditorArea({ |
9 | editorStore, | 9 | editorStore, |
10 | }: { | 10 | }: { |
11 | editorStore: EditorStore; | 11 | editorStore: EditorStore; |
@@ -32,6 +32,4 @@ function EditorArea({ | |||
32 | ref={editorParentRef} | 32 | ref={editorParentRef} |
33 | /> | 33 | /> |
34 | ); | 34 | ); |
35 | } | 35 | }); |
36 | |||
37 | export default observer(EditorArea); | ||
diff --git a/subprojects/frontend/src/editor/EditorButtons.tsx b/subprojects/frontend/src/editor/EditorButtons.tsx index cbe7c424..d2273c6c 100644 --- a/subprojects/frontend/src/editor/EditorButtons.tsx +++ b/subprojects/frontend/src/editor/EditorButtons.tsx | |||
@@ -32,7 +32,7 @@ function getLintIcon(severity: Diagnostic['severity'] | undefined) { | |||
32 | } | 32 | } |
33 | } | 33 | } |
34 | 34 | ||
35 | function EditorButtons({ | 35 | export default observer(function EditorButtons({ |
36 | editorStore, | 36 | editorStore, |
37 | }: { | 37 | }: { |
38 | editorStore: EditorStore | undefined; | 38 | editorStore: EditorStore | undefined; |
@@ -102,6 +102,4 @@ function EditorButtons({ | |||
102 | </IconButton> | 102 | </IconButton> |
103 | </Stack> | 103 | </Stack> |
104 | ); | 104 | ); |
105 | } | 105 | }); |
106 | |||
107 | export default observer(EditorButtons); | ||
diff --git a/subprojects/frontend/src/editor/EditorPane.tsx b/subprojects/frontend/src/editor/EditorPane.tsx index df43d2c9..2651726c 100644 --- a/subprojects/frontend/src/editor/EditorPane.tsx +++ b/subprojects/frontend/src/editor/EditorPane.tsx | |||
@@ -29,7 +29,7 @@ function EditorLoading(): JSX.Element { | |||
29 | ); | 29 | ); |
30 | } | 30 | } |
31 | 31 | ||
32 | function EditorPane(): JSX.Element { | 32 | export default observer(function EditorPane(): JSX.Element { |
33 | const { editorStore } = useRootStore(); | 33 | const { editorStore } = useRootStore(); |
34 | 34 | ||
35 | return ( | 35 | return ( |
@@ -50,6 +50,4 @@ function EditorPane(): JSX.Element { | |||
50 | </Box> | 50 | </Box> |
51 | </Stack> | 51 | </Stack> |
52 | ); | 52 | ); |
53 | } | 53 | }); |
54 | |||
55 | export default observer(EditorPane); | ||
diff --git a/subprojects/frontend/src/editor/EditorStore.ts b/subprojects/frontend/src/editor/EditorStore.ts index b634a427..4407376b 100644 --- a/subprojects/frontend/src/editor/EditorStore.ts +++ b/subprojects/frontend/src/editor/EditorStore.ts | |||
@@ -13,7 +13,7 @@ import { | |||
13 | type EditorState, | 13 | type EditorState, |
14 | } from '@codemirror/state'; | 14 | } from '@codemirror/state'; |
15 | import { type Command, EditorView } from '@codemirror/view'; | 15 | import { type Command, EditorView } from '@codemirror/view'; |
16 | import { action, computed, makeObservable, observable } from 'mobx'; | 16 | import { makeAutoObservable, observable } from 'mobx'; |
17 | import { nanoid } from 'nanoid'; | 17 | import { nanoid } from 'nanoid'; |
18 | 18 | ||
19 | import getLogger from '../utils/getLogger'; | 19 | import getLogger from '../utils/getLogger'; |
@@ -57,29 +57,15 @@ export default class EditorStore { | |||
57 | this.client = new XtextClient(this); | 57 | this.client = new XtextClient(this); |
58 | this.searchPanel = new SearchPanelStore(this); | 58 | this.searchPanel = new SearchPanelStore(this); |
59 | this.lintPanel = new LintPanelStore(this); | 59 | this.lintPanel = new LintPanelStore(this); |
60 | makeObservable(this, { | 60 | makeAutoObservable<EditorStore, 'client'>(this, { |
61 | id: false, | ||
61 | state: observable.ref, | 62 | state: observable.ref, |
63 | client: false, | ||
62 | view: observable.ref, | 64 | view: observable.ref, |
63 | showLineNumbers: observable, | 65 | searchPanel: false, |
64 | errorCount: observable, | 66 | lintPanel: false, |
65 | warningCount: observable, | 67 | contentAssist: false, |
66 | infoCount: observable, | 68 | formatText: false, |
67 | highestDiagnosticLevel: computed, | ||
68 | canUndo: computed, | ||
69 | canRedo: computed, | ||
70 | setDarkMode: action, | ||
71 | setEditorParent: action, | ||
72 | dispatch: action, | ||
73 | dispatchTransaction: action, | ||
74 | doCommand: action, | ||
75 | doStateCommand: action, | ||
76 | updateDiagnostics: action, | ||
77 | nextDiagnostic: action, | ||
78 | updateOccurrences: action, | ||
79 | updateSemanticHighlighting: action, | ||
80 | undo: action, | ||
81 | redo: action, | ||
82 | toggleLineNumbers: action, | ||
83 | }); | 69 | }); |
84 | } | 70 | } |
85 | 71 | ||
@@ -141,13 +127,11 @@ export default class EditorStore { | |||
141 | } | 127 | } |
142 | } | 128 | } |
143 | 129 | ||
144 | private readonly dispatchTransactionWithoutView = action( | 130 | private dispatchTransactionWithoutView(tr: Transaction): void { |
145 | (tr: Transaction) => { | 131 | log.trace('Editor transaction', tr); |
146 | log.trace('Editor transaction', tr); | 132 | this.state = tr.state; |
147 | this.state = tr.state; | 133 | this.client.onTransaction(tr); |
148 | this.client.onTransaction(tr); | 134 | } |
149 | }, | ||
150 | ); | ||
151 | 135 | ||
152 | doCommand(command: Command): boolean { | 136 | doCommand(command: Command): boolean { |
153 | if (this.view === undefined) { | 137 | if (this.view === undefined) { |
diff --git a/subprojects/frontend/src/editor/GenerateButton.tsx b/subprojects/frontend/src/editor/GenerateButton.tsx index a28f6b4b..5254f6cb 100644 --- a/subprojects/frontend/src/editor/GenerateButton.tsx +++ b/subprojects/frontend/src/editor/GenerateButton.tsx | |||
@@ -7,7 +7,7 @@ import type EditorStore from './EditorStore'; | |||
7 | 7 | ||
8 | const GENERATE_LABEL = 'Generate'; | 8 | const GENERATE_LABEL = 'Generate'; |
9 | 9 | ||
10 | function GenerateButton({ | 10 | export default observer(function GenerateButton({ |
11 | editorStore, | 11 | editorStore, |
12 | }: { | 12 | }: { |
13 | editorStore: EditorStore | undefined; | 13 | editorStore: EditorStore | undefined; |
@@ -53,6 +53,4 @@ function GenerateButton({ | |||
53 | {summary === '' ? GENERATE_LABEL : `${GENERATE_LABEL} (${summary})`} | 53 | {summary === '' ? GENERATE_LABEL : `${GENERATE_LABEL} (${summary})`} |
54 | </Button> | 54 | </Button> |
55 | ); | 55 | ); |
56 | } | 56 | }); |
57 | |||
58 | export default observer(GenerateButton); | ||
diff --git a/subprojects/frontend/src/editor/PanelStore.ts b/subprojects/frontend/src/editor/PanelStore.ts index e0e2b2f4..4f827280 100644 --- a/subprojects/frontend/src/editor/PanelStore.ts +++ b/subprojects/frontend/src/editor/PanelStore.ts | |||
@@ -18,13 +18,29 @@ export default class PanelStore { | |||
18 | private readonly closeCommand: Command, | 18 | private readonly closeCommand: Command, |
19 | protected readonly store: EditorStore, | 19 | protected readonly store: EditorStore, |
20 | ) { | 20 | ) { |
21 | makeObservable(this, { | 21 | makeObservable< |
22 | PanelStore, | ||
23 | | 'openCommand' | ||
24 | | 'closeCommand' | ||
25 | | 'store' | ||
26 | | 'setState' | ||
27 | | 'doOpen' | ||
28 | | 'doClose' | ||
29 | >(this, { | ||
30 | panelClass: false, | ||
31 | openCommand: false, | ||
32 | closeCommand: false, | ||
33 | store: false, | ||
22 | state: observable, | 34 | state: observable, |
23 | element: observable, | 35 | element: observable, |
36 | id: false, | ||
24 | open: action, | 37 | open: action, |
25 | close: action, | 38 | close: action, |
26 | toggle: action, | 39 | toggle: action, |
40 | setState: false, | ||
27 | synchronizeStateToView: action, | 41 | synchronizeStateToView: action, |
42 | doOpen: false, | ||
43 | doClose: false, | ||
28 | }); | 44 | }); |
29 | } | 45 | } |
30 | 46 | ||
diff --git a/subprojects/frontend/src/editor/SearchPanelPortal.tsx b/subprojects/frontend/src/editor/SearchPanelPortal.tsx index e8301489..b6b375e3 100644 --- a/subprojects/frontend/src/editor/SearchPanelPortal.tsx +++ b/subprojects/frontend/src/editor/SearchPanelPortal.tsx | |||
@@ -5,7 +5,7 @@ import React from 'react'; | |||
5 | import type EditorStore from './EditorStore'; | 5 | import type EditorStore from './EditorStore'; |
6 | import SearchToolbar from './SearchToolbar'; | 6 | import SearchToolbar from './SearchToolbar'; |
7 | 7 | ||
8 | function SearchPanelPortal({ | 8 | export default observer(function SearchPanelPortal({ |
9 | editorStore: { searchPanel: searchPanelStore }, | 9 | editorStore: { searchPanel: searchPanelStore }, |
10 | }: { | 10 | }: { |
11 | editorStore: EditorStore; | 11 | editorStore: EditorStore; |
@@ -20,6 +20,4 @@ function SearchPanelPortal({ | |||
20 | <SearchToolbar searchPanelStore={searchPanelStore} /> | 20 | <SearchToolbar searchPanelStore={searchPanelStore} /> |
21 | </Portal> | 21 | </Portal> |
22 | ); | 22 | ); |
23 | } | 23 | }); |
24 | |||
25 | export default observer(SearchPanelPortal); | ||
diff --git a/subprojects/frontend/src/editor/SearchPanelStore.ts b/subprojects/frontend/src/editor/SearchPanelStore.ts index 8dd02ae6..65d595a8 100644 --- a/subprojects/frontend/src/editor/SearchPanelStore.ts +++ b/subprojects/frontend/src/editor/SearchPanelStore.ts | |||
@@ -21,7 +21,7 @@ export default class SearchPanelStore extends PanelStore { | |||
21 | // Use a custom class name to avoid specificity issues with | 21 | // Use a custom class name to avoid specificity issues with |
22 | // CodeMirror `.cm-search.cm-panel` CSS styles. | 22 | // CodeMirror `.cm-search.cm-panel` CSS styles. |
23 | super('refinery-cm-search', openSearchPanel, closeSearchPanel, store); | 23 | super('refinery-cm-search', openSearchPanel, closeSearchPanel, store); |
24 | makeObservable(this, { | 24 | makeObservable<SearchPanelStore, 'selectSearchField'>(this, { |
25 | searchField: observable.ref, | 25 | searchField: observable.ref, |
26 | query: computed, | 26 | query: computed, |
27 | invalidRegexp: computed, | 27 | invalidRegexp: computed, |
@@ -32,6 +32,7 @@ export default class SearchPanelStore extends PanelStore { | |||
32 | findPrevious: action, | 32 | findPrevious: action, |
33 | replaceNext: action, | 33 | replaceNext: action, |
34 | replaceAll: action, | 34 | replaceAll: action, |
35 | selectSearchField: false, | ||
35 | }); | 36 | }); |
36 | } | 37 | } |
37 | 38 | ||
diff --git a/subprojects/frontend/src/editor/SearchToolbar.tsx b/subprojects/frontend/src/editor/SearchToolbar.tsx index 895f1ca1..a9b9811d 100644 --- a/subprojects/frontend/src/editor/SearchToolbar.tsx +++ b/subprojects/frontend/src/editor/SearchToolbar.tsx | |||
@@ -27,7 +27,7 @@ const DimLabel = styled(FormControlLabel)(({ theme }) => ({ | |||
27 | }, | 27 | }, |
28 | })); | 28 | })); |
29 | 29 | ||
30 | function SearchToolbar({ | 30 | export default observer(function SearchToolbar({ |
31 | searchPanelStore, | 31 | searchPanelStore, |
32 | }: { | 32 | }: { |
33 | searchPanelStore: SearchPanelStore; | 33 | searchPanelStore: SearchPanelStore; |
@@ -271,6 +271,4 @@ function SearchToolbar({ | |||
271 | </Stack> | 271 | </Stack> |
272 | </Toolbar> | 272 | </Toolbar> |
273 | ); | 273 | ); |
274 | } | 274 | }); |
275 | |||
276 | export default observer(SearchToolbar); | ||
diff --git a/subprojects/frontend/src/index.tsx b/subprojects/frontend/src/index.tsx index 3f06b332..8436c7ae 100644 --- a/subprojects/frontend/src/index.tsx +++ b/subprojects/frontend/src/index.tsx | |||
@@ -1,5 +1,6 @@ | |||
1 | import Box from '@mui/material/Box'; | 1 | import Box from '@mui/material/Box'; |
2 | import CssBaseline from '@mui/material/CssBaseline'; | 2 | import CssBaseline from '@mui/material/CssBaseline'; |
3 | import { configure } from 'mobx'; | ||
3 | import { SnackbarProvider } from 'notistack'; | 4 | import { SnackbarProvider } from 'notistack'; |
4 | import React, { Suspense, lazy } from 'react'; | 5 | import React, { Suspense, lazy } from 'react'; |
5 | import { createRoot } from 'react-dom/client'; | 6 | import { createRoot } from 'react-dom/client'; |
@@ -60,6 +61,11 @@ age(bob, bobAge). | |||
60 | scope Family = 1, Person += 5..10. | 61 | scope Family = 1, Person += 5..10. |
61 | `; | 62 | `; |
62 | 63 | ||
64 | configure({ | ||
65 | enforceActions: 'always', | ||
66 | reactionRequiresObservable: true, | ||
67 | }); | ||
68 | |||
63 | const rootStore = new RootStore(initialValue); | 69 | const rootStore = new RootStore(initialValue); |
64 | 70 | ||
65 | const App = lazy(() => import('./App.js')); | 71 | const App = lazy(() => import('./App.js')); |
diff --git a/subprojects/frontend/src/theme/ThemeProvider.tsx b/subprojects/frontend/src/theme/ThemeProvider.tsx index 5aaf3ad1..6f9a712e 100644 --- a/subprojects/frontend/src/theme/ThemeProvider.tsx +++ b/subprojects/frontend/src/theme/ThemeProvider.tsx | |||
@@ -313,7 +313,11 @@ ContrastThemeProvider.defaultProps = { | |||
313 | children: undefined, | 313 | children: undefined, |
314 | }; | 314 | }; |
315 | 315 | ||
316 | function ThemeProvider({ children }: { children?: ReactNode }): JSX.Element { | 316 | const ThemeProvider = observer(function ThemeProvider({ |
317 | children, | ||
318 | }: { | ||
319 | children?: ReactNode; | ||
320 | }): JSX.Element { | ||
317 | const { | 321 | const { |
318 | themeStore: { darkMode }, | 322 | themeStore: { darkMode }, |
319 | } = useRootStore(); | 323 | } = useRootStore(); |
@@ -326,10 +330,10 @@ function ThemeProvider({ children }: { children?: ReactNode }): JSX.Element { | |||
326 | {children} | 330 | {children} |
327 | </ThemeAndContrastThemeProvider> | 331 | </ThemeAndContrastThemeProvider> |
328 | ); | 332 | ); |
329 | } | 333 | }); |
330 | 334 | ||
331 | ThemeProvider.defaultProps = { | 335 | ThemeProvider.defaultProps = { |
332 | children: undefined, | 336 | children: undefined, |
333 | }; | 337 | }; |
334 | 338 | ||
335 | export default observer(ThemeProvider); | 339 | export default ThemeProvider; |
diff --git a/subprojects/frontend/src/theme/ThemeStore.ts b/subprojects/frontend/src/theme/ThemeStore.ts index 6fbd9f90..e09d8d99 100644 --- a/subprojects/frontend/src/theme/ThemeStore.ts +++ b/subprojects/frontend/src/theme/ThemeStore.ts | |||
@@ -1,4 +1,4 @@ | |||
1 | import { action, computed, makeObservable, observable } from 'mobx'; | 1 | import { makeAutoObservable } from 'mobx'; |
2 | 2 | ||
3 | export enum ThemePreference { | 3 | export enum ThemePreference { |
4 | System, | 4 | System, |
@@ -17,12 +17,7 @@ export default class ThemeStore { | |||
17 | mediaQuery.addEventListener('change', (event) => { | 17 | mediaQuery.addEventListener('change', (event) => { |
18 | this.systemDarkMode = event.matches; | 18 | this.systemDarkMode = event.matches; |
19 | }); | 19 | }); |
20 | makeObservable(this, { | 20 | makeAutoObservable(this); |
21 | preference: observable, | ||
22 | systemDarkMode: observable, | ||
23 | darkMode: computed, | ||
24 | toggleDarkMode: action, | ||
25 | }); | ||
26 | } | 21 | } |
27 | 22 | ||
28 | get darkMode(): boolean { | 23 | get darkMode(): boolean { |
@@ -1569,20 +1569,20 @@ __metadata: | |||
1569 | languageName: node | 1569 | languageName: node |
1570 | linkType: hard | 1570 | linkType: hard |
1571 | 1571 | ||
1572 | "@eslint/eslintrc@npm:^1.3.0": | 1572 | "@eslint/eslintrc@npm:^1.3.1": |
1573 | version: 1.3.0 | 1573 | version: 1.3.1 |
1574 | resolution: "@eslint/eslintrc@npm:1.3.0" | 1574 | resolution: "@eslint/eslintrc@npm:1.3.1" |
1575 | dependencies: | 1575 | dependencies: |
1576 | ajv: ^6.12.4 | 1576 | ajv: ^6.12.4 |
1577 | debug: ^4.3.2 | 1577 | debug: ^4.3.2 |
1578 | espree: ^9.3.2 | 1578 | espree: ^9.4.0 |
1579 | globals: ^13.15.0 | 1579 | globals: ^13.15.0 |
1580 | ignore: ^5.2.0 | 1580 | ignore: ^5.2.0 |
1581 | import-fresh: ^3.2.1 | 1581 | import-fresh: ^3.2.1 |
1582 | js-yaml: ^4.1.0 | 1582 | js-yaml: ^4.1.0 |
1583 | minimatch: ^3.1.2 | 1583 | minimatch: ^3.1.2 |
1584 | strip-json-comments: ^3.1.1 | 1584 | strip-json-comments: ^3.1.1 |
1585 | checksum: a1e734ad31a8b5328dce9f479f185fd4fc83dd7f06c538e1fa457fd8226b89602a55cc6458cd52b29573b01cdfaf42331be8cfc1fec732570086b591f4ed6515 | 1585 | checksum: 9844dcc58a44399649926d5a17a2d53d529b80d3e8c3e9d0964ae198bac77ee6bb1cf44940f30cd9c2e300f7568ec82500be42ace6cacefb08aebf9905fe208e |
1586 | languageName: node | 1586 | languageName: node |
1587 | linkType: hard | 1587 | linkType: hard |
1588 | 1588 | ||
@@ -1625,6 +1625,13 @@ __metadata: | |||
1625 | languageName: node | 1625 | languageName: node |
1626 | linkType: hard | 1626 | linkType: hard |
1627 | 1627 | ||
1628 | "@humanwhocodes/module-importer@npm:^1.0.1": | ||
1629 | version: 1.0.1 | ||
1630 | resolution: "@humanwhocodes/module-importer@npm:1.0.1" | ||
1631 | checksum: 0fd22007db8034a2cdf2c764b140d37d9020bbfce8a49d3ec5c05290e77d4b0263b1b972b752df8c89e5eaa94073408f2b7d977aed131faf6cf396ebb5d7fb61 | ||
1632 | languageName: node | ||
1633 | linkType: hard | ||
1634 | |||
1628 | "@humanwhocodes/object-schema@npm:^1.2.1": | 1635 | "@humanwhocodes/object-schema@npm:^1.2.1": |
1629 | version: 1.2.1 | 1636 | version: 1.2.1 |
1630 | resolution: "@humanwhocodes/object-schema@npm:1.2.1" | 1637 | resolution: "@humanwhocodes/object-schema@npm:1.2.1" |
@@ -2013,15 +2020,16 @@ __metadata: | |||
2013 | ansi-styles: ^6.1.0 | 2020 | ansi-styles: ^6.1.0 |
2014 | cross-env: ^7.0.3 | 2021 | cross-env: ^7.0.3 |
2015 | escape-string-regexp: ^5.0.0 | 2022 | escape-string-regexp: ^5.0.0 |
2016 | eslint: ^8.22.0 | 2023 | eslint: ^8.23.0 |
2017 | eslint-config-airbnb: ^19.0.4 | 2024 | eslint-config-airbnb: ^19.0.4 |
2018 | eslint-config-airbnb-typescript: ^17.0.0 | 2025 | eslint-config-airbnb-typescript: ^17.0.0 |
2019 | eslint-config-prettier: ^8.5.0 | 2026 | eslint-config-prettier: ^8.5.0 |
2020 | eslint-import-resolver-typescript: ^3.5.0 | 2027 | eslint-import-resolver-typescript: ^3.5.0 |
2021 | eslint-plugin-import: ^2.26.0 | 2028 | eslint-plugin-import: ^2.26.0 |
2022 | eslint-plugin-jsx-a11y: ^6.6.1 | 2029 | eslint-plugin-jsx-a11y: ^6.6.1 |
2030 | eslint-plugin-mobx: ^0.0.9 | ||
2023 | eslint-plugin-prettier: ^4.2.1 | 2031 | eslint-plugin-prettier: ^4.2.1 |
2024 | eslint-plugin-react: ^7.31.0 | 2032 | eslint-plugin-react: ^7.31.1 |
2025 | eslint-plugin-react-hooks: ^4.6.0 | 2033 | eslint-plugin-react-hooks: ^4.6.0 |
2026 | html-minifier-terser: ^7.0.0 | 2034 | html-minifier-terser: ^7.0.0 |
2027 | lodash-es: ^4.17.21 | 2035 | lodash-es: ^4.17.21 |
@@ -2047,7 +2055,7 @@ __metadata: | |||
2047 | version: 0.0.0-use.local | 2055 | version: 0.0.0-use.local |
2048 | resolution: "@refinery/root@workspace:." | 2056 | resolution: "@refinery/root@workspace:." |
2049 | dependencies: | 2057 | dependencies: |
2050 | eslint: ^8.22.0 | 2058 | eslint: ^8.23.0 |
2051 | typescript: ~4.8.2 | 2059 | typescript: ~4.8.2 |
2052 | languageName: unknown | 2060 | languageName: unknown |
2053 | linkType: soft | 2061 | linkType: soft |
@@ -3676,6 +3684,15 @@ __metadata: | |||
3676 | languageName: node | 3684 | languageName: node |
3677 | linkType: hard | 3685 | linkType: hard |
3678 | 3686 | ||
3687 | "eslint-plugin-mobx@npm:^0.0.9": | ||
3688 | version: 0.0.9 | ||
3689 | resolution: "eslint-plugin-mobx@npm:0.0.9" | ||
3690 | peerDependencies: | ||
3691 | eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 | ||
3692 | checksum: 6ccbce066f3ca34799ce32fcf885b9f163712c684ed3b4dfbfe7c690ede03a76b25fd598d6a4e9885cc9b08d4ca722a469bd4f1da2ef00def1c00be6378425a5 | ||
3693 | languageName: node | ||
3694 | linkType: hard | ||
3695 | |||
3679 | "eslint-plugin-prettier@npm:^4.2.1": | 3696 | "eslint-plugin-prettier@npm:^4.2.1": |
3680 | version: 4.2.1 | 3697 | version: 4.2.1 |
3681 | resolution: "eslint-plugin-prettier@npm:4.2.1" | 3698 | resolution: "eslint-plugin-prettier@npm:4.2.1" |
@@ -3700,9 +3717,9 @@ __metadata: | |||
3700 | languageName: node | 3717 | languageName: node |
3701 | linkType: hard | 3718 | linkType: hard |
3702 | 3719 | ||
3703 | "eslint-plugin-react@npm:^7.31.0": | 3720 | "eslint-plugin-react@npm:^7.31.1": |
3704 | version: 7.31.0 | 3721 | version: 7.31.1 |
3705 | resolution: "eslint-plugin-react@npm:7.31.0" | 3722 | resolution: "eslint-plugin-react@npm:7.31.1" |
3706 | dependencies: | 3723 | dependencies: |
3707 | array-includes: ^3.1.5 | 3724 | array-includes: ^3.1.5 |
3708 | array.prototype.flatmap: ^1.3.0 | 3725 | array.prototype.flatmap: ^1.3.0 |
@@ -3720,7 +3737,7 @@ __metadata: | |||
3720 | string.prototype.matchall: ^4.0.7 | 3737 | string.prototype.matchall: ^4.0.7 |
3721 | peerDependencies: | 3738 | peerDependencies: |
3722 | eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 | 3739 | eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 |
3723 | checksum: 465829bb477f3adf0ce96294c2b9c97147414a449d14f4dde21711f38213924a4facd567f7263be67958f284edf5ea25cf9f996bc95240d74cfa2ee95b1c81a6 | 3740 | checksum: 6217d4c4e36c8fea24facd0cdcf22b2fd38a3603db94ec7c0a6f430046c8564b6c6884e0a9d4a4b8766201f66e8b18af594002210421bf9b6623b1fc32e15a3a |
3724 | languageName: node | 3741 | languageName: node |
3725 | linkType: hard | 3742 | linkType: hard |
3726 | 3743 | ||
@@ -3769,13 +3786,14 @@ __metadata: | |||
3769 | languageName: node | 3786 | languageName: node |
3770 | linkType: hard | 3787 | linkType: hard |
3771 | 3788 | ||
3772 | "eslint@npm:^8.22.0": | 3789 | "eslint@npm:^8.23.0": |
3773 | version: 8.22.0 | 3790 | version: 8.23.0 |
3774 | resolution: "eslint@npm:8.22.0" | 3791 | resolution: "eslint@npm:8.23.0" |
3775 | dependencies: | 3792 | dependencies: |
3776 | "@eslint/eslintrc": ^1.3.0 | 3793 | "@eslint/eslintrc": ^1.3.1 |
3777 | "@humanwhocodes/config-array": ^0.10.4 | 3794 | "@humanwhocodes/config-array": ^0.10.4 |
3778 | "@humanwhocodes/gitignore-to-minimatch": ^1.0.2 | 3795 | "@humanwhocodes/gitignore-to-minimatch": ^1.0.2 |
3796 | "@humanwhocodes/module-importer": ^1.0.1 | ||
3779 | ajv: ^6.10.0 | 3797 | ajv: ^6.10.0 |
3780 | chalk: ^4.0.0 | 3798 | chalk: ^4.0.0 |
3781 | cross-spawn: ^7.0.2 | 3799 | cross-spawn: ^7.0.2 |
@@ -3785,7 +3803,7 @@ __metadata: | |||
3785 | eslint-scope: ^7.1.1 | 3803 | eslint-scope: ^7.1.1 |
3786 | eslint-utils: ^3.0.0 | 3804 | eslint-utils: ^3.0.0 |
3787 | eslint-visitor-keys: ^3.3.0 | 3805 | eslint-visitor-keys: ^3.3.0 |
3788 | espree: ^9.3.3 | 3806 | espree: ^9.4.0 |
3789 | esquery: ^1.4.0 | 3807 | esquery: ^1.4.0 |
3790 | esutils: ^2.0.2 | 3808 | esutils: ^2.0.2 |
3791 | fast-deep-equal: ^3.1.3 | 3809 | fast-deep-equal: ^3.1.3 |
@@ -3811,21 +3829,20 @@ __metadata: | |||
3811 | strip-ansi: ^6.0.1 | 3829 | strip-ansi: ^6.0.1 |
3812 | strip-json-comments: ^3.1.0 | 3830 | strip-json-comments: ^3.1.0 |
3813 | text-table: ^0.2.0 | 3831 | text-table: ^0.2.0 |
3814 | v8-compile-cache: ^2.0.3 | ||
3815 | bin: | 3832 | bin: |
3816 | eslint: bin/eslint.js | 3833 | eslint: bin/eslint.js |
3817 | checksum: 2d84a7a2207138cdb250759b047fdb05a57fede7f87b7a039d9370edba7f26e23a873a208becfd4b2c9e4b5499029f3fc3b9318da3290e693d25c39084119c80 | 3834 | checksum: ff6075daa28d817a7ac4508f31bc108a04d9ab5056608c8651b5bf9cfea5d708ca16dea6cdab2c3c0ae99b0bf0e726af8504eaa8e17c8e12e242cb68237ead64 |
3818 | languageName: node | 3835 | languageName: node |
3819 | linkType: hard | 3836 | linkType: hard |
3820 | 3837 | ||
3821 | "espree@npm:^9.3.2, espree@npm:^9.3.3": | 3838 | "espree@npm:^9.4.0": |
3822 | version: 9.3.3 | 3839 | version: 9.4.0 |
3823 | resolution: "espree@npm:9.3.3" | 3840 | resolution: "espree@npm:9.4.0" |
3824 | dependencies: | 3841 | dependencies: |
3825 | acorn: ^8.8.0 | 3842 | acorn: ^8.8.0 |
3826 | acorn-jsx: ^5.3.2 | 3843 | acorn-jsx: ^5.3.2 |
3827 | eslint-visitor-keys: ^3.3.0 | 3844 | eslint-visitor-keys: ^3.3.0 |
3828 | checksum: 33e8a36fc15d082e68672e322e22a53856b564d60aad8f291a667bfc21b2c900c42412d37dd3c7a0f18b9d0d8f8858dabe8776dbd4b4c2f72c5cf4d6afeabf65 | 3845 | checksum: 2e3020dde67892d2ba3632413b44d0dc31d92c29ce72267d7ec24216a562f0a6494d3696e2fa39a3ec8c0e0088d773947ab2925fbb716801a11eb8dd313ac89c |
3829 | languageName: node | 3846 | languageName: node |
3830 | linkType: hard | 3847 | linkType: hard |
3831 | 3848 | ||
@@ -6577,13 +6594,6 @@ __metadata: | |||
6577 | languageName: node | 6594 | languageName: node |
6578 | linkType: hard | 6595 | linkType: hard |
6579 | 6596 | ||
6580 | "v8-compile-cache@npm:^2.0.3": | ||
6581 | version: 2.3.0 | ||
6582 | resolution: "v8-compile-cache@npm:2.3.0" | ||
6583 | checksum: adb0a271eaa2297f2f4c536acbfee872d0dd26ec2d76f66921aa7fc437319132773483344207bdbeee169225f4739016d8d2dbf0553913a52bb34da6d0334f8e | ||
6584 | languageName: node | ||
6585 | linkType: hard | ||
6586 | |||
6587 | "vite-plugin-inject-preload@npm:^1.1.0": | 6597 | "vite-plugin-inject-preload@npm:^1.1.0": |
6588 | version: 1.1.0 | 6598 | version: 1.1.0 |
6589 | resolution: "vite-plugin-inject-preload@npm:1.1.0" | 6599 | resolution: "vite-plugin-inject-preload@npm:1.1.0" |