From f590d7757830171de240c028f126f8dc341c3aea Mon Sep 17 00:00:00 2001 From: ngc2207 Date: Sun, 15 Dec 2024 21:15:19 +0800 Subject: [PATCH] feat(playground): add theme selector component and enhance code editor with additional themes and languages --- src/app/playground/components/code-editor.tsx | 99 +++++++++++++------ .../playground/components/theme-selector.tsx | 47 +++++++++ src/app/playground/layout.tsx | 17 +--- 3 files changed, 116 insertions(+), 47 deletions(-) create mode 100644 src/app/playground/components/theme-selector.tsx diff --git a/src/app/playground/components/code-editor.tsx b/src/app/playground/components/code-editor.tsx index 7829d4a..fb17544 100644 --- a/src/app/playground/components/code-editor.tsx +++ b/src/app/playground/components/code-editor.tsx @@ -1,52 +1,87 @@ "use client"; -import { useRef } from "react"; import "@fontsource-variable/fira-code"; import { createHighlighter } from "shiki"; import type { editor } from "monaco-editor"; import { shikiToMonaco } from "@shikijs/monaco"; +import { useEffect, useRef, useMemo } from "react"; import { useCodeEditorStore } from "@/store/codeEditorStore"; import MonacoEditor, { type Monaco } from "@monaco-editor/react"; +const ADDITIONAL_THEMES = [ + "andromeeda", + "aurora-x", + "ayu-dark", + "catppuccin-frappe", + "catppuccin-latte", + "catppuccin-macchiato", + "catppuccin-mocha", + "dark-plus", + "dracula", + "dracula-soft", + "one-dark-pro", + "vitesse-dark", + "vitesse-light", +]; + +const ADDITIONAL_LANGUAGES = ["c", "java"] as const satisfies Parameters< + typeof createHighlighter +>[0]["langs"]; + export function CodeEditor() { const monacoRef = useRef(null); const editorRef = useRef(null); const { lang, theme, value, isLigature } = useCodeEditorStore(); + + useEffect(() => { + if (monacoRef.current && editorRef.current) { + monacoRef.current.editor.setTheme(theme); + } + }, [theme]); + + const options = useMemo( + () => ({ + minimap: { enabled: false }, + fontSize: 14, + fontFamily: "Fira Code Variable, monospace", + tabSize: 4, + showFoldingControls: "always" as const, + fontLigatures: isLigature, + automaticLayout: true, + guides: { + bracketPairs: true, + indentation: true, + }, + }), + [isLigature] + ); + + const handleEditorMount = async ( + editor: editor.IStandaloneCodeEditor, + monaco: Monaco + ) => { + editorRef.current = editor; + monacoRef.current = monaco; + + for (const lang of ADDITIONAL_LANGUAGES) { + monacoRef.current?.languages.register({ id: lang }); + } + + const highlighter = await createHighlighter({ + themes: ADDITIONAL_THEMES, + langs: ADDITIONAL_LANGUAGES, + }); + + shikiToMonaco(highlighter, monacoRef.current); + }; + return ( { - editorRef.current = editor; - monacoRef.current = monaco; - void (async () => { - const ADDITIONAL_LANGUAGES = [ - "c", - "java", - ] as const satisfies Parameters[0]["langs"]; - - for (const lang of ADDITIONAL_LANGUAGES) { - monacoRef.current?.languages.register({ id: lang }); - } - - const highlighter = await createHighlighter({ - themes: [theme], - langs: ADDITIONAL_LANGUAGES, - }); - - shikiToMonaco(highlighter, monacoRef.current); - })(); - }} + onMount={handleEditorMount} /> ); } diff --git a/src/app/playground/components/theme-selector.tsx b/src/app/playground/components/theme-selector.tsx new file mode 100644 index 0000000..65cd17d --- /dev/null +++ b/src/app/playground/components/theme-selector.tsx @@ -0,0 +1,47 @@ +"use client"; + +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/ui/select"; +import { useCodeEditorStore } from "@/store/codeEditorStore"; + +const themeOptions = [ + { value: "andromeeda", label: "Andromeeda" }, + { value: "aurora-x", label: "Aurora X" }, + { value: "ayu-dark", label: "Ayu Dark" }, + { value: "catppuccin-frappe", label: "Catppuccin Frappé" }, + { value: "catppuccin-latte", label: "Catppuccin Latte" }, + { value: "catppuccin-macchiato", label: "Catppuccin Macchiato" }, + { value: "catppuccin-mocha", label: "Catppuccin Mocha" }, + { value: "dark-plus", label: "Dark Plus" }, + { value: "dracula", label: "Dracula Theme" }, + { value: "dracula-soft", label: "Dracula Theme Soft" }, + { value: "one-dark-pro", label: "One Dark Pro" }, + { value: "vitesse-dark", label: "Vitesse Dark" }, + { value: "vitesse-light", label: "Vitesse Light" }, +]; + +export default function ThemeSelector() { + const { theme, setTheme } = useCodeEditorStore(); + + return ( +
+ +
+ ); +} diff --git a/src/app/playground/layout.tsx b/src/app/playground/layout.tsx index 0b2961f..6c7a470 100644 --- a/src/app/playground/layout.tsx +++ b/src/app/playground/layout.tsx @@ -3,14 +3,9 @@ import { SidebarProvider, SidebarTrigger, } from "@/components/ui/sidebar"; -import { - Breadcrumb, - BreadcrumbItem, - BreadcrumbList, - BreadcrumbPage, -} from "@/components/ui/breadcrumb"; import { SessionProvider } from "next-auth/react"; import { Separator } from "@/components/ui/separator"; +import ThemeSelector from "./components/theme-selector"; import { ModeSwitcher } from "@/components/mode-switcher"; import LanguageSwitcher from "@/components/language-switcher"; import { PlaygroundSidebar } from "@/app/playground/components/playground-sidebar"; @@ -28,15 +23,7 @@ export default function PlaygroundLayout({ - - - - - Project Management & Task Tracking - - - - +