diff --git a/app/components/Theme.tsx b/app/components/Theme.tsx index 282dda277..417ab7d4d 100644 --- a/app/components/Theme.tsx +++ b/app/components/Theme.tsx @@ -23,8 +23,12 @@ const Theme: React.FC = ({ children }) => { : resolvedTheme; React.useEffect(() => { - window.dispatchEvent(new Event("theme-changed")); - }, [theme]); + window.dispatchEvent( + new CustomEvent("theme-changed", { + detail: { isDark: ui.resolvedTheme === "dark" }, + }) + ); + }, [ui.resolvedTheme]); return ( diff --git a/app/editor/index.tsx b/app/editor/index.tsx index bf787c3bc..8e97809e4 100644 --- a/app/editor/index.tsx +++ b/app/editor/index.tsx @@ -210,6 +210,7 @@ export class Editor extends React.PureComponent< */ public componentDidMount() { this.init(); + window.addEventListener("theme-changed", this.dispatchThemeChanged); if (this.props.scrollTo) { this.scrollToAnchor(this.props.scrollTo); @@ -278,6 +279,10 @@ export class Editor extends React.PureComponent< } } + public componentWillUnmount(): void { + window.removeEventListener("theme-changed", this.dispatchThemeChanged); + } + private init() { this.extensions = this.createExtensions(); this.nodes = this.createNodes(); @@ -398,7 +403,9 @@ export class Editor extends React.PureComponent< plugins: [ ...this.plugins, ...this.keymaps, - dropCursor({ color: this.props.theme.cursor }), + dropCursor({ + color: this.props.theme.cursor, + }), gapCursor(), inputRules({ rules: this.inputRules, @@ -468,6 +475,10 @@ export class Editor extends React.PureComponent< return view; } + private dispatchThemeChanged = (event: CustomEvent) => { + this.view.dispatch(this.view.state.tr.setMeta("theme", event.detail)); + }; + public scrollToAnchor(hash: string) { if (!hash) { return; diff --git a/shared/editor/nodes/CodeFence.ts b/shared/editor/nodes/CodeFence.ts index 3ee081c7b..1f6fef0a3 100644 --- a/shared/editor/nodes/CodeFence.ts +++ b/shared/editor/nodes/CodeFence.ts @@ -338,7 +338,10 @@ export default class CodeFence extends Node { name: this.name, lineNumbers: this.showLineNumbers, }), - Mermaid({ name: this.name }), + Mermaid({ + name: this.name, + isDark: this.editor.props.theme.isDark, + }), new Plugin({ key: new PluginKey("triple-click"), props: { diff --git a/shared/editor/plugins/Mermaid.ts b/shared/editor/plugins/Mermaid.ts index 9ef5c005c..0eb434147 100644 --- a/shared/editor/plugins/Mermaid.ts +++ b/shared/editor/plugins/Mermaid.ts @@ -7,6 +7,7 @@ import { v4 as uuidv4 } from "uuid"; type MermaidState = { decorationSet: DecorationSet; diagramVisibility: Record; + isDark: boolean; }; function getNewState({ @@ -65,6 +66,7 @@ function getNewState({ flowchart: { htmlLabels: false, }, + theme: pluginState.isDark ? "dark" : "default", fontFamily: "inherit", }); try { @@ -114,10 +116,17 @@ function getNewState({ return { decorationSet: DecorationSet.create(doc, decorations), diagramVisibility: pluginState.diagramVisibility, + isDark: pluginState.isDark, }; } -export default function Mermaid({ name }: { name: string }) { +export default function Mermaid({ + name, + isDark, +}: { + name: string; + isDark: boolean; +}) { let diagramShown = false; return new Plugin({ @@ -127,6 +136,7 @@ export default function Mermaid({ name }: { name: string }) { const pluginState: MermaidState = { decorationSet: DecorationSet.create(doc, []), diagramVisibility: {}, + isDark, }; return pluginState; }, @@ -142,7 +152,13 @@ export default function Mermaid({ name }: { name: string }) { transaction.docChanged && [nodeName, previousNodeName].includes(name); const ySyncEdit = !!transaction.getMeta("y-sync$"); const mermaidMeta = transaction.getMeta("mermaid"); + const themeMeta = transaction.getMeta("theme"); const diagramToggled = mermaidMeta?.toggleDiagram !== undefined; + const themeToggled = themeMeta?.isDark !== undefined; + + if (themeToggled) { + pluginState.isDark = themeMeta.isDark; + } if (diagramToggled) { pluginState.diagramVisibility[ @@ -150,7 +166,13 @@ export default function Mermaid({ name }: { name: string }) { ] = !pluginState.diagramVisibility[mermaidMeta.toggleDiagram]; } - if (!diagramShown || codeBlockChanged || diagramToggled || ySyncEdit) { + if ( + !diagramShown || + themeToggled || + codeBlockChanged || + diagramToggled || + ySyncEdit + ) { diagramShown = true; return getNewState({ doc: transaction.doc, @@ -165,6 +187,7 @@ export default function Mermaid({ name }: { name: string }) { transaction.doc ), diagramVisibility: pluginState.diagramVisibility, + isDark: pluginState.isDark, }; }, }, @@ -178,6 +201,7 @@ export default function Mermaid({ name }: { name: string }) { view.dispatch(view.state.tr.setMeta("mermaid", { loaded: true })); }, 10); } + return {}; }, props: { diff --git a/shared/styles/theme.ts b/shared/styles/theme.ts index 0a739faa3..87de5f9c2 100644 --- a/shared/styles/theme.ts +++ b/shared/styles/theme.ts @@ -22,6 +22,7 @@ const colors = { black05: "rgba(0, 0, 0, 0.05)", black10: "rgba(0, 0, 0, 0.1)", black50: "rgba(0, 0, 0, 0.50)", + black75: "rgba(0, 0, 0, 0.75)", primary: "#0366d6", yellow: "#EDBA07", warmGrey: "#EDF2F7", @@ -204,7 +205,7 @@ export const dark = { toastText: colors.lightBlack, quote: colors.almostWhite, code: colors.almostWhite, - codeBackground: colors.black, + codeBackground: colors.black75, codeBorder: colors.black50, codeString: "#3d8fd1", embedBorder: colors.black50,