From 6c9e3edef5bc92dc9e4a147ff9d64f22e76af08b Mon Sep 17 00:00:00 2001 From: Merlin Osayimwen Date: Tue, 26 Jul 2022 14:08:51 +0100 Subject: [PATCH] Restyle --- .../evaluation/shell/ShellEvaluation.java | 25 ++ .../shell/ExhaustiveExecutionTest.java | 7 + .../monitoring/ForkEnvironmentMonitoring.java | 2 +- website/package-lock.json | 71 ++++++ website/package.json | 2 + website/public/discord.svg | 10 + website/src/App.tsx | 99 ++++---- website/src/editor/Editor.tsx | 24 +- .../src/editor/{themes/dark.ts => theme.ts} | 2 +- website/src/editor/themes/light.ts | 56 ----- website/src/editor/themes/themes.ts | 14 -- website/src/header/Header.style.ts | 19 -- website/src/header/Header.tsx | 37 --- website/src/header/Logo.style.ts | 16 -- website/src/header/Logo.tsx | 14 -- website/src/index.css | 25 +- website/src/index.tsx | 43 ++-- website/src/layout/Footer.module.css | 0 website/src/layout/Footer.tsx | 40 ++++ website/src/layout/Header.module.css | 50 ++++ website/src/layout/Header.tsx | 30 +++ website/src/layout/Page.module.css | 0 website/src/layout/Page.tsx | 20 ++ website/src/sheet/ImportedSheet.tsx | 3 - website/src/sheet/ShareModal.tsx | 10 +- website/src/sheet/Sheet.tsx | 5 +- website/src/sheet/evaluation.ts | 8 + website/src/sheet/snippet/Snippet.module.css | 56 +++++ website/src/sheet/snippet/Snippet.style.ts | 27 --- website/src/sheet/snippet/Snippet.tsx | 224 +++--------------- website/src/sheet/snippet/SnippetContext.tsx | 13 + .../src/sheet/snippet/SnippetExtras.style.ts | 9 - website/src/sheet/snippet/SnippetExtras.tsx | 89 ------- website/src/sheet/snippet/SnippetX.tsx | 188 +++++++++++++++ website/src/sheet/snippet/Title.style.tsx | 43 ---- website/src/sheet/snippet/Title.tsx | 35 --- .../component/ComponentContainer.style.ts | 11 +- .../sheet/snippet/component/ComponentList.tsx | 2 +- .../snippet/component/TextComponent.style.ts | 5 +- .../sheet/snippet/component/TextComponent.tsx | 4 - ...eREquest.ts => createEvaluationRequest.ts} | 2 +- website/src/theme/ThemeContext.tsx | 122 ---------- website/src/theme/ToggleButton.tsx | 16 -- website/src/theme/dark.less | 17 -- website/src/theme/light.less | 17 -- website/src/theme/theme.ts | 65 ----- website/src/theme/themed.ts | 28 --- website/src/theme/updateTheme.ts | 97 -------- website/src/version.ts | 1 + 49 files changed, 677 insertions(+), 1026 deletions(-) create mode 100644 website/public/discord.svg rename website/src/editor/{themes/dark.ts => theme.ts} (97%) delete mode 100644 website/src/editor/themes/light.ts delete mode 100644 website/src/editor/themes/themes.ts delete mode 100644 website/src/header/Header.style.ts delete mode 100644 website/src/header/Header.tsx delete mode 100644 website/src/header/Logo.style.ts delete mode 100644 website/src/header/Logo.tsx create mode 100644 website/src/layout/Footer.module.css create mode 100644 website/src/layout/Footer.tsx create mode 100644 website/src/layout/Header.module.css create mode 100644 website/src/layout/Header.tsx create mode 100644 website/src/layout/Page.module.css create mode 100644 website/src/layout/Page.tsx create mode 100644 website/src/sheet/evaluation.ts create mode 100644 website/src/sheet/snippet/Snippet.module.css delete mode 100644 website/src/sheet/snippet/Snippet.style.ts create mode 100644 website/src/sheet/snippet/SnippetContext.tsx delete mode 100644 website/src/sheet/snippet/SnippetExtras.style.ts delete mode 100644 website/src/sheet/snippet/SnippetExtras.tsx create mode 100644 website/src/sheet/snippet/SnippetX.tsx delete mode 100644 website/src/sheet/snippet/Title.style.tsx delete mode 100644 website/src/sheet/snippet/Title.tsx rename website/src/sheet/snippet/{createEvaluateREquest.ts => createEvaluationRequest.ts} (96%) delete mode 100644 website/src/theme/ThemeContext.tsx delete mode 100644 website/src/theme/ToggleButton.tsx delete mode 100644 website/src/theme/dark.less delete mode 100644 website/src/theme/light.less delete mode 100644 website/src/theme/theme.ts delete mode 100644 website/src/theme/themed.ts delete mode 100644 website/src/theme/updateTheme.ts create mode 100644 website/src/version.ts diff --git a/evaluation/src/main/java/jsheets/evaluation/shell/ShellEvaluation.java b/evaluation/src/main/java/jsheets/evaluation/shell/ShellEvaluation.java index d0c4cfc..a936530 100644 --- a/evaluation/src/main/java/jsheets/evaluation/shell/ShellEvaluation.java +++ b/evaluation/src/main/java/jsheets/evaluation/shell/ShellEvaluation.java @@ -1,5 +1,7 @@ package jsheets.evaluation.shell; +import java.io.PrintWriter; +import java.io.StringWriter; import java.time.Clock; import java.time.Duration; import java.time.Instant; @@ -178,6 +180,9 @@ private void reportSnippetEvent( ) { switch (event.status()) { case VALID -> { + if (event.exception() != null && event.exception().getCause() != null) { + reportException(componentId, event.exception().getCause(), response); + } if (event.value() == null) { return; } @@ -193,6 +198,26 @@ private void reportSnippetEvent( } } + private void reportException( + String componentId, + Throwable exception, + EvaluateResponse.Builder response + ) { + response.addError( + EvaluationError.newBuilder() + .setComponentId(componentId) + .setKind("exception") + .setMessage(formatException(exception)) + .build() + ); + } + + private String formatException(Throwable exception) { + var output = new StringWriter(); + exception.printStackTrace(new PrintWriter(output)); + return output.toString(); + } + private void reportFailure( String componentId, SnippetEvent event, diff --git a/evaluation/src/test/java/jsheets/evaluation/shell/ExhaustiveExecutionTest.java b/evaluation/src/test/java/jsheets/evaluation/shell/ExhaustiveExecutionTest.java index f5ce0f5..6e90d80 100644 --- a/evaluation/src/test/java/jsheets/evaluation/shell/ExhaustiveExecutionTest.java +++ b/evaluation/src/test/java/jsheets/evaluation/shell/ExhaustiveExecutionTest.java @@ -71,4 +71,11 @@ public void testInvalid() { .execute("callWithoutClosedParen(someArgument, 1, 2, 3"); Assertions.assertEquals(1, events.size()); } + + @Test + public void textExceptionCapture() { + var events = ExhaustiveExecution.create(createSilentShell()) + .execute("throw new RuntimeException();"); + Assertions.assertEquals(1, events.size()); + } } \ No newline at end of file diff --git a/runtime/src/main/java/jsheets/runtime/monitoring/ForkEnvironmentMonitoring.java b/runtime/src/main/java/jsheets/runtime/monitoring/ForkEnvironmentMonitoring.java index ee3f29f..19ae2b8 100644 --- a/runtime/src/main/java/jsheets/runtime/monitoring/ForkEnvironmentMonitoring.java +++ b/runtime/src/main/java/jsheets/runtime/monitoring/ForkEnvironmentMonitoring.java @@ -16,7 +16,7 @@ static ForkEnvironmentMonitoring register(MeterRegistry metrics) { ); var startedBoxes = Counter .builder("jsheets.runtime.evaluation.fork.startedBoxes") - .description("The number of boxes that have been started") + .description("The number of cells that have been started") .register(metrics); return new ForkEnvironmentMonitoring(activeBoxCount, startedBoxes); } diff --git a/website/package-lock.json b/website/package-lock.json index 6267627..e560f24 100644 --- a/website/package-lock.json +++ b/website/package-lock.json @@ -26,6 +26,7 @@ "google-protobuf": "^3.18.0", "i18next": "^20.6.1", "install": "^0.13.0", + "jotai": "^1.7.6", "npm": "^7.21.0", "prosemirror-utils": "^1.0.0-0", "react": "^17.0.2", @@ -35,6 +36,7 @@ "react-redux": "^7.2.5", "react-router-dom": "^5.3.0", "react-scripts": "4.0.3", + "remixicon-react": "^1.0.0", "rich-markdown-editor": "^11.17.8", "styled-components": "^5.3.1", "typescript": "^4.3.5", @@ -13658,6 +13660,55 @@ "node": ">=8" } }, + "node_modules/jotai": { + "version": "1.7.6", + "resolved": "https://registry.npmjs.org/jotai/-/jotai-1.7.6.tgz", + "integrity": "sha512-D3R5f6OvwUPUyTPQY3wGP800nb6bDEOl/mqftjxg3gcHVITeFcldr9W9IBK+gXsow357vhNXuci/LfD+rl92PA==", + "engines": { + "node": ">=12.7.0" + }, + "peerDependencies": { + "@babel/core": "*", + "@babel/template": "*", + "@urql/core": "*", + "immer": "*", + "optics-ts": "*", + "react": ">=16.8", + "react-query": "*", + "valtio": "*", + "wonka": "*", + "xstate": "*" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "@babel/template": { + "optional": true + }, + "@urql/core": { + "optional": true + }, + "immer": { + "optional": true + }, + "optics-ts": { + "optional": true + }, + "react-query": { + "optional": true + }, + "valtio": { + "optional": true + }, + "wonka": { + "optional": true + }, + "xstate": { + "optional": true + } + } + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -21874,6 +21925,14 @@ "node": ">= 0.10" } }, + "node_modules/remixicon-react": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/remixicon-react/-/remixicon-react-1.0.0.tgz", + "integrity": "sha512-KOXlc8EdKdujr2f/2idyFSQRjUB8p0HNiWZYBBzRsTRlTXFuSAFfnGq9culNjhCGmc92Jbtfr9OP0MXWvTMdsQ==", + "peerDependencies": { + "react": ">=0.14.0" + } + }, "node_modules/remove-trailing-separator": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", @@ -37200,6 +37259,12 @@ } } }, + "jotai": { + "version": "1.7.6", + "resolved": "https://registry.npmjs.org/jotai/-/jotai-1.7.6.tgz", + "integrity": "sha512-D3R5f6OvwUPUyTPQY3wGP800nb6bDEOl/mqftjxg3gcHVITeFcldr9W9IBK+gXsow357vhNXuci/LfD+rl92PA==", + "requires": {} + }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -43529,6 +43594,12 @@ "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", "integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=" }, + "remixicon-react": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/remixicon-react/-/remixicon-react-1.0.0.tgz", + "integrity": "sha512-KOXlc8EdKdujr2f/2idyFSQRjUB8p0HNiWZYBBzRsTRlTXFuSAFfnGq9culNjhCGmc92Jbtfr9OP0MXWvTMdsQ==", + "requires": {} + }, "remove-trailing-separator": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", diff --git a/website/package.json b/website/package.json index 913c8f9..752aec8 100644 --- a/website/package.json +++ b/website/package.json @@ -21,6 +21,7 @@ "google-protobuf": "^3.18.0", "i18next": "^20.6.1", "install": "^0.13.0", + "jotai": "^1.7.6", "npm": "^7.21.0", "prosemirror-utils": "^1.0.0-0", "react": "^17.0.2", @@ -30,6 +31,7 @@ "react-redux": "^7.2.5", "react-router-dom": "^5.3.0", "react-scripts": "4.0.3", + "remixicon-react": "^1.0.0", "rich-markdown-editor": "^11.17.8", "styled-components": "^5.3.1", "typescript": "^4.3.5", diff --git a/website/public/discord.svg b/website/public/discord.svg new file mode 100644 index 0000000..f905d23 --- /dev/null +++ b/website/public/discord.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/website/src/App.tsx b/website/src/App.tsx index bcfcf74..e8755ec 100644 --- a/website/src/App.tsx +++ b/website/src/App.tsx @@ -1,9 +1,6 @@ import React, {useCallback, useState} from 'react' -import {Layout} from 'antd' -import {Content} from 'antd/lib/layout/layout' -import Sheet from './sheet/Sheet' +import Sheet, {CaptureSnippetReference} from './sheet/Sheet' import useEvaluate from './sheet/useEvaluate' -import Header from './header/Header' import { Route, Switch, @@ -13,60 +10,72 @@ import {useShare} from './sheet/useShare' import ImportedSheet from './sheet/ImportedSheet' import ShareModal from './sheet/ShareModal' import {createBlankSheet, createWelcomeSheet} from './sheet/defaultSheet' +import Page from './layout/Page' const welcomeSheet = createWelcomeSheet() const blankSheet = createBlankSheet() -export default function App() { - const [evaluate, evaluating, cooldown] = useEvaluate() - const history = useHistory() +interface UseShareModal { + component: React.ReactNode + open: () => void + captureSnippet: CaptureSnippetReference +} + +function useShareModal(): UseShareModal { const [sharedId, setSharedId] = useState('') const [shareVisible, setShareVisible] = useState(false) + const history = useHistory() const callback = useCallback(created => { history.push(`/s/${created.id}`) setShareVisible(true) setSharedId(created.id) }, [history]) - const [share, captureSnippet] = useShare(callback) + const [open, captureSnippet] = useShare(callback) + + const component = + + return {component, open, captureSnippet} +} + +export default function App() { + const [evaluate, evaluating, cooldown] = useEvaluate() + const {open, component, captureSnippet} = useShareModal() return ( - -
- - + {component} + + + + + + + + + - - - - - - - - - - - - - + + + ) } diff --git a/website/src/editor/Editor.tsx b/website/src/editor/Editor.tsx index 043eb1c..d747a00 100644 --- a/website/src/editor/Editor.tsx +++ b/website/src/editor/Editor.tsx @@ -2,13 +2,12 @@ import React, {useEffect} from 'react' import {EditorView} from '@codemirror/view' import {Compartment, EditorState} from '@codemirror/state' import {basicSetup} from '@codemirror/basic-setup' -import {java} from "./java/language"; -import {ThemeKey, useTheme} from '../theme/ThemeContext' -import {editorThemes, highlightingThemes} from './themes/themes' +import {java} from './java/language' +import {highlighting, theme} from './theme' const tabSize = 2 -function createView(initialContent: string, element: Element, theme: ThemeKey) { +function createView(initialContent: string, element: Element) { return new EditorView({ parent: element, state: EditorState.create({ @@ -17,8 +16,8 @@ function createView(initialContent: string, element: Element, theme: ThemeKey) { basicSetup, EditorState.tabSize.of(tabSize), java(), - themeState.of(editorThemes[theme]), - highlightingState.of(highlightingThemes[theme]) + themeState.of(theme), + highlightingState.of(highlighting) ] }) }) @@ -34,14 +33,13 @@ const highlightingState = new Compartment() export default function Editor(properties: EditorProperties) { const element = React.createRef() - const editor = React.useRef<{editor: EditorView | undefined}>({editor: undefined}) - const [theme] = useTheme() + const editor = React.useRef<{ editor: EditorView | undefined }>({editor: undefined}) useEffect(() => { if (element == null) { return } - const created = createView(properties.code, element.current!, theme) + const created = createView(properties.code, element.current!) editor.current.editor = created if (properties.editorRef) { properties.editorRef.current = created @@ -49,14 +47,6 @@ export default function Editor(properties: EditorProperties) { return () => created.destroy() }, [properties.editorRef]) - useEffect(() => { - properties.editorRef?.current?.dispatch({ - effects: [ - themeState.reconfigure(editorThemes[theme]), - highlightingState.reconfigure(highlightingThemes[theme]) - ] - }) - }, [theme]) return (
) } \ No newline at end of file diff --git a/website/src/editor/themes/dark.ts b/website/src/editor/theme.ts similarity index 97% rename from website/src/editor/themes/dark.ts rename to website/src/editor/theme.ts index b2f6c85..ce59ba1 100644 --- a/website/src/editor/themes/dark.ts +++ b/website/src/editor/theme.ts @@ -1,6 +1,6 @@ import {HighlightStyle, tags as t} from '@codemirror/highlight' -import {customTags} from '../java/language' import {EditorView} from '@codemirror/view' +import {customTags} from './java/language' export const theme = EditorView.theme({ ".cm-scroller": { diff --git a/website/src/editor/themes/light.ts b/website/src/editor/themes/light.ts deleted file mode 100644 index c7027db..0000000 --- a/website/src/editor/themes/light.ts +++ /dev/null @@ -1,56 +0,0 @@ -import {EditorView} from '@codemirror/view' -import {HighlightStyle, tags as t} from '@codemirror/highlight' -import {customTags} from '../java/language' - -export const theme = EditorView.theme({ - ".cm-scroller": { - fontFamily: `'JetBrains Mono', 'Roboto Mono', Menlo, Monaco, source-code-pro, Consolas, monospace` - }, - "&": { - color: "#24292e", - backgroundColor: "#f6f8fa", - padding: "10px 0" - }, - ".cm-matchingBracket": { - color: "#2b2b2b", - }, - ".cm-activeLineGutter, .cm-activeLine": { - backgroundColor: "#f8f8f8" - }, - ".cm-content": { - caretColor: "#424242" - }, - "&.cm-focused .cm-cursor": { - borderLeftColor: "#b6b6b6" - }, - "&.cm-focused .cm-selectionBackground, ::selection": { - backgroundColor: "#a2a2a2" - }, - ".cm-gutters": { - backgroundColor: "#f6f8fa", - color: "#ddd", - border: "none" - }, -}, {dark: false}) - -export const highlighting = HighlightStyle.define([ - {tag: t.function(t.name), color: '#00627A'}, - {tag: t.standard(t.typeName), fontStyle: 'bold', color: '#E75A7C'}, - {tag: customTags.annotationAttribute, color: '#8250df'}, - {tag: t.typeName, fontStyle: 'bold', color: '#89D2DC'}, - {tag: t.function(customTags.call), color: '#502cc5'}, - {tag: t.constant(t.variableName), color: '#0550ae'}, - {tag: t.className, color: '#6564DB'}, - {tag: t.keyword, color: '#D73A49'}, - {tag: t.definitionKeyword, color: '#D73A49'}, - {tag: t.controlKeyword, color: '#D73A49'}, - {tag: t.operatorKeyword, color: '#D73A49'}, - {tag: t.annotation, color: "#9E880D"}, - {tag: t.function(t.definition(t.variableName)), color: '#871094'}, - {tag: t.definition(t.variableName), color: "#6f42c1"}, - {tag: t.constant, color: '#005cc5'}, - {tag: t.operator, color: '#D73A49'}, - {tag: t.number, color: '#1750EB'}, - {tag: t.string, color: '#067D17'}, - {tag: t.comment, color: '#6a737d'} -]) diff --git a/website/src/editor/themes/themes.ts b/website/src/editor/themes/themes.ts deleted file mode 100644 index 283a913..0000000 --- a/website/src/editor/themes/themes.ts +++ /dev/null @@ -1,14 +0,0 @@ -import * as darkTheme from './dark' -import * as lightTheme from './light' -import {ThemeTable} from '../../theme/ThemeContext' -import {Extension} from '@codemirror/state' - -export const editorThemes: ThemeTable = { - light: lightTheme.theme, - dark: darkTheme.theme -} - -export const highlightingThemes: ThemeTable = { - light: lightTheme.highlighting, - dark: darkTheme.highlighting -} diff --git a/website/src/header/Header.style.ts b/website/src/header/Header.style.ts deleted file mode 100644 index 4a76e51..0000000 --- a/website/src/header/Header.style.ts +++ /dev/null @@ -1,19 +0,0 @@ -import styled from "styled-components"; -import {Header as AntdHeader} from "antd/lib/layout/layout"; -import {Menu as AntdMenu} from "antd"; -import themed from '../theme/themed' - -export const Header = styled(AntdHeader)` - box-shadow: ${themed('header.shadow')}; - background: ${themed('header.background')} !important; - ul { - background: none; - } - .ant-menu-horizontal { - border-bottom: none; - } -` - -export const Menu = styled(AntdMenu)` - margin-right: auto; -` \ No newline at end of file diff --git a/website/src/header/Header.tsx b/website/src/header/Header.tsx deleted file mode 100644 index 2e41dfb..0000000 --- a/website/src/header/Header.tsx +++ /dev/null @@ -1,37 +0,0 @@ -import {Button, Space} from "antd"; -import {Logo} from "./Logo"; -import * as icons from "@ant-design/icons"; -import React from "react"; -import * as Styled from './Header.style' -import {useTranslation} from "react-i18next"; -import ToggleButton from '../theme/ToggleButton' -import {GithubOutlined} from '@ant-design/icons' - -export interface HeaderProperties { - onShare?: () => void -} - -export default function Header(properties: HeaderProperties) { - const {t} = useTranslation() - return ( - - - - - - - +
+
+ ) +} \ No newline at end of file diff --git a/website/src/layout/Page.module.css b/website/src/layout/Page.module.css new file mode 100644 index 0000000..e69de29 diff --git a/website/src/layout/Page.tsx b/website/src/layout/Page.tsx new file mode 100644 index 0000000..434622f --- /dev/null +++ b/website/src/layout/Page.tsx @@ -0,0 +1,20 @@ +import React from 'react' +import Header from './Header' +import Footer from './Footer' + +import styles from './Page.module.css' + +export interface PageProps { + children?: React.ReactNode + onShare?: () => void +} + +export default function Page(props: PageProps) { + return ( +
+
+
{props.children}
+
+
+ ) +} \ No newline at end of file diff --git a/website/src/sheet/ImportedSheet.tsx b/website/src/sheet/ImportedSheet.tsx index 5812151..0216d2f 100644 --- a/website/src/sheet/ImportedSheet.tsx +++ b/website/src/sheet/ImportedSheet.tsx @@ -7,7 +7,6 @@ import Client from '../client' import styled from 'styled-components' import {LoadingOutlined} from '@ant-design/icons' import {Empty} from 'antd' -import themed from '../theme/themed' interface ImportedSheetProperties { evaluating?: boolean @@ -52,7 +51,6 @@ const Centered = styled.div` const ErrorBox = styled.div` margin: 50px auto auto auto; - background: ${themed('snippet.card.background')}; border-radius: 5px; padding: 20px; max-width: 300px; @@ -61,7 +59,6 @@ const ErrorBox = styled.div` width: 100%; } code { - background: ${themed('snippet.card.icon.background')}; width: 100%; padding: 10px; } diff --git a/website/src/sheet/ShareModal.tsx b/website/src/sheet/ShareModal.tsx index f8a7747..8de8cb0 100644 --- a/website/src/sheet/ShareModal.tsx +++ b/website/src/sheet/ShareModal.tsx @@ -1,7 +1,6 @@ import {Button} from 'antd' import {CheckOutlined, CopyOutlined, ShareAltOutlined} from '@ant-design/icons' import * as Styled from './ShareModal.style' -import * as StyledTitle from './snippet/Title.style' import useTimedFlag from '../util/useTimedFlag' import copy from 'copy-to-clipboard' @@ -18,7 +17,7 @@ function createLink(sheetId: string) { export default function ShareModal(properties: ShareModalProperties) { const [clicked, setClicked] = useTimedFlag(false, 1000) - const link =createLink(properties.sheetId || 'none') + const link = createLink(properties.sheetId || 'none') const onClick = () => { setClicked(true) @@ -27,12 +26,7 @@ export default function ShareModal(properties: ShareModalProperties) { return ( - - Share - - } + title="Share" visible={properties.visible} onCancel={() => properties.onVisibilityChange?.(false)} onOk={() => properties.onVisibilityChange?.(false)} diff --git a/website/src/sheet/Sheet.tsx b/website/src/sheet/Sheet.tsx index a45ae33..5dede96 100644 --- a/website/src/sheet/Sheet.tsx +++ b/website/src/sheet/Sheet.tsx @@ -13,10 +13,11 @@ import {useDispatch} from 'react-redux' import {StartEvaluationRequest} from "@jsheets/protocol/src/jsheets/api/snippet_runtime_pb"; import {reorderSnippet} from './state' import {listSnippetsInState, SheetState, SnippetState} from './index' -import Snippet, {SnippetReference} from './snippet/Snippet' +import SnippetContext from './snippet/Snippet' import {useDraggableIds} from './snippet/draggableId' +import {SnippetReference} from './snippet/SnippetX' -const MemoizedSnippet = React.memo(Snippet) +const MemoizedSnippet = React.memo(SnippetContext) function useReorder(): (result: DropResult) => void { const dispatch = useDispatch() diff --git a/website/src/sheet/evaluation.ts b/website/src/sheet/evaluation.ts new file mode 100644 index 0000000..523d6ea --- /dev/null +++ b/website/src/sheet/evaluation.ts @@ -0,0 +1,8 @@ +import {atom, useAtom} from 'jotai' + +const isEvaluatingAtom = atom(false) + +export function useIsEvaluating(): boolean { + const [state] = useAtom(isEvaluatingAtom) + return state +} \ No newline at end of file diff --git a/website/src/sheet/snippet/Snippet.module.css b/website/src/sheet/snippet/Snippet.module.css new file mode 100644 index 0000000..e94cd58 --- /dev/null +++ b/website/src/sheet/snippet/Snippet.module.css @@ -0,0 +1,56 @@ +.snippet { + overflow: hidden; + border-radius: 0.5em; +} + +.snippet-header { + display: flex; + align-items: center; + justify-content: space-between; + background-color: var(--snippet-header-bg); + border-bottom: 0.2em solid var(--card-border-color); +} + +.snippet-header-title { + font-size: 1.2em; + font-weight: 500; + user-select: inherit; +} + +.snippet-header-actions { + display: flex; + justify-content: flex-end; + align-items: center; + gap: 0.5em; +} + +.edit-button, .run-button { + font-size: 0.9em; + display: flex; + justify-content: center; + align-items: center; + gap: 0.5em; + padding: 0.5em 1em; + border-radius: 0.2em; + transition: .2s ease-in background-color; +} + +.run-button { + color: var(--primary-fg); + background: var(--primary-bg); +} + +.run-button:hover { + background: var(--primary-hover-bg); +} + +.edit-button { + color: var(--secondary-fg); + background: var(--secondary-bg); +} + +.edit-button:hover { + background: var(--secondary-hover-bg); +} + +.snippet-body { } \ No newline at end of file diff --git a/website/src/sheet/snippet/Snippet.style.ts b/website/src/sheet/snippet/Snippet.style.ts deleted file mode 100644 index 9b72f53..0000000 --- a/website/src/sheet/snippet/Snippet.style.ts +++ /dev/null @@ -1,27 +0,0 @@ -import styled from 'styled-components' -import themed from '../../theme/themed' - -export const Card = styled.div` - max-width: 1000px; - margin: 50px auto 0 auto; - overflow: hidden; - box-shadow: ${themed('snippet.card.shadow')}; - border: none; - border-radius: 3px; - background: ${themed('background')}; - &:first-child { - margin-top: 0; - } -` - -export const CardHead = styled.div` - padding: 0 15px; - height: 70px; - box-shadow: ${themed('snippet.card.head.shadow')} !important; - display: flex; -` - -export const CardBody = styled.div` - padding: 0; - overflow: hidden; -` \ No newline at end of file diff --git a/website/src/sheet/snippet/Snippet.tsx b/website/src/sheet/snippet/Snippet.tsx index 0608a5b..49788f9 100644 --- a/website/src/sheet/snippet/Snippet.tsx +++ b/website/src/sheet/snippet/Snippet.tsx @@ -1,192 +1,40 @@ -import * as Styled from './Snippet.style' -import {ExperimentOutlined} from '@ant-design/icons' import React from 'react' -import Title from './Title' -import {UseSnippet, useSnippet} from '../useSheet' -import {SnippetState} from '../index' -import ComponentList from "./component/ComponentList"; -import SnippetExtras from "./SnippetExtras"; -import { - SnippetComponentListRef, - SnippetComponentReference -} from './component/reference' -import * as SnippetProtocol from "@jsheets/protocol/src/jsheets/api/snippet_pb"; -import {StartEvaluationRequest} from "@jsheets/protocol/src/jsheets/api/snippet_runtime_pb"; -import createEvaluateRequest from './createEvaluateREquest' - -export interface SnippetPosition { - highestOrder: number - lowestOrder: number - moveUp: () => void - moveDown: () => void -} - -interface ExistingSnippetProperties extends UseSnippet { - sheetId: string - snippet: SnippetState - position: SnippetPosition - headProperties?: any - isCooldown?: boolean - running?: boolean - evaluate: (request: StartEvaluationRequest) => void - capture?: (reference: SnippetReference) => void -} - -const MemoizedTitle = React.memo(Title) -const MemoizedExtras = React.memo(SnippetExtras) - -interface ExistingSnippetState { - editingTitle: boolean -} - -export interface SnippetReference { - listSources(): Map - serialize(): SnippetProtocol.Snippet -} - -class ExistingSnippet - extends React.Component - implements SnippetReference { - - private readonly componentsReferences: React.MutableRefObject - = React.createRef() - - constructor(props: ExistingSnippetProperties) { - super(props) - this.componentsReferences.current = {components: new Map()} - this.state = {editingTitle: props.snippet.title === ''} - } - - changeEditingTitle = (target: boolean) => { - if (!target && this.props.snippet.title === '') { - this.props.changeDetails({title: 'None'}) - } - this.setState({editingTitle: target}) - } - - componentDidMount() { - this.props.capture?.(this) - } - - render() { - return ( - - - } - onChange={title => this.props.changeDetails({title})} - onEditingChange={this.changeEditingTitle} - text={this.props.snippet.title} - /> - - - - - - - ) - } - - private registerComponent = (id: string, reference: SnippetComponentReference) => { - this.componentsReferences.current?.components.set(id, reference) - } - - run = () => { - const start = createEvaluateRequest( - this.props.sheetId, - this.props.snippet, - this.listSources('code') - ) - this.props.evaluate(start) - } - - serialize = () => { - const message = new SnippetProtocol.Snippet() - message.setId(this.props.snippet.id) - message.setName(this.props.snippet.title) - message.setOrder(this.props.snippet.order) - message.setComponentsList(this.serializeComponents()) - return message - } - - serializeComponents = () => { - const references = this.componentsReferences.current?.components - const output: SnippetProtocol.Snippet.Component[] = [] - if (!references) { - return output - } - for (const component of Object.values(this.props.snippet.components)) { - const reference = references.get(component.id) - const serialized = reference?.serialize() - if (serialized) { - serialized.setOrder(component.order) - output.push(serialized) - } - } - return output - } - - listSources = (type?: 'text' | 'code'): Map => { - const componentRefTable = this.componentsReferences.current?.components - if (!componentRefTable) { - return new Map() - } - const sources = new Map() - for (const component of Object.values(this.props.snippet.components)) { - if (component.type !== type) { - continue - } - const ref = componentRefTable.get(component.id) - const source = ref?.content() - if (source) { - sources.set(component.id, source) - } - } - return sources - } -} - -export interface SnippetProperties { - id: string - sheetId: string - position: SnippetPosition - dragHandleProps?: any - running?: boolean - isCooldown?: boolean - evaluate: (request: StartEvaluationRequest) => void - capture?: (reference: SnippetReference) => void -} - -export default function Snippet(properties: SnippetProperties) { - const snippetContext = useSnippet(properties.id) - if (!snippetContext.snippet) { - return <> - } +import SnippetContext from './SnippetContext' +import styles from './Snippet.module.css' +import ComponentList from './component/ComponentList' +import TerminalLineIcon from 'remixicon-react/TerminalLineIcon' +import AddLineIcon from 'remixicon-react/AddLineIcon' +import CloseLineIcon from 'remixicon-react/CloseLineIcon' + +export default function Snippet() { + const {snippet} = React.useContext(SnippetContext) return ( - +
+
+
+ {snippet.title} +
+
+ + + + +
+
+
+ +
+
) } \ No newline at end of file diff --git a/website/src/sheet/snippet/SnippetContext.tsx b/website/src/sheet/snippet/SnippetContext.tsx new file mode 100644 index 0000000..d1d2e79 --- /dev/null +++ b/website/src/sheet/snippet/SnippetContext.tsx @@ -0,0 +1,13 @@ +import {ComponentState, SnippetState} from '../index' +import React from 'react' + +export interface SnippetContextProps { + snippet: SnippetState + addComponent?: (component: Partial) => void + removeComponent?: (id: string) => void + setEditingTitle?: (state: boolean) => void + changeTitle?: (target: string) => void +} + +export default React.createContext( + {snippet: {id: '', title: '', components: {}, order: 0}}) \ No newline at end of file diff --git a/website/src/sheet/snippet/SnippetExtras.style.ts b/website/src/sheet/snippet/SnippetExtras.style.ts deleted file mode 100644 index aafb98e..0000000 --- a/website/src/sheet/snippet/SnippetExtras.style.ts +++ /dev/null @@ -1,9 +0,0 @@ -import styled from "styled-components"; -import {Space} from "antd"; - -export const SnippetExtras = styled(Space)` - margin: auto 0 auto auto; - & > .ant-button { - cursor: pointer !important; - } -` diff --git a/website/src/sheet/snippet/SnippetExtras.tsx b/website/src/sheet/snippet/SnippetExtras.tsx deleted file mode 100644 index 217e2c2..0000000 --- a/website/src/sheet/snippet/SnippetExtras.tsx +++ /dev/null @@ -1,89 +0,0 @@ -import {Button, Dropdown, Menu} from "antd"; -import { - ClockCircleOutlined, - CodeOutlined, - CommentOutlined, DeleteOutlined, EditOutlined, - FireOutlined, MoreOutlined, - PlusOutlined -} from "@ant-design/icons"; -import * as Styled from "./SnippetExtras.style"; -import React from "react"; -import {ComponentState} from "../index"; -import {TFunction} from 'i18next' -import {useTranslation} from 'react-i18next' - -type AddComponent = (component: Partial) => void - -export interface SnippetExtrasProperties { - editingTitle: boolean - setEditingTitle: (state: boolean) => void - delete: () => void - addComponent: AddComponent - onRun: () => void - running?: boolean - isCooldown?: boolean -} - -const AddMenu: React.FC<{addComponent: AddComponent, t: TFunction}> = ({addComponent, t}) => ( - - } - onClick={() => addComponent({type: 'code'})} - >{t('snippet.menu.add.code')} - } - onClick={() => addComponent({type: 'text'})} - >{t('snippet.menu.add.comment')} - - }> - - -) - -const EditMenu: React.FC = properties => ( - - } - onClick={() => properties.setEditingTitle(!properties.editingTitle)} - >{properties.t('snippet.menu.edit.rename')} - } - onClick={properties.delete} - >{properties.t('snippet.menu.edit.delete')} - - }> - - - - ) -} \ No newline at end of file diff --git a/website/src/sheet/snippet/SnippetX.tsx b/website/src/sheet/snippet/SnippetX.tsx new file mode 100644 index 0000000..e6275c1 --- /dev/null +++ b/website/src/sheet/snippet/SnippetX.tsx @@ -0,0 +1,188 @@ +import {ExperimentOutlined} from '@ant-design/icons' +import React from 'react' +import {UseSnippet, useSnippet} from '../useSheet' +import {SnippetState} from '../index' +import ComponentList from './component/ComponentList' +import { + SnippetComponentListRef, + SnippetComponentReference +} from './component/reference' +import * as SnippetProtocol from '@jsheets/protocol/src/jsheets/api/snippet_pb' +import { + StartEvaluationRequest +} from '@jsheets/protocol/src/jsheets/api/snippet_runtime_pb' +import createEvaluationRequest from './createEvaluationRequest' +import styles from './Snippet.module.css' +import SnippetContext from './SnippetContext' + +export interface SnippetPosition { + highestOrder: number + lowestOrder: number + moveUp: () => void + moveDown: () => void +} + +interface ExistingSnippetProperties extends UseSnippet { + sheetId: string + snippet: SnippetState + position: SnippetPosition + headProperties?: any + isCooldown?: boolean + running?: boolean + evaluate: (request: StartEvaluationRequest) => void + capture?: (reference: SnippetReference) => void +} + +interface ExistingSnippetState { + editingTitle: boolean +} + +export interface SnippetReference { + listSources(): Map + + serialize(): SnippetProtocol.Snippet +} + +class ExistingSnippet + extends React.Component + implements SnippetReference { + + private readonly componentsReferences: React.MutableRefObject + = React.createRef() + + constructor(props: ExistingSnippetProperties) { + super(props) + this.componentsReferences.current = {components: new Map()} + this.state = {editingTitle: props.snippet.title === ''} + } + + changeEditingTitle = (target: boolean) => { + if (!target && this.props.snippet.title === '') { + this.props.changeDetails({title: 'None'}) + } + this.setState({editingTitle: target}) + } + + componentDidMount() { + this.props.capture?.(this) + } + + render() { + const {snippet} = React.useContext(SnippetContext) + return ( +
+
+
{snippet.title}
+
+ +
+
+
+ +
+
+ ) + } + + private registerComponent = (id: string, reference: SnippetComponentReference) => { + this.componentsReferences.current?.components.set(id, reference) + } + + run = () => { + const start = createEvaluationRequest( + this.props.sheetId, + this.props.snippet, + this.listSources('code') + ) + this.props.evaluate(start) + } + + serialize = () => { + const message = new SnippetProtocol.Snippet() + message.setId(this.props.snippet.id) + message.setName(this.props.snippet.title) + message.setOrder(this.props.snippet.order) + message.setComponentsList(this.serializeComponents()) + return message + } + + serializeComponents = () => { + const references = this.componentsReferences.current?.components + const output: SnippetProtocol.Snippet.Component[] = [] + if (!references) { + return output + } + for (const component of Object.values(this.props.snippet.components)) { + const reference = references.get(component.id) + const serialized = reference?.serialize() + if (serialized) { + serialized.setOrder(component.order) + output.push(serialized) + } + } + return output + } + + listSources = (type?: 'text' | 'code'): Map => { + const componentRefTable = this.componentsReferences.current?.components + if (!componentRefTable) { + return new Map() + } + const sources = new Map() + for (const component of Object.values(this.props.snippet.components)) { + if (component.type !== type) { + continue + } + const ref = componentRefTable.get(component.id) + const source = ref?.content() + if (source) { + sources.set(component.id, source) + } + } + return sources + } +} + +export interface SnippetProperties { + id: string + sheetId: string + position: SnippetPosition + dragHandleProps?: any + running?: boolean + isCooldown?: boolean + evaluate: (request: StartEvaluationRequest) => void + capture?: (reference: SnippetReference) => void +} + +export default function SnippetX(properties: SnippetProperties) { + const snippetContext = useSnippet(properties.id) + if (!snippetContext.snippet) { + return <> + } + return ( + + ) +} \ No newline at end of file diff --git a/website/src/sheet/snippet/Title.style.tsx b/website/src/sheet/snippet/Title.style.tsx deleted file mode 100644 index 4b8c891..0000000 --- a/website/src/sheet/snippet/Title.style.tsx +++ /dev/null @@ -1,43 +0,0 @@ -import styled from 'styled-components' -import {Input as AntdInput} from 'antd' -import themed from '../../theme/themed' - -export const Title = styled.span` - display: flex; - font-size: 18px; - cursor: default !important; - & > * { - margin: auto 0 auto 0; - } -` - -export const IconBox = styled.span` - padding: 8px; - display: flex; - border-radius: 5px; - margin: auto 5px auto 0; - background: ${themed('snippet.card.icon.background')}; - .anticon { - color: ${themed('base.primary')}; - margin: auto 0; - } -` - -export const Input = styled(AntdInput)` - margin: auto 10px auto 5px !important; - max-width: 300px; - height: 34px !important; - padding: 2px !important; - font-size: 18px !important; - border: none !important; - outline: none !important; - &:focus { - outline: none !important; - } -` - -export const Text = styled.span` - margin: auto 0 auto 7px; - cursor: text; - user-select: text !important; -` \ No newline at end of file diff --git a/website/src/sheet/snippet/Title.tsx b/website/src/sheet/snippet/Title.tsx deleted file mode 100644 index 5171be1..0000000 --- a/website/src/sheet/snippet/Title.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import React, {useEffect} from 'react' -import * as Styled from './Title.style' -import {Input} from 'antd' - -interface TitleProperties { - icon: React.ReactNode - text: string - editing: boolean - onEditingChange?: (target: boolean) => void - onChange?: (text: string) => void -} - -export default function Title(properties: TitleProperties) { - const ref = React.createRef() - useEffect(() => { - if (properties.editing) { - ref.current?.focus() - } - }, [ref, properties.editing]) - return ( - - {properties.icon} - {properties.editing - ? properties.onEditingChange?.(false)} - onChange={event => properties.onChange?.(event.target.value)} - /> - : properties.onEditingChange?.(true)}>{properties.text} - } - - - ) -} diff --git a/website/src/sheet/snippet/component/ComponentContainer.style.ts b/website/src/sheet/snippet/component/ComponentContainer.style.ts index ef5587a..5b8f96e 100644 --- a/website/src/sheet/snippet/component/ComponentContainer.style.ts +++ b/website/src/sheet/snippet/component/ComponentContainer.style.ts @@ -1,6 +1,5 @@ -import styled from "styled-components"; -import {Button} from "antd"; -import themed from '../../../theme/themed' +import styled from 'styled-components' +import {Button} from 'antd' export const ComponentOptions = styled.div` z-index: 20; @@ -11,6 +10,7 @@ export const ComponentOptions = styled.div` transition: all .1s ease-in-out; right: -10px; opacity: 0; + & > :not(:first-child) { margin-left: 5px; } @@ -23,10 +23,10 @@ export const ComponentInputArea = styled.div` export const Component = styled.div` min-height: 45px; // To include the options transition: opacity .1s ease-in, box-shadow .1s ease-in; - background: ${themed('snippet.component.background')}; + background: var(--snippet-code-bg); &:not(:first-child) { - border-top: ${themed('snippet.component.borderTop')}; + border-top: var(--card-border-color); } &.dragging-component { @@ -48,6 +48,7 @@ export const DragHandle = styled.div` border-radius: 2px; font-size: 15px; transition: background-color .2s ease-in; + &:hover { background: rgba(250, 250, 250, 0.5); } diff --git a/website/src/sheet/snippet/component/ComponentList.tsx b/website/src/sheet/snippet/component/ComponentList.tsx index f42fb09..77b78f3 100644 --- a/website/src/sheet/snippet/component/ComponentList.tsx +++ b/website/src/sheet/snippet/component/ComponentList.tsx @@ -47,7 +47,7 @@ function useComponents( ) } -export default function ComponentList(properties: ComponentListProperties) { +export default function ComponentList() { const reorder = useReorder(properties.snippetId) const components = useComponents(properties.components, properties.capture) const draggableId = useDraggableId(properties.snippetId) diff --git a/website/src/sheet/snippet/component/TextComponent.style.ts b/website/src/sheet/snippet/component/TextComponent.style.ts index 0eb7c67..82fa5b0 100644 --- a/website/src/sheet/snippet/component/TextComponent.style.ts +++ b/website/src/sheet/snippet/component/TextComponent.style.ts @@ -1,6 +1,5 @@ import styled, {createGlobalStyle} from 'styled-components' import RichMarkdownEditor from 'rich-markdown-editor' -import themed from '../../../theme/themed' export const TextComponent = styled.div` padding: 0; @@ -19,9 +18,9 @@ export const Editor = styled(RichMarkdownEditor)` :first-child { padding: 10px !important; } - background: ${themed('snippet.textComponent.background')} !important; + background: var(--snippet-doc-bg) !important; * > div { - background: ${themed('snippet.textComponent.background')} !important; + background: var(--snippet-doc-bg) !important; } & > :first-child h1 { margin: 0 0 0.25em; diff --git a/website/src/sheet/snippet/component/TextComponent.tsx b/website/src/sheet/snippet/component/TextComponent.tsx index 4141369..acd284a 100644 --- a/website/src/sheet/snippet/component/TextComponent.tsx +++ b/website/src/sheet/snippet/component/TextComponent.tsx @@ -3,9 +3,7 @@ import React from 'react' import {EditorComponentProperties} from './EditorComponent' import {SnippetComponentReference} from './reference' import RichMarkdownEditor from 'rich-markdown-editor' -import {ThemeContext} from '../../../theme/ThemeContext' import * as SnippetProtocol from '@jsheets/protocol/src/jsheets/api/snippet_pb' -import * as jspb from "google-protobuf"; export interface TextComponentProperties { value: string @@ -21,8 +19,6 @@ export default class TextComponent extends React.Component implements SnippetComponentReference { - static contextType = ThemeContext - private readonly editorRef = React.createRef() render() { diff --git a/website/src/sheet/snippet/createEvaluateREquest.ts b/website/src/sheet/snippet/createEvaluationRequest.ts similarity index 96% rename from website/src/sheet/snippet/createEvaluateREquest.ts rename to website/src/sheet/snippet/createEvaluationRequest.ts index ce95371..bc37c72 100644 --- a/website/src/sheet/snippet/createEvaluateREquest.ts +++ b/website/src/sheet/snippet/createEvaluationRequest.ts @@ -2,7 +2,7 @@ import {findComponentByIdInState, SnippetState} from '../index' import * as EvaluationProtocol from '@jsheets/protocol/src/jsheets/api/snippet_runtime_pb' import * as SnippetProtocol from '@jsheets/protocol/src/jsheets/api/snippet_pb' -export default function createEvaluateRequest( +export default function createEvaluationRequest( sheetId: string, snippet: SnippetState, componentSources: Map diff --git a/website/src/theme/ThemeContext.tsx b/website/src/theme/ThemeContext.tsx deleted file mode 100644 index 2562487..0000000 --- a/website/src/theme/ThemeContext.tsx +++ /dev/null @@ -1,122 +0,0 @@ -import React, {useEffect, useState} from 'react' -import {insertPrefetches, updateTheme} from './updateTheme' -import {light as lightTheme, dark as darkTheme} from './theme' -import { - DefaultTheme, - ThemeProvider as StyledThemeProvider -} from 'styled-components' - -export type ThemeKey = 'light' | 'dark' - -type UpdateTheme = React.Dispatch> - -export interface ThemeContextProperties { - theme: ThemeKey - update: UpdateTheme -} - -export const ThemeContext = React.createContext( - { - theme: 'light', - update: () => 'light' - } -) - -export function useTheme(): [ThemeKey, UpdateTheme] { - const {theme, update} = React.useContext(ThemeContext) - return [theme, update] -} - -type ToggleTheme = () => void - -export function useThemeToggle(): ToggleTheme { - const [, update] = useTheme() - return () => update((current: ThemeKey) => toggle(current)) -} - -function toggle(current: ThemeKey): ThemeKey { - return current === 'light' ? 'dark' : 'light' -} - -export interface ThemeProviderProperties { - initialTheme?: ThemeKey - children: React.ReactNode -} - -export type ThemeTable = Record - -const themeSources: ThemeTable = { - light: '/theme/light.css', - dark: '/theme/dark.css' -} - -const themeVariables: ThemeTable = { - light: lightTheme, - dark: darkTheme -} - -const themeStorageKey = 'jsheets.theme' - -export function detectTheme(): ThemeKey { - try { - const stored = localStorage.getItem(themeStorageKey) - if (stored) { - return stored === 'dark' ? 'dark' : 'light' - } - } catch (error) { - console.error({message: 'failed to detect theme', error}) - } - return selectUserPreference() -} - -function storeTheme(theme: ThemeKey) { - try { - localStorage.setItem(themeStorageKey, theme) - } catch (error) { - console.error({message: 'failed to store theme', error}) - } -} - -function selectUserPreference(): ThemeKey { - const prefersDark = window.matchMedia && - window.matchMedia('(prefers-color-scheme: dark)').matches - return prefersDark ? 'dark' : 'light' -} - -export async function installThemes(): Promise { - return new Promise(resolve => { - const initial = detectTheme() - insertPrefetches(themeSources) - updateTheme(initial, themeSources[initial], () => resolve(initial)) - }) -} - -function useUpdate(call: () => void, dependencies: any[]) { - const firstRender = React.useRef(true) - useEffect(() => { - if (firstRender.current) { - firstRender.current = false - } else { - call() - } - }, [...dependencies, firstRender]) -} - -export default function ThemeProvider(properties: ThemeProviderProperties) { - const [theme, update] = useState(properties.initialTheme || 'light') - const variables = themeVariables[theme] - - useUpdate(() => { - const link = themeSources[theme] - updateTheme(theme, link) - storeTheme(theme) - }, [theme]) - - return ( - - - {properties.children} - - - ) -} \ No newline at end of file diff --git a/website/src/theme/ToggleButton.tsx b/website/src/theme/ToggleButton.tsx deleted file mode 100644 index 30c65dc..0000000 --- a/website/src/theme/ToggleButton.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import {Button} from 'antd' -import {BulbFilled, BulbOutlined} from '@ant-design/icons' -import {useTheme, useThemeToggle} from './ThemeContext' - -export default function ToggleButton() { - const [theme] = useTheme() - const toggle = useThemeToggle() - return ( -