diff --git a/web/bun.lockb b/web/bun.lockb index c6973a84..aa378ee8 100755 Binary files a/web/bun.lockb and b/web/bun.lockb differ diff --git a/web/package.json b/web/package.json index 0e91cd98..067a12ef 100644 --- a/web/package.json +++ b/web/package.json @@ -22,7 +22,7 @@ "@types/react-syntax-highlighter": "^15.5.13", "@vitejs/plugin-react": "^4.6.0", "rimraf": "^6.0.1", - "tailwindcss": "^4.1.10", + "tailwindcss": "^4.1.11", "typescript": "^5.8.3", "vite": "^7.0.0", "vite-bundle-visualizer": "^1.2.1" @@ -31,7 +31,7 @@ "@hookform/resolvers": "^5.1.1", "@radix-ui/react-navigation-menu": "^1.2.13", "@radix-ui/react-popover": "^1.1.14", - "@tailwindcss/vite": "^4.1.10", + "@tailwindcss/vite": "^4.1.11", "@tanstack/react-query": "^5.81.2", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", diff --git a/web/src/components/code-viewer.tsx b/web/src/components/code-viewer.tsx index 19550f1f..270c036a 100644 --- a/web/src/components/code-viewer.tsx +++ b/web/src/components/code-viewer.tsx @@ -3,12 +3,14 @@ import { Check, Copy } from "lucide-react"; import { type HTMLProps, type ReactNode, useCallback, useEffect, useState } from "react"; import { CopyToClipboard } from "react-copy-to-clipboard"; import { useTranslation } from "react-i18next"; -import { Prism as SyntaxHighlighter } from "react-syntax-highlighter"; +import { PrismLight as SyntaxHighlighter } from "react-syntax-highlighter"; +import java from "react-syntax-highlighter/dist/esm/languages/prism/java"; import { materialDark } from "react-syntax-highlighter/dist/esm/styles/prism"; import { toast } from "sonner"; import { Button, buttonVariants } from "@/components/ui/button"; import { cn } from "@/lib/utils"; +SyntaxHighlighter.registerLanguage("java", java); interface CopyButtonProps extends React.ComponentProps<"button"> { value: string; src?: string; @@ -49,7 +51,7 @@ export function CopyButton({ value }: Readonly = { [ShellToolType.Custom]: , }; -export function MainConfigCard({ +export default function MainConfigCard({ mainConfig, form, servers, diff --git a/web/src/components/package-config-card.tsx b/web/src/components/package-config-card.tsx index a207bdf6..23a10eb6 100644 --- a/web/src/components/package-config-card.tsx +++ b/web/src/components/package-config-card.tsx @@ -13,7 +13,7 @@ type Option = { value: string; }; -export function PackageConfigCard({ +export default function PackageConfigCard({ packerConfig, form, }: Readonly<{ diff --git a/web/src/components/results/multi-packer.tsx b/web/src/components/results/multi-packer.tsx index b9c20bd8..d02f15ab 100644 --- a/web/src/components/results/multi-packer.tsx +++ b/web/src/components/results/multi-packer.tsx @@ -1,8 +1,7 @@ import { TFunction } from "i18next"; import { useEffect, useState } from "react"; -import { CodeViewer } from "../code-viewer"; +import CodeViewer from "@/components/code-viewer"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "../ui/select"; - export function MultiPackResult({ allPackResults, packMethod, diff --git a/web/src/components/results/result-component.tsx b/web/src/components/results/result-component.tsx index 621fa96b..1919cbc3 100644 --- a/web/src/components/results/result-component.tsx +++ b/web/src/components/results/result-component.tsx @@ -1,6 +1,6 @@ import { TFunction } from "i18next"; +import CodeViewer from "@/components/code-viewer"; import { GenerateResult } from "@/types/shell"; -import { CodeViewer } from "../code-viewer"; import { AgentResult } from "./agent"; import { JarResult } from "./jar-result"; import { MultiPackResult } from "./multi-packer"; diff --git a/web/src/components/shell-result.tsx b/web/src/components/shell-result.tsx index 214a025c..129ce1e6 100644 --- a/web/src/components/shell-result.tsx +++ b/web/src/components/shell-result.tsx @@ -1,16 +1,17 @@ import { DownloadIcon } from "lucide-react"; import { useTranslation } from "react-i18next"; import { toast } from "sonner"; -import { CodeViewer } from "@/components/code-viewer.tsx"; + import { QuickUsage } from "@/components/quick-usage.tsx"; import { Button } from "@/components/ui/button.tsx"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs.tsx"; import { downloadBytes } from "@/lib/utils.ts"; import { GenerateResult } from "@/types/shell.ts"; +import CodeViewer from "./code-viewer"; import { BasicInfo } from "./results/basic-info"; import { ResultComponent } from "./results/result-component"; -export function ShellResult({ +export default function ShellResult({ packResult, allPackResults, packMethod, diff --git a/web/src/components/theme-provider.tsx b/web/src/components/theme-provider.tsx index 7f038361..6012cbb4 100644 --- a/web/src/components/theme-provider.tsx +++ b/web/src/components/theme-provider.tsx @@ -1,4 +1,4 @@ -import { createContext, useContext, useEffect, useState } from "react"; +import { createContext, useContext, useEffect, useMemo, useState } from "react"; type Theme = "dark" | "light" | "system"; @@ -25,7 +25,7 @@ export function ThemeProvider({ defaultTheme = "system", storageKey = "vite-ui-theme", ...props -}: ThemeProviderProps) { +}: Readonly) { const [theme, setTheme] = useState(() => (localStorage.getItem(storageKey) as Theme) || defaultTheme); useEffect(() => { @@ -45,13 +45,16 @@ export function ThemeProvider({ root.classList.add(theme); }, [theme]); - const value = { - theme, - setTheme: (theme: Theme) => { - localStorage.setItem(storageKey, theme); - setTheme(theme); - }, - }; + const value = useMemo( + () => ({ + theme, + setTheme: (theme: Theme) => { + localStorage.setItem(storageKey, theme); + setTheme(theme); + }, + }), + [theme, storageKey], + ); return ( diff --git a/web/src/pages/memshell.tsx b/web/src/pages/memshell.tsx index b1f1dfea..b53368c7 100644 --- a/web/src/pages/memshell.tsx +++ b/web/src/pages/memshell.tsx @@ -5,9 +5,9 @@ import { useForm } from "react-hook-form"; import { useTranslation } from "react-i18next"; import { useLoaderData } from "react-router-dom"; import { toast } from "sonner"; -import { MainConfigCard } from "@/components/main-config-card.tsx"; -import { PackageConfigCard } from "@/components/package-config-card.tsx"; -import { ShellResult } from "@/components/shell-result.tsx"; +import MainConfigCard from "@/components/main-config-card.tsx"; +import PackageConfigCard from "@/components/package-config-card.tsx"; +import ShellResult from "@/components/shell-result.tsx"; import { Button } from "@/components/ui/button"; import { Form } from "@/components/ui/form.tsx"; import { env } from "@/config.ts"; diff --git a/web/src/router.tsx b/web/src/router.tsx index 7fbd4dcf..bad22b02 100644 --- a/web/src/router.tsx +++ b/web/src/router.tsx @@ -1,4 +1,4 @@ -import { createBrowserRouter } from "react-router-dom"; +import { createHashRouter } from "react-router-dom"; import RootLayout from "@/components/layouts/root-layout"; import { env } from "@/config"; import MemShellPage from "@/pages/memshell"; @@ -42,7 +42,7 @@ const parseUrlParams = (searchParams: URLSearchParams): Partial => { return result; }; -export const router = createBrowserRouter( +export const router = createHashRouter( [ { path: "/", diff --git a/web/vite.config.ts b/web/vite.config.ts index 27578c79..f4ba1835 100644 --- a/web/vite.config.ts +++ b/web/vite.config.ts @@ -11,4 +11,19 @@ export default defineConfig({ "@": path.resolve(__dirname, "./src"), }, }, + build: { + rollupOptions: { + output: { + manualChunks: { + highlight: ["react-syntax-highlighter"], + radixUi: ["radix-ui"], + motion: ["framer-motion", "motion"], + sonner: ["sonner"], + yup: ["yup"], + i18n: ["react-i18next", "i18next"], + reactRouter: ["react-router", "react-router-dom"], + }, + }, + }, + }, });