From c925954035f972cfe7256e1e8c17c76dcaccbb4d Mon Sep 17 00:00:00 2001 From: ReaJason Date: Thu, 26 Jun 2025 17:58:18 +0800 Subject: [PATCH] feat: add more page --- web/biome.json | 23 +- web/bun.lockb | Bin 158844 -> 164132 bytes web/copy-build.js | 2 +- web/package.json | 61 +- web/src/components/code-viewer.tsx | 4 +- web/src/components/copyable-field.tsx | 4 +- web/src/components/layouts/root-layout.tsx | 23 +- .../components/magicui/line-shadow-text.tsx | 40 + web/src/components/magicui/rainbow-button.tsx | 59 ++ web/src/components/main-config-card.tsx | 267 +++--- web/src/components/modile-nav.tsx | 97 +++ web/src/components/package-config-card.tsx | 8 +- web/src/components/quick-usage.tsx | 2 +- web/src/components/results/agent.tsx | 4 +- web/src/components/results/basic-info.tsx | 4 +- web/src/components/results/jar-result.tsx | 2 +- .../components/results/result-component.tsx | 2 +- web/src/components/shell-result.tsx | 6 +- web/src/components/tips/jre-tip.tsx | 2 +- web/src/components/tools/antsword-tab.tsx | 8 +- web/src/components/tools/behinder-tab.tsx | 2 +- web/src/components/tools/classname-field.tsx | 18 +- web/src/components/tools/command-tab.tsx | 4 +- web/src/components/tools/custom-tab.tsx | 17 +- web/src/components/tools/godzilla-tab.tsx | 2 +- web/src/components/tools/neoreg-tab.tsx | 2 +- web/src/components/tools/shelltype-field.tsx | 5 +- web/src/components/tools/suo5-tab.tsx | 2 +- web/src/components/tools/urlpattern-field.tsx | 4 +- web/src/components/ui/alert-dialog.tsx | 5 +- web/src/components/ui/alert.tsx | 2 +- web/src/components/ui/badge.tsx | 36 + web/src/components/ui/breadcrumb.tsx | 92 ++ web/src/components/ui/button.tsx | 6 +- web/src/components/ui/checkbox.tsx | 4 +- web/src/components/ui/context-menu.tsx | 209 +++++ web/src/components/ui/dialog.tsx | 121 +++ web/src/components/ui/dropdown-menu.tsx | 4 +- web/src/components/ui/form.tsx | 16 +- web/src/components/ui/input.tsx | 2 +- web/src/components/ui/label.tsx | 2 +- web/src/components/ui/navigation-menu.tsx | 142 ++++ web/src/components/ui/popover.tsx | 40 + web/src/components/ui/radio-group.tsx | 4 +- web/src/components/ui/scroll-area.tsx | 46 + web/src/components/ui/select.tsx | 4 +- web/src/components/ui/separator.tsx | 2 +- web/src/components/ui/switch.tsx | 2 +- web/src/components/ui/table.tsx | 73 ++ web/src/components/ui/tabs.tsx | 2 +- web/src/components/ui/tooltip.tsx | 2 +- web/src/components/version-badge.tsx | 2 +- web/src/index.css | 33 + web/src/lib/config.ts | 15 + web/src/main.tsx | 4 +- web/src/pages/detection.tsx | 802 ++++++++++++++++++ web/src/pages/landing.tsx | 296 +++++++ web/src/pages/{index.tsx => memshell.tsx} | 16 +- web/src/router.tsx | 16 +- web/src/types/schema.ts | 13 +- 60 files changed, 2403 insertions(+), 284 deletions(-) create mode 100644 web/src/components/magicui/line-shadow-text.tsx create mode 100644 web/src/components/magicui/rainbow-button.tsx create mode 100644 web/src/components/modile-nav.tsx create mode 100644 web/src/components/ui/badge.tsx create mode 100644 web/src/components/ui/breadcrumb.tsx create mode 100644 web/src/components/ui/context-menu.tsx create mode 100644 web/src/components/ui/dialog.tsx create mode 100644 web/src/components/ui/navigation-menu.tsx create mode 100644 web/src/components/ui/popover.tsx create mode 100644 web/src/components/ui/scroll-area.tsx create mode 100644 web/src/components/ui/table.tsx create mode 100644 web/src/lib/config.ts create mode 100644 web/src/pages/detection.tsx create mode 100644 web/src/pages/landing.tsx rename web/src/pages/{index.tsx => memshell.tsx} (99%) diff --git a/web/biome.json b/web/biome.json index cbff8337..525a77f2 100644 --- a/web/biome.json +++ b/web/biome.json @@ -1,5 +1,5 @@ { - "$schema": "https://biomejs.dev/schemas/1.9.4/schema.json", + "$schema": "https://biomejs.dev/schemas/2.0.5/schema.json", "vcs": { "enabled": true, "clientKind": "git", @@ -13,7 +13,17 @@ "noExplicitAny": "off" }, "style": { - "useImportType": "off" + "useImportType": "off", + "noParameterAssign": "error", + "useAsConstAssertion": "error", + "useDefaultParameterLast": "error", + "useEnumInitializers": "error", + "useSelfClosingElements": "error", + "useSingleVarDeclarator": "error", + "noUnusedTemplateLiteral": "error", + "useNumberNamespace": "error", + "noInferrableTypes": "error", + "noUselessElse": "error" }, "recommended": true, "a11y": { @@ -24,19 +34,16 @@ "noUnusedImports": "warn" } }, - "ignore": ["node_modules", "tsconfig*", "dist", "components/ui/**"] + "includes": ["**", "!**/node_modules", "!**/tsconfig*", "!**/dist", "!**/components/ui/**"] }, "formatter": { "indentStyle": "space", "indentWidth": 2, "enabled": true, "lineWidth": 120, - "ignore": ["node_modules", "tsconfig*", "dist"] - }, - "organizeImports": { - "enabled": true, - "ignore": ["node_modules", "dist", "components/ui/**"] + "includes": ["**", "!**/node_modules", "!**/tsconfig*", "!**/dist"] }, + "assist": { "actions": { "source": { "organizeImports": "on" } } }, "javascript": { "formatter": { "quoteStyle": "double" diff --git a/web/bun.lockb b/web/bun.lockb index c5072ad181beff0e17753c186d12dd759974b088..c6973a84eee38f14c9b6e5a0712510922e0ee6fc 100755 GIT binary patch delta 44328 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μ3#9u| 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 Dfo9(M delta 41699 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 diff --git a/web/copy-build.js b/web/copy-build.js index 27f3d3de..3be0c363 100644 --- a/web/copy-build.js +++ b/web/copy-build.js @@ -1,4 +1,4 @@ -import { existsSync, mkdirSync, readFileSync, readdirSync, rmSync, writeFileSync } from "node:fs"; +import { existsSync, mkdirSync, readdirSync, readFileSync, rmSync, writeFileSync } from "node:fs"; import { cp } from "node:fs/promises"; import { join, resolve } from "node:path"; diff --git a/web/package.json b/web/package.json index 2171b7b4..0e91cd98 100644 --- a/web/package.json +++ b/web/package.json @@ -14,67 +14,46 @@ "lint:fix": "bunx @biomejs/biome check ./ --write" }, "devDependencies": { - "@biomejs/biome": "1.9.4", - "@types/node": "^22.15.29", - "@types/react": "^19.1.6", + "@biomejs/biome": "2.0.5", + "@types/node": "^24.0.4", + "@types/react": "^19.1.8", "@types/react-copy-to-clipboard": "^5.0.7", "@types/react-dom": "^19.1.6", "@types/react-syntax-highlighter": "^15.5.13", - "@vitejs/plugin-react": "^4.5.1", + "@vitejs/plugin-react": "^4.6.0", "rimraf": "^6.0.1", - "tailwindcss": "^4.1.8", + "tailwindcss": "^4.1.10", "typescript": "^5.8.3", - "vite": "^6.3.5", + "vite": "^7.0.0", "vite-bundle-visualizer": "^1.2.1" }, "dependencies": { - "@hookform/resolvers": "^5.0.1", - "@radix-ui/react-accordion": "^1.2.11", - "@radix-ui/react-alert-dialog": "^1.1.14", - "@radix-ui/react-aspect-ratio": "^1.1.7", - "@radix-ui/react-avatar": "^1.1.10", - "@radix-ui/react-checkbox": "^1.3.2", - "@radix-ui/react-context-menu": "^2.2.15", - "@radix-ui/react-dialog": "^1.1.14", - "@radix-ui/react-dropdown-menu": "^2.1.15", - "@radix-ui/react-hover-card": "^1.1.14", - "@radix-ui/react-label": "^2.1.7", - "@radix-ui/react-menubar": "^1.1.15", + "@hookform/resolvers": "^5.1.1", "@radix-ui/react-navigation-menu": "^1.2.13", "@radix-ui/react-popover": "^1.1.14", - "@radix-ui/react-progress": "^1.1.7", - "@radix-ui/react-radio-group": "^1.3.7", - "@radix-ui/react-scroll-area": "^1.2.9", - "@radix-ui/react-select": "^2.2.5", - "@radix-ui/react-separator": "^1.1.7", - "@radix-ui/react-slot": "^1.2.3", - "@radix-ui/react-switch": "^1.2.5", - "@radix-ui/react-tabs": "^1.1.12", - "@radix-ui/react-toggle": "^1.1.9", - "@radix-ui/react-toggle-group": "^1.1.10", - "@radix-ui/react-tooltip": "^1.2.7", - "@tailwindcss/vite": "^4.1.8", - "@tanstack/react-query": "^5.80.3", + "@tailwindcss/vite": "^4.1.10", + "@tanstack/react-query": "^5.81.2", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", - "date-fns": "^4.1.0", + "framer-motion": "^12.19.1", "i18next": "^25.2.1", - "lucide-react": "^0.513.0", + "lucide-react": "^0.523.0", + "motion": "^12.19.1", + "radix-ui": "^1.4.2", "react": "^19.1.0", "react-copy-to-clipboard": "^5.1.0", - "react-day-picker": "9.7.0", "react-dom": "^19.1.0", - "react-hook-form": "^7.57.0", - "react-i18next": "^15.5.2", + "react-hook-form": "^7.58.1", + "react-i18next": "^15.5.3", "react-router": "^7.6.2", "react-router-dom": "^7.6.2", "react-syntax-highlighter": "^15.6.1", "sonner": "^2.0.5", - "tailwind-merge": "^3.3.0", - "tailwind-scrollbar": "^4.0.2", + "tailwind-merge": "^3.3.1", "tw-animate-css": "^1.3.4", - "yup": "^1.6.1", - "zod": "^3.25.51" + "yup": "^1.6.1" }, - "trustedDependencies": ["@biomejs/biome"] + "trustedDependencies": [ + "@biomejs/biome" + ] } diff --git a/web/src/components/code-viewer.tsx b/web/src/components/code-viewer.tsx index a9aab28d..19550f1f 100644 --- a/web/src/components/code-viewer.tsx +++ b/web/src/components/code-viewer.tsx @@ -1,5 +1,3 @@ -import { Button, buttonVariants } from "@/components/ui/button"; -import { cn } from "@/lib/utils"; import { VariantProps } from "class-variance-authority"; import { Check, Copy } from "lucide-react"; import { type HTMLProps, type ReactNode, useCallback, useEffect, useState } from "react"; @@ -8,6 +6,8 @@ import { useTranslation } from "react-i18next"; import { Prism as SyntaxHighlighter } from "react-syntax-highlighter"; 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"; interface CopyButtonProps extends React.ComponentProps<"button"> { value: string; diff --git a/web/src/components/copyable-field.tsx b/web/src/components/copyable-field.tsx index ff31546f..afd2f569 100644 --- a/web/src/components/copyable-field.tsx +++ b/web/src/components/copyable-field.tsx @@ -1,10 +1,10 @@ -import { Button } from "@/components/ui/button"; -import { Label } from "@/components/ui/label"; import { Check, Copy } from "lucide-react"; import { useCallback, useEffect, useState } from "react"; import { CopyToClipboard } from "react-copy-to-clipboard"; import { useTranslation } from "react-i18next"; import { toast } from "sonner"; +import { Button } from "@/components/ui/button"; +import { Label } from "@/components/ui/label"; interface CopyableFieldProps { label: string; diff --git a/web/src/components/layouts/root-layout.tsx b/web/src/components/layouts/root-layout.tsx index f6e6cf16..89a5f1ce 100644 --- a/web/src/components/layouts/root-layout.tsx +++ b/web/src/components/layouts/root-layout.tsx @@ -1,3 +1,5 @@ +import { NavLink } from "react-router"; +import { Outlet } from "react-router-dom"; import { LanguageSwitcher } from "@/components/language-switcher"; import { ModeToggle } from "@/components/mode-toggle.tsx"; import { ThemeProvider } from "@/components/theme-provider.tsx"; @@ -5,7 +7,8 @@ import { Button } from "@/components/ui/button"; import { Toaster } from "@/components/ui/sonner"; import VersionBadge from "@/components/version-badge"; import { GitHubIcon } from "@/icon"; -import { Outlet } from "react-router-dom"; +import { siteConfig } from "@/lib/config"; +import { MobileNav } from "../modile-nav"; export default function RootLayout() { return ( @@ -13,11 +16,21 @@ export default function RootLayout() {
-
-
-

MemShellParty - JavaWeb

+
+ +
+ + MemShellParty +
-
+ +
+ + +
+
+
Menu
+
+ + Home + + {items.map((item) => ( + + {item.label} + + ))} +
+
+
+
+ + ); +} + +function MobileLink({ + href, + className, + children, + onOpenChange, + ...props +}: Readonly<{ + href: string; + onOpenChange?: (open: boolean) => void; + children: React.ReactNode; + className?: string; +}>) { + return ( + { + onOpenChange?.(false); + }} + className={cn("text-2xl font-medium", className)} + {...props} + > + {children} + + ); +} diff --git a/web/src/components/package-config-card.tsx b/web/src/components/package-config-card.tsx index 7e2b2adf..a207bdf6 100644 --- a/web/src/components/package-config-card.tsx +++ b/web/src/components/package-config-card.tsx @@ -1,12 +1,12 @@ +import { PackageIcon } from "lucide-react"; +import { useEffect, useState } from "react"; +import { FormProvider, UseFormReturn } from "react-hook-form"; +import { useTranslation } from "react-i18next"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card.tsx"; import { FormControl, FormField, FormItem, FormLabel } from "@/components/ui/form.tsx"; import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group.tsx"; import { FormSchema } from "@/types/schema.ts"; import { PackerConfig } from "@/types/shell.ts"; -import { PackageIcon } from "lucide-react"; -import { useEffect, useState } from "react"; -import { FormProvider, UseFormReturn } from "react-hook-form"; -import { useTranslation } from "react-i18next"; type Option = { name: string; diff --git a/web/src/components/quick-usage.tsx b/web/src/components/quick-usage.tsx index 671ed538..d3f993b2 100644 --- a/web/src/components/quick-usage.tsx +++ b/web/src/components/quick-usage.tsx @@ -1,6 +1,6 @@ -import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card.tsx"; import { ScrollTextIcon } from "lucide-react"; import { useTranslation } from "react-i18next"; +import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card.tsx"; export function QuickUsage() { const { t } = useTranslation(); diff --git a/web/src/components/results/agent.tsx b/web/src/components/results/agent.tsx index 8199e522..40169b03 100644 --- a/web/src/components/results/agent.tsx +++ b/web/src/components/results/agent.tsx @@ -1,7 +1,7 @@ -import { downloadBytes, formatBytes } from "@/lib/utils"; -import { GenerateResult } from "@/types/shell"; import { ScrollTextIcon } from "lucide-react"; import { useTranslation } from "react-i18next"; +import { downloadBytes, formatBytes } from "@/lib/utils"; +import { GenerateResult } from "@/types/shell"; import { Button } from "../ui/button"; import { Card, CardContent, CardHeader, CardTitle } from "../ui/card"; import { Separator } from "../ui/separator"; diff --git a/web/src/components/results/basic-info.tsx b/web/src/components/results/basic-info.tsx index 9bf67396..5c0fe353 100644 --- a/web/src/components/results/basic-info.tsx +++ b/web/src/components/results/basic-info.tsx @@ -1,3 +1,5 @@ +import { FileTextIcon } from "lucide-react"; +import { useTranslation } from "react-i18next"; import { shouldHidden } from "@/lib/utils"; import { AntSwordShellToolConfig, @@ -9,8 +11,6 @@ import { ShellToolType, Suo5ShellToolConfig, } from "@/types/shell"; -import { FileTextIcon } from "lucide-react"; -import { useTranslation } from "react-i18next"; import { CopyableField } from "../copyable-field"; import { Card, CardContent, CardHeader, CardTitle } from "../ui/card"; import { Separator } from "../ui/separator"; diff --git a/web/src/components/results/jar-result.tsx b/web/src/components/results/jar-result.tsx index d8f5cc45..4613cea2 100644 --- a/web/src/components/results/jar-result.tsx +++ b/web/src/components/results/jar-result.tsx @@ -1,6 +1,6 @@ +import { useTranslation } from "react-i18next"; import { downloadBytes } from "@/lib/utils"; import { GenerateResult } from "@/types/shell"; -import { useTranslation } from "react-i18next"; import { Button } from "../ui/button"; export function JarResult({ diff --git a/web/src/components/results/result-component.tsx b/web/src/components/results/result-component.tsx index fb9ec1ea..621fa96b 100644 --- a/web/src/components/results/result-component.tsx +++ b/web/src/components/results/result-component.tsx @@ -1,5 +1,5 @@ -import { GenerateResult } from "@/types/shell"; import { TFunction } from "i18next"; +import { GenerateResult } from "@/types/shell"; import { CodeViewer } from "../code-viewer"; import { AgentResult } from "./agent"; import { JarResult } from "./jar-result"; diff --git a/web/src/components/shell-result.tsx b/web/src/components/shell-result.tsx index 6e71c43d..214a025c 100644 --- a/web/src/components/shell-result.tsx +++ b/web/src/components/shell-result.tsx @@ -1,12 +1,12 @@ +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 { DownloadIcon } from "lucide-react"; -import { useTranslation } from "react-i18next"; -import { toast } from "sonner"; import { BasicInfo } from "./results/basic-info"; import { ResultComponent } from "./results/result-component"; diff --git a/web/src/components/tips/jre-tip.tsx b/web/src/components/tips/jre-tip.tsx index 68cb20cf..8a728584 100644 --- a/web/src/components/tips/jre-tip.tsx +++ b/web/src/components/tips/jre-tip.tsx @@ -1,6 +1,6 @@ -import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip.tsx"; import { InfoIcon } from "lucide-react"; import { useTranslation } from "react-i18next"; +import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip.tsx"; export function JreTip() { const { t } = useTranslation(); diff --git a/web/src/components/tools/antsword-tab.tsx b/web/src/components/tools/antsword-tab.tsx index 42197321..726a12f7 100644 --- a/web/src/components/tools/antsword-tab.tsx +++ b/web/src/components/tools/antsword-tab.tsx @@ -1,8 +1,8 @@ -import { FormSchema } from "@/types/schema"; import { FormProvider, UseFormReturn } from "react-hook-form"; import { useTranslation } from "react-i18next"; +import { FormSchema } from "@/types/schema"; import { Card, CardContent } from "../ui/card"; -import { FormField, FormFieldItem, FormFieldLabel } from "../ui/form"; +import { FormControl, FormField, FormFieldItem, FormFieldLabel } from "../ui/form"; import { Input } from "../ui/input"; import { TabsContent } from "../ui/tabs"; import { OptionalClassFormField } from "./classname-field"; @@ -42,7 +42,9 @@ export function AntSwordTabContent({ render={({ field }) => ( {t("shellToolConfig.headerName")} - + + + )} /> diff --git a/web/src/components/tools/behinder-tab.tsx b/web/src/components/tools/behinder-tab.tsx index 218cf16b..9f846ef1 100644 --- a/web/src/components/tools/behinder-tab.tsx +++ b/web/src/components/tools/behinder-tab.tsx @@ -1,6 +1,6 @@ -import { FormSchema } from "@/types/schema"; import { FormProvider, UseFormReturn } from "react-hook-form"; import { useTranslation } from "react-i18next"; +import { FormSchema } from "@/types/schema"; import { Card, CardContent } from "../ui/card"; import { FormField, FormFieldItem, FormFieldLabel } from "../ui/form"; import { Input } from "../ui/input"; diff --git a/web/src/components/tools/classname-field.tsx b/web/src/components/tools/classname-field.tsx index cf071b9c..0164d209 100644 --- a/web/src/components/tools/classname-field.tsx +++ b/web/src/components/tools/classname-field.tsx @@ -1,15 +1,17 @@ +import { ChevronDown, ChevronUp, Settings } from "lucide-react"; +import { Fragment, useId, useState } from "react"; +import { FormProvider, UseFormReturn } from "react-hook-form"; +import { useTranslation } from "react-i18next"; import { FormField, FormFieldItem, FormFieldLabel } from "@/components/ui/form.tsx"; import { Input } from "@/components/ui/input.tsx"; import { FormSchema } from "@/types/schema.ts"; -import { ChevronDown, ChevronUp, Settings } from "lucide-react"; -import { Fragment, useState } from "react"; -import { FormProvider, UseFormReturn } from "react-hook-form"; -import { useTranslation } from "react-i18next"; import { Button } from "../ui/button"; export function OptionalClassFormField({ form }: Readonly<{ form: UseFormReturn }>) { const { t } = useTranslation(); const [showAdvanced, setShowAdvanced] = useState(false); + const shellClassNameId = useId(); + const injectClassNameId = useId(); return (
@@ -32,10 +34,10 @@ export function OptionalClassFormField({ form }: Readonly<{ form: UseFormReturn< name="shellClassName" render={({ field }) => ( - + {t("mainConfig.shellClassName")} {t("optional")} - + )} /> @@ -44,10 +46,10 @@ export function OptionalClassFormField({ form }: Readonly<{ form: UseFormReturn< name="injectorClassName" render={({ field }) => ( - + {t("mainConfig.injectorClassName")} {t("optional")} - + )} /> diff --git a/web/src/components/tools/command-tab.tsx b/web/src/components/tools/command-tab.tsx index 2f7d180f..17c85a67 100644 --- a/web/src/components/tools/command-tab.tsx +++ b/web/src/components/tools/command-tab.tsx @@ -1,8 +1,8 @@ -import { env } from "@/config"; -import { FormSchema } from "@/types/schema"; import { useQuery } from "@tanstack/react-query"; import { FormProvider, UseFormReturn } from "react-hook-form"; import { useTranslation } from "react-i18next"; +import { env } from "@/config"; +import { FormSchema } from "@/types/schema"; import { Card, CardContent } from "../ui/card"; import { FormControl, FormField, FormFieldItem, FormFieldLabel } from "../ui/form"; import { Input } from "../ui/input"; diff --git a/web/src/components/tools/custom-tab.tsx b/web/src/components/tools/custom-tab.tsx index ccbfc88a..1c79493f 100644 --- a/web/src/components/tools/custom-tab.tsx +++ b/web/src/components/tools/custom-tab.tsx @@ -1,9 +1,9 @@ +import { t } from "i18next"; +import { useId, useState } from "react"; +import { FormProvider, UseFormReturn } from "react-hook-form"; import { Card, CardContent } from "@/components/ui/card"; import { TabsContent } from "@/components/ui/tabs"; import { FormSchema } from "@/types/schema"; -import { t } from "i18next"; -import { useState } from "react"; -import { FormProvider, UseFormReturn } from "react-hook-form"; import { FormControl, FormField, FormFieldItem, FormFieldLabel, FormMessage } from "../ui/form"; import { Input } from "../ui/input"; import { Label } from "../ui/label"; @@ -18,7 +18,8 @@ export default function CustomTabContent({ shellTypes, }: Readonly<{ form: UseFormReturn; shellTypes: Array }>) { const [isFile, setIsFile] = useState(false); - + const optionOneId = useId(); + const optionTwoId = useId(); return ( @@ -43,12 +44,12 @@ export default function CustomTabContent({ className="flex items-center space-x-2" >
- - + +
- - + +
diff --git a/web/src/components/tools/godzilla-tab.tsx b/web/src/components/tools/godzilla-tab.tsx index 427d0924..017805a7 100644 --- a/web/src/components/tools/godzilla-tab.tsx +++ b/web/src/components/tools/godzilla-tab.tsx @@ -1,6 +1,6 @@ -import { FormSchema } from "@/types/schema"; import { FormProvider, UseFormReturn } from "react-hook-form"; import { useTranslation } from "react-i18next"; +import { FormSchema } from "@/types/schema"; import { Card, CardContent } from "../ui/card"; import { FormField, FormFieldItem, FormFieldLabel } from "../ui/form"; import { Input } from "../ui/input"; diff --git a/web/src/components/tools/neoreg-tab.tsx b/web/src/components/tools/neoreg-tab.tsx index 8f4c687a..39b84d93 100644 --- a/web/src/components/tools/neoreg-tab.tsx +++ b/web/src/components/tools/neoreg-tab.tsx @@ -1,6 +1,6 @@ -import { FormSchema } from "@/types/schema"; import { FormProvider, UseFormReturn } from "react-hook-form"; import { useTranslation } from "react-i18next"; +import { FormSchema } from "@/types/schema"; import { Card, CardContent } from "../ui/card"; import { FormField, FormFieldItem, FormFieldLabel } from "../ui/form"; import { Input } from "../ui/input"; diff --git a/web/src/components/tools/shelltype-field.tsx b/web/src/components/tools/shelltype-field.tsx index a19baa9d..5d84bfbf 100644 --- a/web/src/components/tools/shelltype-field.tsx +++ b/web/src/components/tools/shelltype-field.tsx @@ -1,10 +1,9 @@ +import { FormProvider, UseFormReturn } from "react-hook-form"; +import { useTranslation } from "react-i18next"; import { FormControl, FormField, FormFieldItem, FormFieldLabel } from "@/components/ui/form.tsx"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select.tsx"; import { FormSchema } from "@/types/schema.ts"; -import { FormProvider, UseFormReturn } from "react-hook-form"; -import { useTranslation } from "react-i18next"; - export function ShellTypeFormField({ form, shellTypes, diff --git a/web/src/components/tools/suo5-tab.tsx b/web/src/components/tools/suo5-tab.tsx index 29951e7e..78873567 100644 --- a/web/src/components/tools/suo5-tab.tsx +++ b/web/src/components/tools/suo5-tab.tsx @@ -1,6 +1,6 @@ -import { FormSchema } from "@/types/schema"; import { FormProvider, UseFormReturn } from "react-hook-form"; import { useTranslation } from "react-i18next"; +import { FormSchema } from "@/types/schema"; import { Card, CardContent } from "../ui/card"; import { FormField, FormFieldItem, FormFieldLabel } from "../ui/form"; import { Input } from "../ui/input"; diff --git a/web/src/components/tools/urlpattern-field.tsx b/web/src/components/tools/urlpattern-field.tsx index 399ebe94..a2e72966 100644 --- a/web/src/components/tools/urlpattern-field.tsx +++ b/web/src/components/tools/urlpattern-field.tsx @@ -1,9 +1,9 @@ +import { FormProvider, UseFormReturn } from "react-hook-form"; +import { useTranslation } from "react-i18next"; import { FormField, FormFieldItem, FormFieldLabel, FormMessage } from "@/components/ui/form.tsx"; import { Input } from "@/components/ui/input.tsx"; import { shouldHidden } from "@/lib/utils"; import { FormSchema } from "@/types/schema.ts"; -import { FormProvider, UseFormReturn } from "react-hook-form"; -import { useTranslation } from "react-i18next"; export function UrlPatternFormField({ form }: Readonly<{ form: UseFormReturn }>) { const { t } = useTranslation(); diff --git a/web/src/components/ui/alert-dialog.tsx b/web/src/components/ui/alert-dialog.tsx index 36995311..d82179e4 100644 --- a/web/src/components/ui/alert-dialog.tsx +++ b/web/src/components/ui/alert-dialog.tsx @@ -1,8 +1,7 @@ +import { AlertDialog as AlertDialogPrimitive } from "radix-ui"; import * as React from "react"; -import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog"; - -import { cn } from "@/lib/utils"; import { buttonVariants } from "@/components/ui/button"; +import { cn } from "@/lib/utils"; function AlertDialog({ ...props }: React.ComponentProps) { return ; diff --git a/web/src/components/ui/alert.tsx b/web/src/components/ui/alert.tsx index aadf66c4..8f1e1f97 100644 --- a/web/src/components/ui/alert.tsx +++ b/web/src/components/ui/alert.tsx @@ -1,5 +1,5 @@ -import * as React from "react"; import { cva, type VariantProps } from "class-variance-authority"; +import * as React from "react"; import { cn } from "@/lib/utils"; diff --git a/web/src/components/ui/badge.tsx b/web/src/components/ui/badge.tsx new file mode 100644 index 00000000..25784f66 --- /dev/null +++ b/web/src/components/ui/badge.tsx @@ -0,0 +1,36 @@ +import { cva, type VariantProps } from "class-variance-authority"; +import { Slot as SlotPrimitive } from "radix-ui"; +import * as React from "react"; + +import { cn } from "@/lib/utils"; + +const badgeVariants = cva( + "inline-flex items-center justify-center rounded-md border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden", + { + variants: { + variant: { + default: "border-transparent bg-primary text-primary-foreground [a&]:hover:bg-primary/90", + secondary: "border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90", + destructive: + "border-transparent bg-destructive text-white [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60", + outline: "text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground", + }, + }, + defaultVariants: { + variant: "default", + }, + }, +); + +function Badge({ + className, + variant, + asChild = false, + ...props +}: React.ComponentProps<"span"> & VariantProps & { asChild?: boolean }) { + const Comp = asChild ? SlotPrimitive.Slot : "span"; + + return ; +} + +export { Badge, badgeVariants }; diff --git a/web/src/components/ui/breadcrumb.tsx b/web/src/components/ui/breadcrumb.tsx new file mode 100644 index 00000000..9bb12d07 --- /dev/null +++ b/web/src/components/ui/breadcrumb.tsx @@ -0,0 +1,92 @@ +import { ChevronRight, MoreHorizontal } from "lucide-react"; +import { Slot as SlotPrimitive } from "radix-ui"; +import * as React from "react"; + +import { cn } from "@/lib/utils"; + +function Breadcrumb({ ...props }: React.ComponentProps<"nav">) { + return