From 027f6529f2f60acc9ab951c2ec2df4090100de1a Mon Sep 17 00:00:00 2001 From: Stijnus Date: Fri, 24 Jan 2025 16:14:48 +0100 Subject: [PATCH] UI Enhancements --- app/components/settings/debug/DebugTab.tsx | 906 ++++++++++++--------- app/components/ui/Badge.tsx | 33 + app/components/ui/Collapsible.tsx | 10 + app/components/ui/Progress.tsx | 22 + app/components/ui/ScrollArea.tsx | 39 + app/lib/utils.ts | 6 + package.json | 7 +- pnpm-lock.yaml | 169 +++- 8 files changed, 774 insertions(+), 418 deletions(-) create mode 100644 app/components/ui/Badge.tsx create mode 100644 app/components/ui/Collapsible.tsx create mode 100644 app/components/ui/Progress.tsx create mode 100644 app/components/ui/ScrollArea.tsx create mode 100644 app/lib/utils.ts diff --git a/app/components/settings/debug/DebugTab.tsx b/app/components/settings/debug/DebugTab.tsx index e3fbc3d..438e193 100644 --- a/app/components/settings/debug/DebugTab.tsx +++ b/app/components/settings/debug/DebugTab.tsx @@ -3,6 +3,11 @@ import { toast } from 'react-toastify'; import { classNames } from '~/utils/classNames'; import { logStore } from '~/lib/stores/logs'; import type { LogEntry } from '~/lib/stores/logs'; +import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '~/components/ui/Collapsible'; +import { Progress } from '~/components/ui/Progress'; +import { ScrollArea } from '~/components/ui/ScrollArea'; +import { Badge, type BadgeProps } from '~/components/ui/Badge'; +import { cn } from '~/lib/utils'; interface SystemInfo { os: string; @@ -124,18 +129,11 @@ interface WebAppInfo { }; } -interface GitInfo { - branch: string; - commit: string; - commitTime: string; - author: string; - remoteUrl: string; -} - -interface RepoData { +// Add interface for GitHub API response +interface GitHubRepoResponse { name: string; full_name: string; - description: string; + description: string | null; stargazers_count: number; forks_count: number; open_issues_count: number; @@ -147,14 +145,13 @@ interface RepoData { }; } -interface AppData { - name: string; - version: string; - description: string; - license: string; - nodeVersion: string; - dependencies: { [key: string]: string }; - devDependencies: { [key: string]: string }; +// Add interface for Git info response +interface GitInfo { + branch: string; + commit: string; + commitTime: string; + author: string; + remoteUrl: string; } export default function DebugTab() { @@ -174,6 +171,14 @@ export default function DebugTab() { lastCheck: null, }); + // Add section collapse state + const [openSections, setOpenSections] = useState({ + system: true, + performance: true, + webapp: true, + errors: true, + }); + // Fetch initial data useEffect(() => { getSystemInfo(); @@ -368,13 +373,11 @@ export default function DebugTab() { if (!appInfoResponse.ok) { throw new Error('Failed to fetch webapp info'); } - - const appData = (await appInfoResponse.json()) as AppData; + const appData = (await appInfoResponse.json()) as Record; // Fetch git info const gitInfoResponse = await fetch('/api/system/git-info'); let gitInfo: GitInfo | undefined; - if (gitInfoResponse.ok) { gitInfo = (await gitInfoResponse.json()) as GitInfo; } @@ -382,13 +385,12 @@ export default function DebugTab() { // Fetch GitHub repository info const repoInfoResponse = await fetch('https://api.github.com/repos/stackblitz-labs/bolt.diy'); let repoInfo: WebAppInfo['repoInfo'] | undefined; - if (repoInfoResponse.ok) { - const repoData = (await repoInfoResponse.json()) as RepoData; + const repoData = (await repoInfoResponse.json()) as GitHubRepoResponse; repoInfo = { name: repoData.name, fullName: repoData.full_name, - description: repoData.description, + description: repoData.description ?? '', stars: repoData.stargazers_count, forks: repoData.forks_count, openIssues: repoData.open_issues_count, @@ -409,7 +411,13 @@ export default function DebugTab() { }; setWebAppInfo({ - ...appData, + name: appData.name as string, + version: appData.version as string, + description: appData.description as string, + license: appData.license as string, + nodeVersion: appData.nodeVersion as string, + dependencies: appData.dependencies as Record, + devDependencies: appData.devDependencies as Record, ...buildInfo, gitInfo, repoInfo, @@ -587,7 +595,44 @@ export default function DebugTab() { }; return ( -
+
+ {/* Quick Stats Banner */} +
+
+
Memory Usage
+
+ {systemInfo?.memory.percentage}% +
+ +
+ +
+
Page Load Time
+
+ {systemInfo ? (systemInfo.performance.timing.loadTime / 1000).toFixed(2) + 's' : '-'} +
+
+ DOM Ready: {systemInfo ? (systemInfo.performance.timing.domReadyTime / 1000).toFixed(2) + 's' : '-'} +
+
+ +
+
Network Speed
+
+ {systemInfo?.network.downlink || '-'} Mbps +
+
RTT: {systemInfo?.network.rtt || '-'} ms
+
+ +
+
Errors
+
{errorLog.errors.length}
+
+ Last Check: {errorLog.lastCheck ? new Date(errorLog.lastCheck).toLocaleTimeString() : 'Never'} +
+
+
+ {/* Action Buttons */}
{/* System Information */} -
-
-
-

System Information

-
- {systemInfo ? ( -
-
-
-
- OS: - {systemInfo.os} -
-
-
- Platform: - {systemInfo.platform} -
-
-
- Architecture: - {systemInfo.arch} -
-
-
- CPU Cores: - {systemInfo.cpus} -
-
-
- Node Version: - {systemInfo.node} -
-
-
- Network Type: - - {systemInfo.network.type} ({systemInfo.network.effectiveType}) - -
-
-
- Network Speed: - - {systemInfo.network.downlink}Mbps (RTT: {systemInfo.network.rtt}ms) - -
- {systemInfo.battery && ( -
-
- Battery: - - {systemInfo.battery.level.toFixed(1)}% {systemInfo.battery.charging ? '(Charging)' : ''} - -
+ setOpenSections((prev) => ({ ...prev, system: open }))} + className="w-full" + > + +
+
+
+

System Information

+
+
-
- Storage: - - {(systemInfo.storage.usage / (1024 * 1024 * 1024)).toFixed(2)}GB /{' '} - {(systemInfo.storage.quota / (1024 * 1024 * 1024)).toFixed(2)}GB - -
-
-
-
-
- Memory Usage: - - {systemInfo.memory.used} / {systemInfo.memory.total} ({systemInfo.memory.percentage}%) - -
-
-
- Browser: - - {systemInfo.browser.name} {systemInfo.browser.version} - -
-
-
- Screen: - - {systemInfo.screen.width}x{systemInfo.screen.height} ({systemInfo.screen.pixelRatio}x) - -
-
-
- Timezone: - {systemInfo.time.timezone} -
-
-
- Language: - {systemInfo.browser.language} -
-
-
- JS Heap: - - {(systemInfo.performance.memory.usedJSHeapSize / (1024 * 1024)).toFixed(1)}MB /{' '} - {(systemInfo.performance.memory.totalJSHeapSize / (1024 * 1024)).toFixed(1)}MB ( - {systemInfo.performance.memory.usagePercentage.toFixed(1)}%) - -
-
-
- Page Load: - - {(systemInfo.performance.timing.loadTime / 1000).toFixed(2)}s - -
-
-
- DOM Ready: - - {(systemInfo.performance.timing.domReadyTime / 1000).toFixed(2)}s - -
-
+ />
- ) : ( -
Loading system information...
- )} -
+ + + +
+ {systemInfo ? ( +
+
+
+
+ OS: + {systemInfo.os} +
+
+
+ Platform: + {systemInfo.platform} +
+
+
+ Architecture: + {systemInfo.arch} +
+
+
+ CPU Cores: + {systemInfo.cpus} +
+
+
+ Node Version: + {systemInfo.node} +
+
+
+ Network Type: + + {systemInfo.network.type} ({systemInfo.network.effectiveType}) + +
+
+
+ Network Speed: + + {systemInfo.network.downlink}Mbps (RTT: {systemInfo.network.rtt}ms) + +
+ {systemInfo.battery && ( +
+
+ Battery: + + {systemInfo.battery.level.toFixed(1)}% {systemInfo.battery.charging ? '(Charging)' : ''} + +
+ )} +
+
+ Storage: + + {(systemInfo.storage.usage / (1024 * 1024 * 1024)).toFixed(2)}GB /{' '} + {(systemInfo.storage.quota / (1024 * 1024 * 1024)).toFixed(2)}GB + +
+
+
+
+
+ Memory Usage: + + {systemInfo.memory.used} / {systemInfo.memory.total} ({systemInfo.memory.percentage}%) + +
+
+
+ Browser: + + {systemInfo.browser.name} {systemInfo.browser.version} + +
+
+
+ Screen: + + {systemInfo.screen.width}x{systemInfo.screen.height} ({systemInfo.screen.pixelRatio}x) + +
+
+
+ Timezone: + {systemInfo.time.timezone} +
+
+
+ Language: + {systemInfo.browser.language} +
+
+
+ JS Heap: + + {(systemInfo.performance.memory.usedJSHeapSize / (1024 * 1024)).toFixed(1)}MB /{' '} + {(systemInfo.performance.memory.totalJSHeapSize / (1024 * 1024)).toFixed(1)}MB ( + {systemInfo.performance.memory.usagePercentage.toFixed(1)}%) + +
+
+
+ Page Load: + + {(systemInfo.performance.timing.loadTime / 1000).toFixed(2)}s + +
+
+
+ DOM Ready: + + {(systemInfo.performance.timing.domReadyTime / 1000).toFixed(2)}s + +
+
+
+ ) : ( +
Loading system information...
+ )} +
+ + {/* Performance Metrics */} -
-
-
-

Performance Metrics

-
- {systemInfo && ( -
-
-
- Page Load Time: - - {(systemInfo.performance.timing.loadTime / 1000).toFixed(2)}s - -
-
- DOM Ready Time: - - {(systemInfo.performance.timing.domReadyTime / 1000).toFixed(2)}s - -
-
- Request Time: - - {(systemInfo.performance.timing.requestTime / 1000).toFixed(2)}s - -
-
- Redirect Time: - - {(systemInfo.performance.timing.redirectTime / 1000).toFixed(2)}s - -
-
-
-
- JS Heap Usage: - - {(systemInfo.performance.memory.usedJSHeapSize / (1024 * 1024)).toFixed(1)}MB /{' '} - {(systemInfo.performance.memory.totalJSHeapSize / (1024 * 1024)).toFixed(1)}MB - -
-
- Heap Utilization: - - {systemInfo.performance.memory.usagePercentage.toFixed(1)}% - -
-
- Navigation Type: - - {systemInfo.performance.navigation.type === 0 - ? 'Navigate' - : systemInfo.performance.navigation.type === 1 - ? 'Reload' - : systemInfo.performance.navigation.type === 2 - ? 'Back/Forward' - : 'Other'} - -
-
- Redirects: - - {systemInfo.performance.navigation.redirectCount} - -
+ setOpenSections((prev) => ({ ...prev, performance: open }))} + className="w-full" + > + +
+
+
+

Performance Metrics

+
- )} -
+ + + +
+ {systemInfo && ( +
+
+
+ Page Load Time: + + {(systemInfo.performance.timing.loadTime / 1000).toFixed(2)}s + +
+
+ DOM Ready Time: + + {(systemInfo.performance.timing.domReadyTime / 1000).toFixed(2)}s + +
+
+ Request Time: + + {(systemInfo.performance.timing.requestTime / 1000).toFixed(2)}s + +
+
+ Redirect Time: + + {(systemInfo.performance.timing.redirectTime / 1000).toFixed(2)}s + +
+
+
+
+ JS Heap Usage: + + {(systemInfo.performance.memory.usedJSHeapSize / (1024 * 1024)).toFixed(1)}MB /{' '} + {(systemInfo.performance.memory.totalJSHeapSize / (1024 * 1024)).toFixed(1)}MB + +
+
+ Heap Utilization: + + {systemInfo.performance.memory.usagePercentage.toFixed(1)}% + +
+
+ Navigation Type: + + {systemInfo.performance.navigation.type === 0 + ? 'Navigate' + : systemInfo.performance.navigation.type === 1 + ? 'Reload' + : systemInfo.performance.navigation.type === 2 + ? 'Back/Forward' + : 'Other'} + +
+
+ Redirects: + + {systemInfo.performance.navigation.redirectCount} + +
+
+
+ )} +
+
+ {/* WebApp Information */} -
-
-
-

WebApp Information

-
- {webAppInfo ? ( -
-
-
-
- Name: - {webAppInfo.name} -
-
-
- Version: - {webAppInfo.version} -
-
-
- Description: - {webAppInfo.description} -
-
-
- License: - {webAppInfo.license} -
-
-
- Node Version: - {webAppInfo.nodeVersion} -
- {webAppInfo.buildTime && ( -
-
- Build Time: - {webAppInfo.buildTime} -
- )} - {webAppInfo.buildNumber && ( -
-
- Build Number: - {webAppInfo.buildNumber} -
- )} - {webAppInfo.environment && ( -
-
- Environment: - {webAppInfo.environment} -
- )} + setOpenSections((prev) => ({ ...prev, webapp: open }))} + className="w-full" + > + +
+
+
+

WebApp Information

-
-
-
-
- Key Dependencies: +
+
+ + + +
+ {webAppInfo ? ( +
+
+
+
+ Name: + {webAppInfo.name} +
+
+
+ Version: + {webAppInfo.version} +
+
+
+ Description: + {webAppInfo.description} +
+
+
+ License: + {webAppInfo.license} +
+
+
+ Node Version: + {webAppInfo.nodeVersion} +
+ {webAppInfo.buildTime && ( +
+
+ Build Time: + {webAppInfo.buildTime} +
+ )} + {webAppInfo.buildNumber && ( +
+
+ Build Number: + {webAppInfo.buildNumber} +
+ )} + {webAppInfo.environment && ( +
+
+ Environment: + {webAppInfo.environment} +
+ )}
-
- {Object.entries(webAppInfo.dependencies) - .filter(([key]) => ['react', '@remix-run/react', 'next', 'typescript'].includes(key)) - .map(([key, version]) => ( -
- {key}: {version} +
+
+
+
+ Key Dependencies: +
+
+ {Object.entries(webAppInfo.dependencies) + .filter(([key]) => ['react', '@remix-run/react', 'next', 'typescript'].includes(key)) + .map(([key, version]) => ( +
+ {key}: {version} +
+ ))} +
+
+ {webAppInfo.gitInfo && ( +
+
+
+ Git Info:
- ))} +
+
+ Branch: {webAppInfo.gitInfo.branch} +
+
+ Commit: {webAppInfo.gitInfo.commit} +
+
+ Commit Time: {webAppInfo.gitInfo.commitTime} +
+
+ Author: {webAppInfo.gitInfo.author} +
+
+ Remote URL: {webAppInfo.gitInfo.remoteUrl} +
+
+
+ )} + {webAppInfo.repoInfo && ( +
+
+
+ GitHub Repository: +
+
+
Name: {webAppInfo.repoInfo.name}
+
+ Full Name: {webAppInfo.repoInfo.fullName} +
+
+ Description: {webAppInfo.repoInfo.description} +
+
Stars: {webAppInfo.repoInfo.stars}
+
Forks: {webAppInfo.repoInfo.forks}
+
+ Open Issues: {webAppInfo.repoInfo.openIssues} +
+
+ Default Branch: {webAppInfo.repoInfo.defaultBranch} +
+
+ Last Update: {webAppInfo.repoInfo.lastUpdate} +
+
+ Owner: {webAppInfo.repoInfo.owner.login} +
+
+ Avatar URL: {webAppInfo.repoInfo.owner.avatarUrl} +
+
+
+ )}
- {webAppInfo.gitInfo && ( -
-
-
- Git Info: -
-
-
Branch: {webAppInfo.gitInfo.branch}
-
Commit: {webAppInfo.gitInfo.commit}
-
- Commit Time: {webAppInfo.gitInfo.commitTime} -
-
Author: {webAppInfo.gitInfo.author}
-
- Remote URL: {webAppInfo.gitInfo.remoteUrl} -
-
-
- )} - {webAppInfo.repoInfo && ( -
-
-
- GitHub Repository: -
-
-
Name: {webAppInfo.repoInfo.name}
-
- Full Name: {webAppInfo.repoInfo.fullName} -
-
- Description: {webAppInfo.repoInfo.description} -
-
Stars: {webAppInfo.repoInfo.stars}
-
Forks: {webAppInfo.repoInfo.forks}
-
- Open Issues: {webAppInfo.repoInfo.openIssues} -
-
- Default Branch: {webAppInfo.repoInfo.defaultBranch} -
-
- Last Update: {webAppInfo.repoInfo.lastUpdate} -
-
- Owner: {webAppInfo.repoInfo.owner.login} -
-
- Avatar URL: {webAppInfo.repoInfo.owner.avatarUrl} -
-
-
- )} -
+ ) : ( +
+ {loading.webAppInfo ? 'Loading webapp information...' : 'No webapp information available'} +
+ )}
- ) : ( -
- {loading.webAppInfo ? 'Loading webapp information...' : 'No webapp information available'} -
- )} -
+ + {/* Error Check */} -
-
-
-

