diff --git a/.vscode/settings.json b/.vscode/settings.json index 61683dd..5ebb120 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,3 +1,12 @@ { - "tailwindCSS.experimental.configFile": "packages/ui/src/styles/globals.css" + "tailwindCSS.experimental.configFile": "packages/ui/src/styles/globals.css", + "editor.formatOnSave": false, + "editor.codeActionsOnSave": { + "source.fixAll.eslint": "always" + }, + "eslint.workingDirectories": [ + { "pattern": "apps/*" }, + { "pattern": "packages/*" } + ], + "eslint.useFlatConfig": true } diff --git a/apps/web/app/layout.tsx b/apps/web/app/layout.tsx index b70c759..4d58c00 100644 --- a/apps/web/app/layout.tsx +++ b/apps/web/app/layout.tsx @@ -1,43 +1,43 @@ -import { Geist, Geist_Mono } from "next/font/google" - -import "@workspace/ui/globals.css" -import { Providers } from "@/components/providers" -import { ClerkProvider } from "@clerk/nextjs" -import { Toaster } from "@workspace/ui/components/sonner" +import { Geist, Geist_Mono } from "next/font/google"; +import "@workspace/ui/globals.css"; +import { Providers } from "@/components/providers"; +import { ClerkProvider } from "@clerk/nextjs"; +import { Toaster } from "@workspace/ui/components/sonner"; const fontSans = Geist({ subsets: ["latin"], variable: "--font-sans", -}) +}); const fontMono = Geist_Mono({ subsets: ["latin"], variable: "--font-mono", -}) +}); export default function RootLayout({ children, }: Readonly<{ - children: React.ReactNode + children: React.ReactNode; }>) { return ( - - - - {children} - + colorPrimary: "#3C82F6", + }, + }} + > + + + {children} + - ) + ); } diff --git a/apps/web/package.json b/apps/web/package.json index 5f1fbaa..b786fb0 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -12,7 +12,7 @@ "typecheck": "tsc --noEmit" }, "dependencies": { - "@clerk/nextjs": "^6.30.2", + "@clerk/nextjs": "^6.39.1", "@convex-dev/agent": "^0.1.16", "@hookform/resolvers": "^5.2.1", "@sentry/nextjs": "^10", diff --git a/package.json b/package.json index b156575..6e6cc17 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ "devDependencies": { "@workspace/eslint-config": "workspace:*", "@workspace/typescript-config": "workspace:*", + "eslint": "^9.32.0", "prettier": "^3.6.2", "turbo": "^2.5.5", "typescript": "5.9.2" diff --git a/packages/eslint-config/base.js b/packages/eslint-config/base.js index b0f1eae..5f8d31d 100644 --- a/packages/eslint-config/base.js +++ b/packages/eslint-config/base.js @@ -1,5 +1,6 @@ import js from "@eslint/js" import eslintConfigPrettier from "eslint-config-prettier" +import eslintPluginPrettier from "eslint-plugin-prettier" import onlyWarn from "eslint-plugin-only-warn" import turboPlugin from "eslint-plugin-turbo" import tseslint from "typescript-eslint" @@ -13,6 +14,14 @@ export const config = [ js.configs.recommended, eslintConfigPrettier, ...tseslint.configs.recommended, + { + plugins: { + prettier: eslintPluginPrettier, + }, + rules: { + "prettier/prettier": "warn", + }, + }, { plugins: { turbo: turboPlugin, diff --git a/packages/eslint-config/package.json b/packages/eslint-config/package.json index 7c83663..067ce6d 100644 --- a/packages/eslint-config/package.json +++ b/packages/eslint-config/package.json @@ -17,6 +17,7 @@ "eslint": "^9.32.0", "eslint-config-prettier": "^9.1.2", "eslint-plugin-only-warn": "^1.1.0", + "eslint-plugin-prettier": "^5.5.5", "eslint-plugin-react": "^7.37.5", "eslint-plugin-react-hooks": "^5.2.0", "eslint-plugin-turbo": "^2.5.5", diff --git a/packages/ui/eslint.config.js b/packages/ui/eslint.config.js index 69da3ed..f79dd7d 100644 --- a/packages/ui/eslint.config.js +++ b/packages/ui/eslint.config.js @@ -1,4 +1,4 @@ -import { config } from "@workspace/eslint-config/react-internal" +import { config } from "@workspace/eslint-config/react-internal"; /** @type {import("eslint").Linter.Config} */ -export default config +export default config; diff --git a/packages/ui/postcss.config.mjs b/packages/ui/postcss.config.mjs index 4ae682d..c15b998 100644 --- a/packages/ui/postcss.config.mjs +++ b/packages/ui/postcss.config.mjs @@ -1,6 +1,6 @@ /** @type {import('postcss-load-config').Config} */ const config = { - plugins: { "@tailwindcss/postcss": {} }, + plugins: { "@tailwindcss/postcss": {} }, }; export default config; diff --git a/packages/ui/src/components/accordion.tsx b/packages/ui/src/components/accordion.tsx index 3b51edb..5f8774a 100644 --- a/packages/ui/src/components/accordion.tsx +++ b/packages/ui/src/components/accordion.tsx @@ -1,15 +1,15 @@ -"use client" +"use client"; -import * as React from "react" -import * as AccordionPrimitive from "@radix-ui/react-accordion" -import { ChevronDownIcon } from "lucide-react" +import * as React from "react"; +import * as AccordionPrimitive from "@radix-ui/react-accordion"; +import { ChevronDownIcon } from "lucide-react"; -import { cn } from "@workspace/ui/lib/utils" +import { cn } from "@workspace/ui/lib/utils"; function Accordion({ ...props }: React.ComponentProps) { - return + return ; } function AccordionItem({ @@ -22,7 +22,7 @@ function AccordionItem({ className={cn("border-b last:border-b-0", className)} {...props} /> - ) + ); } function AccordionTrigger({ @@ -36,7 +36,7 @@ function AccordionTrigger({ data-slot="accordion-trigger" className={cn( "focus-visible:border-ring focus-visible:ring-ring/50 flex flex-1 items-start justify-between gap-4 rounded-md py-4 text-left text-sm font-medium transition-all outline-none hover:underline focus-visible:ring-[3px] disabled:pointer-events-none disabled:opacity-50 [&[data-state=open]>svg]:rotate-180", - className + className, )} {...props} > @@ -44,7 +44,7 @@ function AccordionTrigger({ - ) + ); } function AccordionContent({ @@ -60,7 +60,7 @@ function AccordionContent({ >
{children}
- ) + ); } -export { Accordion, AccordionItem, AccordionTrigger, AccordionContent } +export { Accordion, AccordionItem, AccordionTrigger, AccordionContent }; diff --git a/packages/ui/src/components/ai/branch.tsx b/packages/ui/src/components/ai/branch.tsx index 346961e..0ef5746 100644 --- a/packages/ui/src/components/ai/branch.tsx +++ b/packages/ui/src/components/ai/branch.tsx @@ -209,4 +209,4 @@ export const AIBranchPage = ({ className }: AIBranchPageProps) => { {currentBranch + 1} of {totalBranches} ); -}; \ No newline at end of file +}; diff --git a/packages/ui/src/components/ai/conversation.tsx b/packages/ui/src/components/ai/conversation.tsx index 7dde971..5ffbf17 100644 --- a/packages/ui/src/components/ai/conversation.tsx +++ b/packages/ui/src/components/ai/conversation.tsx @@ -53,4 +53,4 @@ export const AIConversationScrollButton = () => { ) ); -}; \ No newline at end of file +}; diff --git a/packages/ui/src/components/ai/input.tsx b/packages/ui/src/components/ai/input.tsx index acbd169..729ecfd 100644 --- a/packages/ui/src/components/ai/input.tsx +++ b/packages/ui/src/components/ai/input.tsx @@ -47,12 +47,12 @@ const useAutoResizeTextarea = ({ // Calculate new height const newHeight = Math.max( minHeight, - Math.min(textarea.scrollHeight, maxHeight ?? Number.POSITIVE_INFINITY) + Math.min(textarea.scrollHeight, maxHeight ?? Number.POSITIVE_INFINITY), ); textarea.style.height = `${newHeight}px`; }, - [minHeight, maxHeight] + [minHeight, maxHeight], ); useEffect(() => { @@ -79,7 +79,7 @@ export const AIInput = ({ className, ...props }: AIInputProps) => (
@@ -120,7 +120,7 @@ export const AIInputTextarea = ({ "w-full resize-none rounded-none border-none p-3 shadow-none outline-none ring-0", "bg-transparent dark:bg-transparent", "focus-visible:ring-0", - className + className, )} name="message" onChange={(e) => { @@ -154,7 +154,7 @@ export const AIInputTools = ({ className, ...props }: AIInputToolsProps) => ( className={cn( "flex items-center gap-1", "[&_button:first-child]:rounded-bl-xl", - className + className, )} {...props} /> @@ -177,7 +177,7 @@ export const AIInputButton = ({ "shrink-0 gap-1.5 rounded-lg", variant === "ghost" && "text-muted-foreground", newSize === "default" && "px-3", - className + className, )} size={newSize} type="button" @@ -240,7 +240,7 @@ export const AIInputModelSelectTrigger = ({ className={cn( "border-none bg-transparent font-medium text-muted-foreground shadow-none transition-colors", 'hover:bg-accent hover:text-foreground [&[aria-expanded="true"]]:bg-accent [&[aria-expanded="true"]]:text-foreground', - className + className, )} {...props} /> @@ -273,4 +273,4 @@ export const AIInputModelSelectValue = ({ ...props }: AIInputModelSelectValueProps) => ( -); \ No newline at end of file +); diff --git a/packages/ui/src/components/ai/message.tsx b/packages/ui/src/components/ai/message.tsx index 63840fa..bd5f7cf 100644 --- a/packages/ui/src/components/ai/message.tsx +++ b/packages/ui/src/components/ai/message.tsx @@ -1,5 +1,9 @@ import type { ComponentProps, HTMLAttributes } from "react"; -import { Avatar, AvatarFallback, AvatarImage } from "@workspace/ui/components/avatar"; +import { + Avatar, + AvatarFallback, + AvatarImage, +} from "@workspace/ui/components/avatar"; import { cn } from "@workspace/ui/lib/utils"; export type AIMessageProps = HTMLAttributes & { @@ -12,7 +16,7 @@ export const AIMessage = ({ className, from, ...props }: AIMessageProps) => ( "group flex w-full items-end justify-end gap-2 py-2", from === "user" ? "is-user" : "is-assistant flex-row-reverse justify-end", "[&>div]:max-w-[80%]", - className + className, )} {...props} /> @@ -31,7 +35,7 @@ export const AIMessageContent = ({ "flex flex-col gap-2 rounded-lg border border-border px-3 py-2 text-sm", "bg-background text-foreground", "group-[.is-user]:border-transparent group-[.is-user]:bg-gradient-to-b group-[.is-user]:from-primary group-[.is-user]:to-[#0b63f3] group-[.is-user]:text-primary-foreground", - className + className, )} {...props} > @@ -54,4 +58,4 @@ export const AIMessageAvatar = ({ {name?.slice(0, 2) || "ME"} -); \ No newline at end of file +); diff --git a/packages/ui/src/components/ai/reasoning.tsx b/packages/ui/src/components/ai/reasoning.tsx index 0bf777b..163789a 100644 --- a/packages/ui/src/components/ai/reasoning.tsx +++ b/packages/ui/src/components/ai/reasoning.tsx @@ -165,4 +165,4 @@ export const AIReasoningContent = memo( AIReasoning.displayName = "AIReasoning"; AIReasoningTrigger.displayName = "AIReasoningTrigger"; -AIReasoningContent.displayName = "AIReasoningContent"; \ No newline at end of file +AIReasoningContent.displayName = "AIReasoningContent"; diff --git a/packages/ui/src/components/ai/response.tsx b/packages/ui/src/components/ai/response.tsx index 283949e..da545a0 100644 --- a/packages/ui/src/components/ai/response.tsx +++ b/packages/ui/src/components/ai/response.tsx @@ -104,4 +104,4 @@ export const AIResponse = memo( (prevProps, nextProps) => prevProps.children === nextProps.children, ); -AIResponse.displayName = "AIResponse"; \ No newline at end of file +AIResponse.displayName = "AIResponse"; diff --git a/packages/ui/src/components/ai/source.tsx b/packages/ui/src/components/ai/source.tsx index ca07a34..e75694c 100644 --- a/packages/ui/src/components/ai/source.tsx +++ b/packages/ui/src/components/ai/source.tsx @@ -73,4 +73,4 @@ export const AISource = ({ )} -); \ No newline at end of file +); diff --git a/packages/ui/src/components/ai/suggestion.tsx b/packages/ui/src/components/ai/suggestion.tsx index 91f18e5..17104ee 100644 --- a/packages/ui/src/components/ai/suggestion.tsx +++ b/packages/ui/src/components/ai/suggestion.tsx @@ -53,4 +53,4 @@ export const AISuggestion = ({ {children || suggestion} ); -}; \ No newline at end of file +}; diff --git a/packages/ui/src/components/ai/tool.tsx b/packages/ui/src/components/ai/tool.tsx index 7514c03..d31dfe6 100644 --- a/packages/ui/src/components/ai/tool.tsx +++ b/packages/ui/src/components/ai/tool.tsx @@ -27,7 +27,7 @@ export const AITool = ({ className, ...props }: AIToolProps) => ( @@ -71,7 +71,7 @@ export const AIToolHeader = ({ @@ -139,11 +139,11 @@ export const AIToolResult = ({ "overflow-x-auto rounded-md p-3 text-xs", error ? "bg-destructive/10 text-destructive" - : "bg-muted/50 text-foreground" + : "bg-muted/50 text-foreground", )} > {error ?
{error}
:
{result}
} ); -}; \ No newline at end of file +}; diff --git a/packages/ui/src/components/alert-dialog.tsx b/packages/ui/src/components/alert-dialog.tsx index 8de0fa5..e0368dc 100644 --- a/packages/ui/src/components/alert-dialog.tsx +++ b/packages/ui/src/components/alert-dialog.tsx @@ -1,15 +1,15 @@ -"use client" +"use client"; -import * as React from "react" -import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog" +import * as React from "react"; +import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog"; -import { cn } from "@workspace/ui/lib/utils" -import { buttonVariants } from "@workspace/ui/components/button" +import { cn } from "@workspace/ui/lib/utils"; +import { buttonVariants } from "@workspace/ui/components/button"; function AlertDialog({ ...props }: React.ComponentProps) { - return + return ; } function AlertDialogTrigger({ @@ -17,7 +17,7 @@ function AlertDialogTrigger({ }: React.ComponentProps) { return ( - ) + ); } function AlertDialogPortal({ @@ -25,7 +25,7 @@ function AlertDialogPortal({ }: React.ComponentProps) { return ( - ) + ); } function AlertDialogOverlay({ @@ -37,11 +37,11 @@ function AlertDialogOverlay({ data-slot="alert-dialog-overlay" className={cn( "data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50", - className + className, )} {...props} /> - ) + ); } function AlertDialogContent({ @@ -55,12 +55,12 @@ function AlertDialogContent({ data-slot="alert-dialog-content" className={cn( "bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-6 shadow-lg duration-200 sm:max-w-lg", - className + className, )} {...props} /> - ) + ); } function AlertDialogHeader({ @@ -73,7 +73,7 @@ function AlertDialogHeader({ className={cn("flex flex-col gap-2 text-center sm:text-left", className)} {...props} /> - ) + ); } function AlertDialogFooter({ @@ -85,11 +85,11 @@ function AlertDialogFooter({ data-slot="alert-dialog-footer" className={cn( "flex flex-col-reverse gap-2 sm:flex-row sm:justify-end", - className + className, )} {...props} /> - ) + ); } function AlertDialogTitle({ @@ -102,7 +102,7 @@ function AlertDialogTitle({ className={cn("text-lg font-semibold", className)} {...props} /> - ) + ); } function AlertDialogDescription({ @@ -115,7 +115,7 @@ function AlertDialogDescription({ className={cn("text-muted-foreground text-sm", className)} {...props} /> - ) + ); } function AlertDialogAction({ @@ -127,7 +127,7 @@ function AlertDialogAction({ className={cn(buttonVariants(), className)} {...props} /> - ) + ); } function AlertDialogCancel({ @@ -139,7 +139,7 @@ function AlertDialogCancel({ className={cn(buttonVariants({ variant: "outline" }), className)} {...props} /> - ) + ); } export { @@ -154,4 +154,4 @@ export { AlertDialogDescription, AlertDialogAction, AlertDialogCancel, -} +}; diff --git a/packages/ui/src/components/alert.tsx b/packages/ui/src/components/alert.tsx index 15d208b..2eeca69 100644 --- a/packages/ui/src/components/alert.tsx +++ b/packages/ui/src/components/alert.tsx @@ -1,7 +1,7 @@ -import * as React from "react" -import { cva, type VariantProps } from "class-variance-authority" +import * as React from "react"; +import { cva, type VariantProps } from "class-variance-authority"; -import { cn } from "@workspace/ui/lib/utils" +import { cn } from "@workspace/ui/lib/utils"; const alertVariants = cva( "relative w-full rounded-lg border px-4 py-3 text-sm grid has-[>svg]:grid-cols-[calc(var(--spacing)*4)_1fr] grid-cols-[0_1fr] has-[>svg]:gap-x-3 gap-y-0.5 items-start [&>svg]:size-4 [&>svg]:translate-y-0.5 [&>svg]:text-current", @@ -16,8 +16,8 @@ const alertVariants = cva( defaultVariants: { variant: "default", }, - } -) + }, +); function Alert({ className, @@ -31,7 +31,7 @@ function Alert({ className={cn(alertVariants({ variant }), className)} {...props} /> - ) + ); } function AlertTitle({ className, ...props }: React.ComponentProps<"div">) { @@ -40,11 +40,11 @@ function AlertTitle({ className, ...props }: React.ComponentProps<"div">) { data-slot="alert-title" className={cn( "col-start-2 line-clamp-1 min-h-4 font-medium tracking-tight", - className + className, )} {...props} /> - ) + ); } function AlertDescription({ @@ -56,11 +56,11 @@ function AlertDescription({ data-slot="alert-description" className={cn( "text-muted-foreground col-start-2 grid justify-items-start gap-1 text-sm [&_p]:leading-relaxed", - className + className, )} {...props} /> - ) + ); } -export { Alert, AlertTitle, AlertDescription } +export { Alert, AlertTitle, AlertDescription }; diff --git a/packages/ui/src/components/aspect-ratio.tsx b/packages/ui/src/components/aspect-ratio.tsx index 3df3fd0..c16d6bc 100644 --- a/packages/ui/src/components/aspect-ratio.tsx +++ b/packages/ui/src/components/aspect-ratio.tsx @@ -1,11 +1,11 @@ -"use client" +"use client"; -import * as AspectRatioPrimitive from "@radix-ui/react-aspect-ratio" +import * as AspectRatioPrimitive from "@radix-ui/react-aspect-ratio"; function AspectRatio({ ...props }: React.ComponentProps) { - return + return ; } -export { AspectRatio } +export { AspectRatio }; diff --git a/packages/ui/src/components/avatar.tsx b/packages/ui/src/components/avatar.tsx index 5f3a8f7..2cf6dd8 100644 --- a/packages/ui/src/components/avatar.tsx +++ b/packages/ui/src/components/avatar.tsx @@ -1,9 +1,9 @@ -"use client" +"use client"; -import * as React from "react" -import * as AvatarPrimitive from "@radix-ui/react-avatar" +import * as React from "react"; +import * as AvatarPrimitive from "@radix-ui/react-avatar"; -import { cn } from "@workspace/ui/lib/utils" +import { cn } from "@workspace/ui/lib/utils"; function Avatar({ className, @@ -14,11 +14,11 @@ function Avatar({ data-slot="avatar" className={cn( "relative flex size-8 shrink-0 overflow-hidden rounded-full", - className + className, )} {...props} /> - ) + ); } function AvatarImage({ @@ -31,7 +31,7 @@ function AvatarImage({ className={cn("aspect-square size-full", className)} {...props} /> - ) + ); } function AvatarFallback({ @@ -43,11 +43,11 @@ function AvatarFallback({ data-slot="avatar-fallback" className={cn( "bg-muted flex size-full items-center justify-center rounded-full", - className + className, )} {...props} /> - ) + ); } -export { Avatar, AvatarImage, AvatarFallback } +export { Avatar, AvatarImage, AvatarFallback }; diff --git a/packages/ui/src/components/badge.tsx b/packages/ui/src/components/badge.tsx index 1e9c9a3..c557c63 100644 --- a/packages/ui/src/components/badge.tsx +++ b/packages/ui/src/components/badge.tsx @@ -1,8 +1,8 @@ -import * as React from "react" -import { Slot } from "@radix-ui/react-slot" -import { cva, type VariantProps } from "class-variance-authority" +import * as React from "react"; +import { Slot } from "@radix-ui/react-slot"; +import { cva, type VariantProps } from "class-variance-authority"; -import { cn } from "@workspace/ui/lib/utils" +import { cn } from "@workspace/ui/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", @@ -22,8 +22,8 @@ const badgeVariants = cva( defaultVariants: { variant: "default", }, - } -) + }, +); function Badge({ className, @@ -32,7 +32,7 @@ function Badge({ ...props }: React.ComponentProps<"span"> & VariantProps & { asChild?: boolean }) { - const Comp = asChild ? Slot : "span" + const Comp = asChild ? Slot : "span"; return ( - ) + ); } -export { Badge, badgeVariants } +export { Badge, badgeVariants }; diff --git a/packages/ui/src/components/breadcrumb.tsx b/packages/ui/src/components/breadcrumb.tsx index 33784bf..464efce 100644 --- a/packages/ui/src/components/breadcrumb.tsx +++ b/packages/ui/src/components/breadcrumb.tsx @@ -1,11 +1,11 @@ -import * as React from "react" -import { Slot } from "@radix-ui/react-slot" -import { ChevronRight, MoreHorizontal } from "lucide-react" +import * as React from "react"; +import { Slot } from "@radix-ui/react-slot"; +import { ChevronRight, MoreHorizontal } from "lucide-react"; -import { cn } from "@workspace/ui/lib/utils" +import { cn } from "@workspace/ui/lib/utils"; function Breadcrumb({ ...props }: React.ComponentProps<"nav">) { - return