Error Check

-
-
-
- Checks for: -
    -
  • Unhandled JavaScript errors
  • -
  • Unhandled Promise rejections
  • -
  • Runtime exceptions
  • -
  • Network errors
  • -
+ setOpenSections((prev) => ({ ...prev, errors: open }))} + className="w-full" + > + +
+
+
+

Error Check

+ {errorLog.errors.length > 0 && ( + + {errorLog.errors.length} Errors + + )} +
+
-
- Last Check: - - {loading.errors - ? 'Checking...' - : errorLog.lastCheck - ? `Last checked ${new Date(errorLog.lastCheck).toLocaleString()} (${errorLog.errors.length} errors found)` - : 'Click to check for errors'} - -
- {errorLog.errors.length > 0 && ( -
-
Recent Errors:
-
- {errorLog.errors.slice(0, 3).map((error, index) => ( -
- {error.type === 'error' && `${error.message} (${error.filename}:${error.lineNumber})`} - {error.type === 'unhandledRejection' && `Unhandled Promise Rejection: ${error.reason}`} - {error.type === 'networkError' && `Network Error: Failed to load ${error.resource}`} -
- ))} - {errorLog.errors.length > 3 && ( -
- And {errorLog.errors.length - 3} more errors... + + + +
+ +
+
+ Checks for: +
    +
  • Unhandled JavaScript errors
  • +
  • Unhandled Promise rejections
  • +
  • Runtime exceptions
  • +
  • Network errors
  • +
+
+
+ Last Check: + + {loading.errors + ? 'Checking...' + : errorLog.lastCheck + ? `Last checked ${new Date(errorLog.lastCheck).toLocaleString()} (${errorLog.errors.length} errors found)` + : 'Click to check for errors'} + +
+ {errorLog.errors.length > 0 && ( +
+
Recent Errors:
+
+ {errorLog.errors.slice(0, 3).map((error, index) => ( +
+ {error.type === 'error' && `${error.message} (${error.filename}:${error.lineNumber})`} + {error.type === 'unhandledRejection' && `Unhandled Promise Rejection: ${error.reason}`} + {error.type === 'networkError' && `Network Error: Failed to load ${error.resource}`} +
+ ))} + {errorLog.errors.length > 3 && ( +
+ And {errorLog.errors.length - 3} more errors... +
+ )} +
)}
-
- )} -
-
+ +
+ +
); } diff --git a/app/components/ui/Badge.tsx b/app/components/ui/Badge.tsx new file mode 100644 index 0000000..c57afd9 --- /dev/null +++ b/app/components/ui/Badge.tsx @@ -0,0 +1,33 @@ +'use client'; + +import * as React from 'react'; +import { cva, type VariantProps } from 'class-variance-authority'; +import { cn } from '~/lib/utils'; + +const badgeVariants = cva( + 'inline-flex items-center rounded-md px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2', + { + variants: { + variant: { + default: 'border-transparent bg-primary text-primary-foreground', + secondary: 'border-transparent bg-secondary text-secondary-foreground', + destructive: 'border-transparent bg-red-500/10 text-red-500 dark:bg-red-900/30', + outline: 'text-foreground', + }, + }, + defaultVariants: { + variant: 'default', + }, + }, +); + +interface BadgeProps extends React.HTMLAttributes, VariantProps { + variant?: 'default' | 'secondary' | 'destructive' | 'outline'; +} + +function Badge({ className, variant = 'default', ...props }: BadgeProps) { + return
; +} + +export { Badge, badgeVariants }; +export type { BadgeProps }; diff --git a/app/components/ui/Collapsible.tsx b/app/components/ui/Collapsible.tsx new file mode 100644 index 0000000..b2f7daa --- /dev/null +++ b/app/components/ui/Collapsible.tsx @@ -0,0 +1,10 @@ +'use client'; + +import * as React from 'react'; +import * as CollapsiblePrimitive from '@radix-ui/react-collapsible'; + +const Collapsible = CollapsiblePrimitive.Root; +const CollapsibleTrigger = CollapsiblePrimitive.Trigger; +const CollapsibleContent = CollapsiblePrimitive.Content; + +export { Collapsible, CollapsibleTrigger, CollapsibleContent }; diff --git a/app/components/ui/Progress.tsx b/app/components/ui/Progress.tsx new file mode 100644 index 0000000..494add5 --- /dev/null +++ b/app/components/ui/Progress.tsx @@ -0,0 +1,22 @@ +import * as React from 'react'; +import * as ProgressPrimitive from '@radix-ui/react-progress'; +import { cn } from '~/lib/utils'; + +const Progress = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, value, ...props }, ref) => ( + + + +)); +Progress.displayName = ProgressPrimitive.Root.displayName; + +export { Progress }; diff --git a/app/components/ui/ScrollArea.tsx b/app/components/ui/ScrollArea.tsx new file mode 100644 index 0000000..9d57b7a --- /dev/null +++ b/app/components/ui/ScrollArea.tsx @@ -0,0 +1,39 @@ +'use client'; + +import * as React from 'react'; +import * as ScrollAreaPrimitive from '@radix-ui/react-scroll-area'; +import { cn } from '~/lib/utils'; + +const ScrollArea = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + {children} + + + +)); +ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName; + +const ScrollBar = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, orientation = 'vertical', ...props }, ref) => ( + + + +)); +ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName; + +export { ScrollArea, ScrollBar }; diff --git a/app/lib/utils.ts b/app/lib/utils.ts new file mode 100644 index 0000000..9ad0df4 --- /dev/null +++ b/app/lib/utils.ts @@ -0,0 +1,6 @@ +import { type ClassValue, clsx } from 'clsx'; +import { twMerge } from 'tailwind-merge'; + +export function cn(...inputs: ClassValue[]) { + return twMerge(clsx(inputs)); +} diff --git a/package.json b/package.json index 099ae2a..bdf3215 100644 --- a/package.json +++ b/package.json @@ -59,11 +59,13 @@ "@octokit/rest": "^21.0.2", "@octokit/types": "^13.6.2", "@openrouter/ai-sdk-provider": "^0.0.5", - "@phosphor-icons/react": "^2.1.7", + "@radix-ui/react-collapsible": "^1.0.3", "@radix-ui/react-context-menu": "^2.2.2", "@radix-ui/react-dialog": "^1.1.2", "@radix-ui/react-dropdown-menu": "^2.1.2", - "@radix-ui/react-popover": "^1.1.4", + "@radix-ui/react-popover": "^1.1.5", + "@radix-ui/react-progress": "^1.0.3", + "@radix-ui/react-scroll-area": "^1.2.2", "@radix-ui/react-separator": "^1.1.0", "@radix-ui/react-switch": "^1.1.1", "@radix-ui/react-tooltip": "^1.1.4", @@ -80,6 +82,7 @@ "ai": "^4.0.13", "chalk": "^5.4.1", "chart.js": "^4.4.7", + "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "date-fns": "^3.6.0", "diff": "^5.2.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a9cc196..9eb1b1f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -98,9 +98,9 @@ importers: '@openrouter/ai-sdk-provider': specifier: ^0.0.5 version: 0.0.5(zod@3.23.8) - '@phosphor-icons/react': - specifier: ^2.1.7 - version: 2.1.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-collapsible': + specifier: ^1.0.3 + version: 1.1.2(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-context-menu': specifier: ^2.2.2 version: 2.2.2(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -111,8 +111,14 @@ importers: specifier: ^2.1.2 version: 2.1.2(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-popover': - specifier: ^1.1.4 - version: 1.1.4(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + specifier: ^1.1.5 + version: 1.1.5(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-progress': + specifier: ^1.0.3 + version: 1.1.1(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-scroll-area': + specifier: ^1.2.2 + version: 1.2.2(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-separator': specifier: ^1.1.0 version: 1.1.0(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -161,6 +167,9 @@ importers: chart.js: specifier: ^4.4.7 version: 4.4.7 + class-variance-authority: + specifier: ^0.7.1 + version: 0.7.1 clsx: specifier: ^2.1.1 version: 2.1.1 @@ -1872,13 +1881,6 @@ packages: resolution: {integrity: sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==} engines: {node: '>=8.0.0'} - '@phosphor-icons/react@2.1.7': - resolution: {integrity: sha512-g2e2eVAn1XG2a+LI09QU3IORLhnFNAFkNbo2iwbX6NOKSLOwvEMmTa7CgOzEbgNWR47z8i8kwjdvYZ5fkGx1mQ==} - engines: {node: '>=10'} - peerDependencies: - react: '>= 16.8' - react-dom: '>= 16.8' - '@pkgjs/parseargs@0.11.0': resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} engines: {node: '>=14'} @@ -1890,6 +1892,9 @@ packages: '@polka/url@1.0.0-next.28': resolution: {integrity: sha512-8LduaNlMZGwdZ6qWrKlfa+2M4gahzFkprZiAt2TF8uS0qQgBizKXpXURqvTJ4WtmupWxaLqjRb2UCTe72mu+Aw==} + '@radix-ui/number@1.1.0': + resolution: {integrity: sha512-V3gRzhVNU1ldS5XhAPTom1fOIo4ccrjjJgmE+LI2h/WaFpHmx0MQApT+KZHnx8abG6Avtfcz4WoEciMnpFT3HQ==} + '@radix-ui/primitive@1.1.0': resolution: {integrity: sha512-4Z8dn6Upk0qk4P74xBhZ6Hd/w0mPEzOOLxy4xiPXOXqjF7jZS0VAKk7/x/H6FyY2zCkYJqePf1G5KmkmNJ4RBA==} @@ -1922,6 +1927,19 @@ packages: '@types/react-dom': optional: true + '@radix-ui/react-collapsible@1.1.2': + resolution: {integrity: sha512-PliMB63vxz7vggcyq0IxNYk8vGDrLXVWw4+W4B8YnwI1s18x7YZYqlG9PLX7XxAJUi0g2DxP4XKJMFHh/iVh9A==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + '@radix-ui/react-collection@1.1.0': resolution: {integrity: sha512-GZsZslMJEyo1VKm5L1ZJY8tGDxZNPAoUeQUIbKeJfoi7Q4kmig5AsgLMYYuyYbfjd8fBmFORAIwYAkXMnXZgZw==} peerDependencies: @@ -2019,8 +2037,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-dismissable-layer@1.1.3': - resolution: {integrity: sha512-onrWn/72lQoEucDmJnr8uczSNTujT0vJnA/X5+3AkChVPowr8n1yvIKIabhWyMQeMvvmdpsvcyDqx3X1LEXCPg==} + '@radix-ui/react-dismissable-layer@1.1.4': + resolution: {integrity: sha512-XDUI0IVYVSwjMXxM6P4Dfti7AH+Y4oS/TB+sglZ/EXc7cqLwGAmp1NlMrcUjj7ks6R5WTZuWKv44FBbLpwU3sA==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -2102,8 +2120,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-popover@1.1.4': - resolution: {integrity: sha512-aUACAkXx8LaFymDma+HQVji7WhvEhpFJ7+qPz17Nf4lLZqtreGOFRiNQWQmhzp7kEWg9cOyyQJpdIMUMPc/CPw==} + '@radix-ui/react-popover@1.1.5': + resolution: {integrity: sha512-YXkTAftOIW2Bt3qKH8vYr6n9gCkVrvyvfiTObVjoHVTHnNj26rmvO87IKa3VgtgCjb8FAQ6qOjNViwl+9iIzlg==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -2219,6 +2237,19 @@ packages: '@types/react-dom': optional: true + '@radix-ui/react-progress@1.1.1': + resolution: {integrity: sha512-6diOawA84f/eMxFHcWut0aE1C2kyE9dOyCTQOMRR2C/qPiXz/X0SaiA/RLbapQaXUCmy0/hLMf9meSccD1N0pA==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + '@radix-ui/react-roving-focus@1.1.0': resolution: {integrity: sha512-EA6AMGeq9AEeQDeSH0aZgG198qkfHSbvWTf1HvoDmOB5bBG/qTxjYMWUKMnYiV6J/iP/J8MEFSuB2zRU2n7ODA==} peerDependencies: @@ -2232,6 +2263,19 @@ packages: '@types/react-dom': optional: true + '@radix-ui/react-scroll-area@1.2.2': + resolution: {integrity: sha512-EFI1N/S3YxZEW/lJ/H1jY3njlvTd8tBmgKEn4GHi51+aMm94i6NmAJstsm5cu3yJwYqYc93gpCPm21FeAbFk6g==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + '@radix-ui/react-separator@1.1.0': resolution: {integrity: sha512-3uBAs+egzvJBDZAzvb/n4NxxOYpnspmWxO2u5NbZ8Y6FM/NdrGSF9bop3Cf6F6C71z1rTSn8KV0Fo2ZVd79lGA==} peerDependencies: @@ -3430,6 +3474,9 @@ packages: resolution: {integrity: sha512-3Ek9H3X6pj5TgenXYtNWdaBon1tgYCaebd+XPg0keyjEbEfkD4KkmAxkQ/i1vYvxdcT5nscLBfq9VJRmCBcFSw==} engines: {node: '>= 0.10'} + class-variance-authority@0.7.1: + resolution: {integrity: sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==} + clean-git-ref@2.0.1: resolution: {integrity: sha512-bLSptAy2P0s6hU4PzuIMKmMJJSE6gLXGH1cntDu7bWJUksvuM+7ReOK61mozULErYvP6a15rnYl0zFDef+pyPw==} @@ -5590,8 +5637,8 @@ packages: '@types/react': optional: true - react-remove-scroll@2.6.2: - resolution: {integrity: sha512-KmONPx5fnlXYJQqC62Q+lwIeAk64ws/cUw6omIumRzMRPqgnYqhSSti99nbj0Ry13bv7dF+BKn7NB+OqkdZGTw==} + react-remove-scroll@2.6.3: + resolution: {integrity: sha512-pnAi91oOk8g8ABQKGF5/M9qxmmOPxaAnopyTHYfqYEwJhyFrbbBtHuSgtKEoH0jpcxx5o3hXqH1mNd9/Oi+8iQ==} engines: {node: '>=10'} peerDependencies: '@types/react': '*' @@ -6488,6 +6535,16 @@ packages: '@types/react': optional: true + use-sidecar@1.1.3: + resolution: {integrity: sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==} + engines: {node: '>=10'} + peerDependencies: + '@types/react': '*' + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + use-sync-external-store@1.2.2: resolution: {integrity: sha512-PElTlVMwpblvbNqQ82d2n6RjStvdSoNe9FG28kNfz3WiXilJm4DdNkEzRhCZuIDwY8U08WVihhGR5iRqAwfDiw==} peerDependencies: @@ -8476,11 +8533,6 @@ snapshots: '@opentelemetry/api@1.9.0': {} - '@phosphor-icons/react@2.1.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - '@pkgjs/parseargs@0.11.0': optional: true @@ -8488,6 +8540,8 @@ snapshots: '@polka/url@1.0.0-next.28': {} + '@radix-ui/number@1.1.0': {} + '@radix-ui/primitive@1.1.0': {} '@radix-ui/primitive@1.1.1': {} @@ -8510,6 +8564,22 @@ snapshots: '@types/react': 18.3.12 '@types/react-dom': 18.3.1 + '@radix-ui/react-collapsible@1.1.2(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/primitive': 1.1.1 + '@radix-ui/react-compose-refs': 1.1.1(@types/react@18.3.12)(react@18.3.1) + '@radix-ui/react-context': 1.1.1(@types/react@18.3.12)(react@18.3.1) + '@radix-ui/react-id': 1.1.0(@types/react@18.3.12)(react@18.3.1) + '@radix-ui/react-presence': 1.1.2(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.12)(react@18.3.1) + '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.12)(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.12 + '@types/react-dom': 18.3.1 + '@radix-ui/react-collection@1.1.0(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.12)(react@18.3.1) @@ -8601,7 +8671,7 @@ snapshots: '@types/react': 18.3.12 '@types/react-dom': 18.3.1 - '@radix-ui/react-dismissable-layer@1.1.3(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-dismissable-layer@1.1.4(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/primitive': 1.1.1 '@radix-ui/react-compose-refs': 1.1.1(@types/react@18.3.12)(react@18.3.1) @@ -8690,12 +8760,12 @@ snapshots: '@types/react': 18.3.12 '@types/react-dom': 18.3.1 - '@radix-ui/react-popover@1.1.4(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-popover@1.1.5(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/primitive': 1.1.1 '@radix-ui/react-compose-refs': 1.1.1(@types/react@18.3.12)(react@18.3.1) '@radix-ui/react-context': 1.1.1(@types/react@18.3.12)(react@18.3.1) - '@radix-ui/react-dismissable-layer': 1.1.3(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-dismissable-layer': 1.1.4(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-focus-guards': 1.1.1(@types/react@18.3.12)(react@18.3.1) '@radix-ui/react-focus-scope': 1.1.1(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-id': 1.1.0(@types/react@18.3.12)(react@18.3.1) @@ -8708,7 +8778,7 @@ snapshots: aria-hidden: 1.2.4 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - react-remove-scroll: 2.6.2(@types/react@18.3.12)(react@18.3.1) + react-remove-scroll: 2.6.3(@types/react@18.3.12)(react@18.3.1) optionalDependencies: '@types/react': 18.3.12 '@types/react-dom': 18.3.1 @@ -8807,6 +8877,16 @@ snapshots: '@types/react': 18.3.12 '@types/react-dom': 18.3.1 + '@radix-ui/react-progress@1.1.1(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/react-context': 1.1.1(@types/react@18.3.12)(react@18.3.1) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.12 + '@types/react-dom': 18.3.1 + '@radix-ui/react-roving-focus@1.1.0(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/primitive': 1.1.0 @@ -8824,6 +8904,23 @@ snapshots: '@types/react': 18.3.12 '@types/react-dom': 18.3.1 + '@radix-ui/react-scroll-area@1.2.2(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/number': 1.1.0 + '@radix-ui/primitive': 1.1.1 + '@radix-ui/react-compose-refs': 1.1.1(@types/react@18.3.12)(react@18.3.1) + '@radix-ui/react-context': 1.1.1(@types/react@18.3.12)(react@18.3.1) + '@radix-ui/react-direction': 1.1.0(@types/react@18.3.12)(react@18.3.1) + '@radix-ui/react-presence': 1.1.2(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.12)(react@18.3.1) + '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.12)(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.12 + '@types/react-dom': 18.3.1 + '@radix-ui/react-separator@1.1.0(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -10360,6 +10457,10 @@ snapshots: inherits: 2.0.4 safe-buffer: 5.2.1 + class-variance-authority@0.7.1: + dependencies: + clsx: 2.1.1 + clean-git-ref@2.0.1: {} clean-stack@2.2.0: {} @@ -13075,14 +13176,14 @@ snapshots: optionalDependencies: '@types/react': 18.3.12 - react-remove-scroll@2.6.2(@types/react@18.3.12)(react@18.3.1): + react-remove-scroll@2.6.3(@types/react@18.3.12)(react@18.3.1): dependencies: react: 18.3.1 react-remove-scroll-bar: 2.3.8(@types/react@18.3.12)(react@18.3.1) - react-style-singleton: 2.2.1(@types/react@18.3.12)(react@18.3.1) + react-style-singleton: 2.2.3(@types/react@18.3.12)(react@18.3.1) tslib: 2.8.1 use-callback-ref: 1.3.3(@types/react@18.3.12)(react@18.3.1) - use-sidecar: 1.1.2(@types/react@18.3.12)(react@18.3.1) + use-sidecar: 1.1.3(@types/react@18.3.12)(react@18.3.1) optionalDependencies: '@types/react': 18.3.12 @@ -14062,6 +14163,14 @@ snapshots: optionalDependencies: '@types/react': 18.3.12 + use-sidecar@1.1.3(@types/react@18.3.12)(react@18.3.1): + dependencies: + detect-node-es: 1.1.0 + react: 18.3.1 + tslib: 2.8.1 + optionalDependencies: + '@types/react': 18.3.12 + use-sync-external-store@1.2.2(react@18.3.1): dependencies: react: 18.3.1