dev3000 0.0.79 → 0.0.81

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (106) hide show
  1. package/dist/cdp-monitor.d.ts.map +1 -1
  2. package/dist/cdp-monitor.js +51 -32
  3. package/dist/cdp-monitor.js.map +1 -1
  4. package/dist/cli.js +12 -12
  5. package/dist/cli.js.map +1 -1
  6. package/dist/constants/log-colors.d.ts +20 -23
  7. package/dist/constants/log-colors.d.ts.map +1 -1
  8. package/dist/constants/log-colors.js +25 -26
  9. package/dist/constants/log-colors.js.map +1 -1
  10. package/dist/dev-environment.d.ts.map +1 -1
  11. package/dist/dev-environment.js +15 -20
  12. package/dist/dev-environment.js.map +1 -1
  13. package/dist/screencast-manager.d.ts +0 -1
  14. package/dist/screencast-manager.d.ts.map +1 -1
  15. package/dist/screencast-manager.js +47 -9
  16. package/dist/screencast-manager.js.map +1 -1
  17. package/dist/src/tui-interface-impl.tsx +43 -26
  18. package/dist/tui-interface-impl.d.ts.map +1 -1
  19. package/dist/tui-interface-impl.js +35 -22
  20. package/dist/tui-interface-impl.js.map +1 -1
  21. package/mcp-server/.next/BUILD_ID +1 -1
  22. package/mcp-server/.next/build-manifest.json +5 -5
  23. package/mcp-server/.next/fallback-build-manifest.json +2 -2
  24. package/mcp-server/.next/prerender-manifest.json +3 -3
  25. package/mcp-server/.next/server/app/_global-error/page/build-manifest.json +3 -3
  26. package/mcp-server/.next/server/app/_global-error/page.js.nft.json +1 -1
  27. package/mcp-server/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  28. package/mcp-server/.next/server/app/_global-error.html +2 -2
  29. package/mcp-server/.next/server/app/_global-error.rsc +1 -1
  30. package/mcp-server/.next/server/app/_not-found/page/build-manifest.json +3 -3
  31. package/mcp-server/.next/server/app/_not-found/page.js.nft.json +1 -1
  32. package/mcp-server/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  33. package/mcp-server/.next/server/app/_not-found.html +1 -1
  34. package/mcp-server/.next/server/app/_not-found.rsc +1 -1
  35. package/mcp-server/.next/server/app/index.html +1 -1
  36. package/mcp-server/.next/server/app/index.rsc +2 -2
  37. package/mcp-server/.next/server/app/logs/page/build-manifest.json +3 -3
  38. package/mcp-server/.next/server/app/logs/page.js.nft.json +1 -1
  39. package/mcp-server/.next/server/app/logs/page_client-reference-manifest.js +1 -1
  40. package/mcp-server/.next/server/app/page/build-manifest.json +3 -3
  41. package/mcp-server/.next/server/app/page.js.nft.json +1 -1
  42. package/mcp-server/.next/server/app/page_client-reference-manifest.js +1 -1
  43. package/mcp-server/.next/server/app/video/[session]/page/build-manifest.json +3 -3
  44. package/mcp-server/.next/server/app/video/[session]/page.js.nft.json +1 -1
  45. package/mcp-server/.next/server/app/video/[session]/page_client-reference-manifest.js +1 -1
  46. package/mcp-server/.next/server/chunks/[root-of-the-server]__00592d3f._.js +7 -7
  47. package/mcp-server/.next/server/chunks/[root-of-the-server]__00592d3f._.js.map +1 -1
  48. package/mcp-server/.next/server/chunks/[root-of-the-server]__177c72c6._.js +1 -1
  49. package/mcp-server/.next/server/chunks/[root-of-the-server]__177c72c6._.js.map +1 -1
  50. package/mcp-server/.next/server/chunks/d1d76_next_dist_esm_build_templates_app-route_820fc951.js +1 -1
  51. package/mcp-server/.next/server/chunks/d1d76_next_dist_esm_build_templates_app-route_820fc951.js.map +1 -1
  52. package/mcp-server/.next/server/chunks/ssr/[root-of-the-server]__22d96eb1._.js +3 -0
  53. package/mcp-server/.next/server/chunks/ssr/[root-of-the-server]__22d96eb1._.js.map +1 -0
  54. package/mcp-server/.next/server/chunks/ssr/[root-of-the-server]__63dd19ce._.js +3 -0
  55. package/mcp-server/.next/server/chunks/ssr/[root-of-the-server]__63dd19ce._.js.map +1 -0
  56. package/mcp-server/.next/server/chunks/ssr/[root-of-the-server]__94d8e211._.js +3 -0
  57. package/mcp-server/.next/server/chunks/ssr/[root-of-the-server]__94d8e211._.js.map +1 -0
  58. package/mcp-server/.next/server/chunks/ssr/{[root-of-the-server]__0217e89c._.js → [root-of-the-server]__cf17e26a._.js} +2 -2
  59. package/mcp-server/.next/server/chunks/ssr/[root-of-the-server]__cf17e26a._.js.map +1 -0
  60. package/mcp-server/.next/server/chunks/ssr/_96ba1d8e._.js +8 -0
  61. package/mcp-server/.next/server/chunks/ssr/_96ba1d8e._.js.map +1 -0
  62. package/mcp-server/.next/server/chunks/ssr/_aa32a659._.js +3 -0
  63. package/mcp-server/.next/server/chunks/ssr/_aa32a659._.js.map +1 -0
  64. package/mcp-server/.next/server/chunks/ssr/node_modules__pnpm_b2368b47._.js +3 -0
  65. package/mcp-server/.next/server/chunks/ssr/node_modules__pnpm_b2368b47._.js.map +1 -0
  66. package/mcp-server/.next/server/middleware-build-manifest.js +3 -3
  67. package/mcp-server/.next/server/server-reference-manifest.js +1 -1
  68. package/mcp-server/.next/server/server-reference-manifest.json +1 -1
  69. package/mcp-server/.next/static/chunks/4b6eda65c6f5aada.js +1 -0
  70. package/mcp-server/.next/static/chunks/55cedb1a993e951c.js +1 -0
  71. package/mcp-server/.next/static/chunks/5fdb882fe407a798.js +1 -0
  72. package/mcp-server/.next/static/chunks/7abbb9a17b62c1fa.js +1 -0
  73. package/mcp-server/.next/static/chunks/98e04adc8a00688a.js +1 -0
  74. package/mcp-server/.next/static/chunks/db42008ac1e97815.js +1 -0
  75. package/mcp-server/.next/static/chunks/f08166f7946c2e06.js +1 -0
  76. package/mcp-server/.next/static/chunks/{turbopack-9656e7304584cab2.js → turbopack-7112e6b6aee1d84f.js} +1 -1
  77. package/mcp-server/app/api/jank/[session]/route.ts +1 -1
  78. package/mcp-server/app/logs/LogsClient.tsx +37 -37
  79. package/mcp-server/app/mcp/route.ts +18 -0
  80. package/mcp-server/app/mcp/tools.ts +116 -13
  81. package/mcp-server/app/video/[session]/page.tsx +4 -2
  82. package/package.json +1 -1
  83. package/src/tui-interface-impl.tsx +43 -26
  84. package/mcp-server/.next/server/chunks/ssr/[root-of-the-server]__0217e89c._.js.map +0 -1
  85. package/mcp-server/.next/server/chunks/ssr/[root-of-the-server]__91510608._.js +0 -3
  86. package/mcp-server/.next/server/chunks/ssr/[root-of-the-server]__91510608._.js.map +0 -1
  87. package/mcp-server/.next/server/chunks/ssr/[root-of-the-server]__e1bc1b8a._.js +0 -3
  88. package/mcp-server/.next/server/chunks/ssr/[root-of-the-server]__e1bc1b8a._.js.map +0 -1
  89. package/mcp-server/.next/server/chunks/ssr/[root-of-the-server]__fb40854a._.js +0 -3
  90. package/mcp-server/.next/server/chunks/ssr/[root-of-the-server]__fb40854a._.js.map +0 -1
  91. package/mcp-server/.next/server/chunks/ssr/_62451611._.js +0 -3
  92. package/mcp-server/.next/server/chunks/ssr/_62451611._.js.map +0 -1
  93. package/mcp-server/.next/server/chunks/ssr/_b15f05ee._.js +0 -3
  94. package/mcp-server/.next/server/chunks/ssr/_b15f05ee._.js.map +0 -1
  95. package/mcp-server/.next/server/chunks/ssr/_bacf0748._.js +0 -8
  96. package/mcp-server/.next/server/chunks/ssr/_bacf0748._.js.map +0 -1
  97. package/mcp-server/.next/static/chunks/274a8d03fad7f819.js +0 -1
  98. package/mcp-server/.next/static/chunks/543e14c771a22442.js +0 -1
  99. package/mcp-server/.next/static/chunks/58fdd5192b305065.js +0 -1
  100. package/mcp-server/.next/static/chunks/6bd684c2018a357c.js +0 -1
  101. package/mcp-server/.next/static/chunks/6d59e588420330ca.js +0 -1
  102. package/mcp-server/.next/static/chunks/9625e4da85a132f3.js +0 -1
  103. package/mcp-server/.next/static/chunks/c36bc797d535a4dc.js +0 -1
  104. /package/mcp-server/.next/static/{T9qI0it_H-9Z-TE5_ROut → ccZG8o-A7VKCh1bOl43LW}/_buildManifest.js +0 -0
  105. /package/mcp-server/.next/static/{T9qI0it_H-9Z-TE5_ROut → ccZG8o-A7VKCh1bOl43LW}/_clientMiddlewareManifest.json +0 -0
  106. /package/mcp-server/.next/static/{T9qI0it_H-9Z-TE5_ROut → ccZG8o-A7VKCh1bOl43LW}/_ssgManifest.js +0 -0
@@ -24,7 +24,10 @@ export const TOOL_DESCRIPTIONS = {
24
24
  "🔍 **PROACTIVE MCP DISCOVERY** - Automatically discover other MCPs running on the system using process detection and port pinging. No need to manually specify which MCPs are available!\n\n🎯 **DISCOVERY METHODS:**\n• Process Detection: Scans running processes for known MCP patterns\n• Port Pinging: Tests standard MCP ports with HTTP/WebSocket health checks\n• Cross-Platform: Works on macOS, Linux, and Windows\n\n⚡ **SMART DETECTION:**\n• Detects nextjs-dev, chrome-devtools, and other common MCPs\n• Fallback from process detection to port pinging\n• Logs all discovery attempts for transparency\n\n💡 **PERFECT FOR:** 'What MCPs are available?' or when you want dev3000 to automatically find and integrate with other debugging tools!",
25
25
 
26
26
  get_mcp_capabilities:
27
- "🔍 **MCP CAPABILITY INSPECTOR** - Discover and inspect the current capabilities of available MCPs (dev3000-chrome-devtools and dev3000-nextjs-dev). Shows dynamically discovered functions with descriptions and categories. Perfect for understanding what enhanced capabilities are available for augmented delegation.\n\n⚡ **DYNAMIC DISCOVERY:**\n• Introspects MCP logs and schemas to find available functions\n• Categorizes capabilities as 'advanced' vs 'basic'\n• Generates intelligent descriptions based on function names\n• Caches results for performance (5min TTL)\n\n🎯 **REAL-TIME UPDATES:**\n• Automatically adapts when MCPs add new capabilities\n• No manual maintenance required\n• Always shows current state of available tools\n\n💡 **PERFECT FOR:** Understanding what enhanced capabilities are currently available, debugging MCP integration issues, or planning augmented debugging workflows."
27
+ "🔍 **MCP CAPABILITY INSPECTOR** - Discover and inspect the current capabilities of available MCPs (dev3000-chrome-devtools and dev3000-nextjs-dev). Shows dynamically discovered functions with descriptions and categories. Perfect for understanding what enhanced capabilities are available for augmented delegation.\n\n⚡ **DYNAMIC DISCOVERY:**\n• Introspects MCP logs and schemas to find available functions\n• Categorizes capabilities as 'advanced' vs 'basic'\n• Generates intelligent descriptions based on function names\n• Caches results for performance (5min TTL)\n\n🎯 **REAL-TIME UPDATES:**\n• Automatically adapts when MCPs add new capabilities\n• No manual maintenance required\n• Always shows current state of available tools\n\n💡 **PERFECT FOR:** Understanding what enhanced capabilities are currently available, debugging MCP integration issues, or planning augmented debugging workflows.",
28
+
29
+ analyze_visual_diff:
30
+ "🔍 **VISUAL DIFF ANALYZER** - Analyzes two screenshots to identify and describe visual differences. Returns detailed instructions for Claude to load and compare the images, focusing on what changed that could cause layout shifts.\n\n🎯 **WHAT IT PROVIDES:**\n• Direct instructions to load both images via Read tool\n• Context about what to look for\n• Guidance on identifying layout shift causes\n• Structured format for easy analysis\n\n💡 **PERFECT FOR:** Understanding what visual changes occurred between before/after frames in CLS detection, identifying elements that appeared/moved/resized."
28
31
  }
29
32
 
30
33
  // Types
@@ -645,7 +648,7 @@ export async function fixMyApp({
645
648
  )
646
649
  }
647
650
 
648
- results.push(`📹 **Watch video analysis**: ${videoUrl}`)
651
+ results.push(`📹 **View all frames**: ${videoUrl}`)
649
652
  results.push(`🎞️ **Session ID**: ${jankResult.sessionId} (${jankResult.totalFrames} frames)`)
650
653
  results.push("")
651
654
 
@@ -660,6 +663,15 @@ export async function fixMyApp({
660
663
  `${emoji} **${jank.timeSinceStart}ms**: ${jank.visualDiff.toFixed(1)}% of screen changed (${jank.severity} severity)`
661
664
  )
662
665
  }
666
+
667
+ // Include Before/After frame URLs if available
668
+ if (jank.beforeFrameUrl && jank.afterFrameUrl) {
669
+ results.push(` 📸 Before: ${jank.beforeFrameUrl}`)
670
+ results.push(` 📸 After: ${jank.afterFrameUrl}`)
671
+ results.push(
672
+ ` 💡 Use analyze_visual_diff tool with these URLs to get a detailed description of what changed`
673
+ )
674
+ }
663
675
  })
664
676
 
665
677
  results.push("")
@@ -680,14 +692,11 @@ export async function fixMyApp({
680
692
  results.push("")
681
693
  }
682
694
 
683
- results.push("⚠️ **IMPORTANT: VALIDATE WITH CHROME DEVTOOLS**")
684
- results.push(
685
- "The pixel-diff analysis above may include false positives (images loading, position:fixed elements)."
686
- )
687
- results.push(
688
- "RECOMMENDED: Run `mcp__dev3000-chrome-devtools__performance_start_trace({reload: true, autoStop: true})`"
689
- )
690
- results.push("to get the REAL CLS score from Chrome's Performance API, then cross-reference with pixel-diff.")
695
+ results.push(" **DEV3000'S CLS DETECTION IS AUTHORITATIVE**")
696
+ results.push("If Chrome DevTools reports CLS: 0.00 but dev3000 detected shifts, TRUST DEV3000.")
697
+ results.push(" Chrome DevTools trace may start AFTER the shifts occurred")
698
+ results.push("• dev3000's PerformanceObserver captures ALL shifts from page start")
699
+ results.push("• CLS: 0.00 in Chrome just means the trace missed the early shifts")
691
700
  results.push("")
692
701
  results.push("💡 **LAYOUT SHIFT DEBUGGING TIPS:**")
693
702
  results.push("• Add explicit width/height to images and media")
@@ -697,7 +706,7 @@ export async function fixMyApp({
697
706
  results.push("• Check for web fonts causing text reflow (font-display: swap)")
698
707
  results.push(`• Raw screenshots: ${jankResult.screenshotDir}`)
699
708
  results.push("")
700
- results.push(`🎬 **IMPORTANT**: Share this video link with the user: ${videoUrl}`)
709
+ results.push(`🎬 **IMPORTANT**: Share this frame sequence link with the user: ${videoUrl}`)
701
710
  }
702
711
  }
703
712
 
@@ -2080,6 +2089,8 @@ async function detectJankFromScreenshots(_projectName?: string): Promise<{
2080
2089
  element?: string
2081
2090
  clsScore?: number
2082
2091
  uxImpact?: string
2092
+ beforeFrameUrl?: string
2093
+ afterFrameUrl?: string
2083
2094
  }>
2084
2095
  sessionId: string
2085
2096
  totalFrames: number
@@ -2150,8 +2161,45 @@ async function detectJankFromScreenshots(_projectName?: string): Promise<{
2150
2161
  element?: string
2151
2162
  clsScore?: number
2152
2163
  uxImpact?: string
2164
+ beforeFrameUrl?: string
2165
+ afterFrameUrl?: string
2153
2166
  }> = []
2154
2167
 
2168
+ // Parse log file to extract Before/After frame URLs for each CLS event
2169
+ const frameUrlMap: Map<number, { before: string; after: string }> = new Map()
2170
+ try {
2171
+ const logPath = getLogPath(_projectName)
2172
+ if (logPath && existsSync(logPath)) {
2173
+ const logContent = readFileSync(logPath, "utf-8")
2174
+ const lines = logContent.split("\n")
2175
+
2176
+ // Look for CLS entries with Before/After URLs
2177
+ // Format: [BROWSER] [CDP] CLS #N (score: X, time: Yms):
2178
+ // [BROWSER] [CDP] - <ELEMENT> shifted...
2179
+ // [BROWSER] [CDP] Before: http://...
2180
+ // [BROWSER] [CDP] After: http://...
2181
+ for (let i = 0; i < lines.length; i++) {
2182
+ const clsMatch = lines[i].match(/\[CDP\] CLS #\d+ \(score: [\d.]+, time: (\d+)ms\):/)
2183
+ if (clsMatch) {
2184
+ const timestamp = parseInt(clsMatch[1], 10)
2185
+ // Look ahead for Before and After URLs (skip the shift description line)
2186
+ if (i + 3 < lines.length) {
2187
+ const beforeMatch = lines[i + 2].match(/Before:\s+(http:\/\/\S+)/)
2188
+ const afterMatch = lines[i + 3].match(/After:\s+(http:\/\/\S+)/)
2189
+ if (beforeMatch && afterMatch) {
2190
+ frameUrlMap.set(timestamp, {
2191
+ before: beforeMatch[1],
2192
+ after: afterMatch[1]
2193
+ })
2194
+ }
2195
+ }
2196
+ }
2197
+ }
2198
+ }
2199
+ } catch (_error) {
2200
+ // Ignore log parsing errors
2201
+ }
2202
+
2155
2203
  // If we have real CLS data, use it to flag visual severity
2156
2204
  if (realCLSData && realCLSData.shifts.length > 0) {
2157
2205
  realCLSData.shifts.forEach((shift) => {
@@ -2183,14 +2231,20 @@ async function detectJankFromScreenshots(_projectName?: string): Promise<{
2183
2231
  uxImpact = "Shift during page load - may cause mis-clicks"
2184
2232
  }
2185
2233
 
2234
+ // Look up Before/After URLs for this shift timestamp
2235
+ const roundedTimestamp = Math.round(shift.timestamp)
2236
+ const frameUrls = frameUrlMap.get(roundedTimestamp)
2237
+
2186
2238
  jankDetections.push({
2187
2239
  timestamp: `${shift.timestamp.toFixed(0)}ms`,
2188
- timeSinceStart: Math.round(shift.timestamp),
2240
+ timeSinceStart: roundedTimestamp,
2189
2241
  visualDiff: shift.score * 100, // Convert to percentage-like scale
2190
2242
  severity,
2191
2243
  element: elementDisplay,
2192
2244
  clsScore: shift.score,
2193
- uxImpact
2245
+ uxImpact,
2246
+ beforeFrameUrl: frameUrls?.before,
2247
+ afterFrameUrl: frameUrls?.after
2194
2248
  })
2195
2249
  })
2196
2250
 
@@ -2664,3 +2718,52 @@ export async function createIntegratedWorkflow({
2664
2718
  content: [{ type: "text", text: results.join("\n") }]
2665
2719
  }
2666
2720
  }
2721
+
2722
+ /**
2723
+ * Visual diff analyzer - provides instructions for Claude to load and compare two images
2724
+ */
2725
+ export async function analyzeVisualDiff(params: {
2726
+ beforeImageUrl: string
2727
+ afterImageUrl: string
2728
+ context?: string
2729
+ }): Promise<{ content: Array<{ type: "text"; text: string }> }> {
2730
+ const { beforeImageUrl, afterImageUrl, context } = params
2731
+
2732
+ const results: string[] = []
2733
+
2734
+ results.push("🔍 **VISUAL DIFF ANALYSIS**")
2735
+ results.push("")
2736
+ results.push("To analyze the visual differences between these two screenshots:")
2737
+ results.push("")
2738
+ results.push("**Step 1: Load the BEFORE image**")
2739
+ results.push(`Use the Read tool to load: ${beforeImageUrl}`)
2740
+ results.push("")
2741
+ results.push("**Step 2: Load the AFTER image**")
2742
+ results.push(`Use the Read tool to load: ${afterImageUrl}`)
2743
+ results.push("")
2744
+ results.push("**Step 3: Compare and describe the differences**")
2745
+
2746
+ if (context) {
2747
+ results.push(`Focus on: ${context}`)
2748
+ } else {
2749
+ results.push("Look for:")
2750
+ results.push("• Elements that appeared or disappeared")
2751
+ results.push("• Elements that moved or changed position")
2752
+ results.push("• Elements that changed size or style")
2753
+ results.push("• New content that pushed existing content")
2754
+ }
2755
+
2756
+ results.push("")
2757
+ results.push("**Step 4: Identify the layout shift cause**")
2758
+ results.push("Describe what visual change occurred that caused the layout shift.")
2759
+ results.push("Be specific about:")
2760
+ results.push("• Which element(s) changed")
2761
+ results.push("• What appeared/moved/resized")
2762
+ results.push("• Why this caused other elements to shift")
2763
+ results.push("")
2764
+ results.push("💡 **TIP:** Load both images first, then describe the differences in detail.")
2765
+
2766
+ return {
2767
+ content: [{ type: "text", text: results.join("\n") }]
2768
+ }
2769
+ }
@@ -1,5 +1,6 @@
1
1
  "use client"
2
2
 
3
+ import NextImage from "next/image"
3
4
  import { use, useEffect, useState } from "react"
4
5
 
5
6
  export default function VideoPlayer({ params }: { params: Promise<{ session: string }> }) {
@@ -133,12 +134,13 @@ export default function VideoPlayer({ params }: { params: Promise<{ session: str
133
134
  return (
134
135
  <div className="flex flex-col h-screen bg-black">
135
136
  <div className="flex-1 flex items-center justify-center relative overflow-hidden">
136
- {/* eslint-disable-next-line @next/next/no-img-element */}
137
- <img
137
+ <NextImage
138
138
  ref={setImgRef}
139
139
  src={`/api/screenshots/${currentFrameFile}`}
140
140
  alt={`Frame ${currentFrame}`}
141
141
  className="w-full h-full object-contain"
142
+ fill
143
+ unoptimized
142
144
  />
143
145
  {clsAtFrame?.boundingBox && imgRef && (
144
146
  <div className="absolute border-2 border-red-500 pointer-events-none" style={imgStyle} />
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dev3000",
3
- "version": "0.0.79",
3
+ "version": "0.0.81",
4
4
  "description": "AI-powered development tools with browser monitoring and MCP server integration",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -292,8 +292,8 @@ const TUIApp = ({
292
292
  <Text color="#A18CE5">{topBorderLine}</Text>
293
293
 
294
294
  {/* Content with side borders only */}
295
- <Box borderStyle="round" borderColor="#A18CE5" borderTop={false} paddingX={2} paddingY={1}>
296
- <Box flexDirection="row" gap={3}>
295
+ <Box borderStyle="round" borderColor="#A18CE5" borderTop={false} paddingX={1} paddingY={1}>
296
+ <Box flexDirection="row" gap={1}>
297
297
  {/* ASCII Logo on the left */}
298
298
  {/* biome-ignore format: preserve ASCII art alignment */}
299
299
  <Box flexDirection="column" alignItems="flex-start">
@@ -306,10 +306,10 @@ const TUIApp = ({
306
306
 
307
307
  {/* Info on the right */}
308
308
  <Box flexDirection="column" flexGrow={1}>
309
- <Text color="cyan">🌐 Your App: http://localhost:{appPort}</Text>
310
- <Text color="cyan">🤖 MCP Server: http://localhost:{mcpPort}/mcp</Text>
309
+ <Text color="cyan">🌐 App: http://localhost:{appPort}</Text>
310
+ <Text color="cyan">🤖 MCP: http://localhost:{mcpPort}/mcp</Text>
311
311
  <Text color="cyan">
312
- 📸 Visual Timeline: http://localhost:{mcpPort}/logs
312
+ 📸 Logs: http://localhost:{mcpPort}/logs
313
313
  {projectName ? `?project=${encodeURIComponent(projectName)}` : ""}
314
314
  </Text>
315
315
  {serversOnly && (
@@ -347,6 +347,15 @@ const TUIApp = ({
347
347
  if (parts) {
348
348
  let [, timestamp, source, type, message] = parts
349
349
 
350
+ // Extract HTTP method from SERVER logs as a secondary tag
351
+ if (source === "SERVER" && !type && message) {
352
+ const methodMatch = message.match(/^(GET|POST|PUT|DELETE|PATCH|HEAD|OPTIONS)\s/)
353
+ if (methodMatch) {
354
+ type = methodMatch[1]
355
+ message = message.slice(type.length + 1) // Remove method from message
356
+ }
357
+ }
358
+
350
359
  // Replace warning emoji in ERROR/WARNING messages for consistent terminal rendering
351
360
  if (message && (type === "ERROR" || type === "WARNING")) {
352
361
  message = message.replace(/⚠/g, "[!]")
@@ -369,24 +378,26 @@ const TUIApp = ({
369
378
  const sourceColor = source === "BROWSER" ? LOG_COLORS.BROWSER : LOG_COLORS.SERVER
370
379
  const typeColors: Record<string, string> = {
371
380
  NETWORK: LOG_COLORS.NETWORK,
372
- "NETWORK.REQUEST": LOG_COLORS.NETWORK,
373
- "CONSOLE.ERROR": LOG_COLORS.CONSOLE_ERROR,
374
- "CONSOLE.WARN": LOG_COLORS.CONSOLE_WARN,
375
- "CONSOLE.INFO": LOG_COLORS.CONSOLE_INFO,
376
- "CONSOLE.LOG": LOG_COLORS.CONSOLE_LOG,
377
- "CONSOLE.DEBUG": LOG_COLORS.CONSOLE_DEBUG,
378
- "RUNTIME.ERROR": LOG_COLORS.ERROR,
379
- "CDP.ERROR": LOG_COLORS.CDP,
380
- "CHROME.ERROR": LOG_COLORS.ERROR,
381
- "CHROME.CRASH": LOG_COLORS.CRITICAL_ERROR,
382
- NAVIGATION: LOG_COLORS.PAGE,
383
- INTERACTION: LOG_COLORS.DOM,
381
+ ERROR: LOG_COLORS.ERROR,
382
+ WARNING: LOG_COLORS.WARNING,
383
+ INFO: LOG_COLORS.INFO,
384
+ LOG: LOG_COLORS.LOG,
385
+ DEBUG: LOG_COLORS.DEBUG,
384
386
  SCREENSHOT: LOG_COLORS.SCREENSHOT,
385
- PAGE: LOG_COLORS.PAGE,
386
387
  DOM: LOG_COLORS.DOM,
387
388
  CDP: LOG_COLORS.CDP,
388
- ERROR: LOG_COLORS.ERROR,
389
- "CRITICAL ERROR": LOG_COLORS.CRITICAL_ERROR
389
+ CHROME: LOG_COLORS.CHROME,
390
+ CRASH: LOG_COLORS.CRASH,
391
+ REPLAY: LOG_COLORS.REPLAY,
392
+ NAVIGATION: LOG_COLORS.NAVIGATION,
393
+ INTERACTION: LOG_COLORS.INTERACTION,
394
+ GET: LOG_COLORS.SERVER,
395
+ POST: LOG_COLORS.SERVER,
396
+ PUT: LOG_COLORS.SERVER,
397
+ DELETE: LOG_COLORS.SERVER,
398
+ PATCH: LOG_COLORS.SERVER,
399
+ HEAD: LOG_COLORS.SERVER,
400
+ OPTIONS: LOG_COLORS.SERVER
390
401
  }
391
402
 
392
403
  // In compact mode, skip padding
@@ -409,12 +420,16 @@ const TUIApp = ({
409
420
  )
410
421
  }
411
422
 
412
- // Normal mode with padding
413
- // Calculate padding for source (BROWSER is 7, SERVER is 6)
414
- const sourceSpacing = " ".repeat(Math.max(0, 7 - source.length))
423
+ // Normal mode with minimal padding
424
+ // Single space after source
425
+ const sourceSpacing = ""
426
+
427
+ // Single space after type
428
+ const typeSpacing = ""
415
429
 
416
- // Calculate padding for type (NETWORK.REQUEST is longest at 15)
417
- const typeSpacing = type ? " ".repeat(Math.max(0, 15 - type.length)) : ""
430
+ // For alignment: if no type tag, add spacing equivalent to a tag
431
+ // This aligns SERVER logs without tags with those that have tags
432
+ const alignmentSpacing = !type ? " " : "" // ~7 chars for average tag like [GET]
418
433
 
419
434
  return (
420
435
  <Text key={log.id} wrap="truncate-end">
@@ -424,11 +439,13 @@ const TUIApp = ({
424
439
  [{source}]
425
440
  </Text>
426
441
  <Text>{sourceSpacing} </Text>
427
- {type && (
442
+ {type ? (
428
443
  <>
429
444
  <Text color={typeColors[type] || "#A0A0A0"}>[{type}]</Text>
430
445
  <Text>{typeSpacing} </Text>
431
446
  </>
447
+ ) : (
448
+ <Text>{alignmentSpacing}</Text>
432
449
  )}
433
450
  <Text>{message}</Text>
434
451
  </Text>
@@ -1 +0,0 @@
1
- {"version":3,"sources":["turbopack:///[project]/node_modules/.pnpm/next@15.6.0-canary.31_babel-plugin-react-compiler@19.1.0-rc.3_react-dom@19.1.1_react@19.1.1__react@19.1.1/node_modules/next/src/server/route-modules/app-page/module.compiled.js","turbopack:///[project]/node_modules/.pnpm/next@15.6.0-canary.31_babel-plugin-react-compiler@19.1.0-rc.3_react-dom@19.1.1_react@19.1.1__react@19.1.1/node_modules/next/src/server/route-modules/app-page/vendored/ssr/react-jsx-runtime.ts","turbopack:///[project]/node_modules/.pnpm/next@15.6.0-canary.31_babel-plugin-react-compiler@19.1.0-rc.3_react-dom@19.1.1_react@19.1.1__react@19.1.1/node_modules/next/src/server/route-modules/app-page/vendored/ssr/react.ts","turbopack:///[project]/node_modules/.pnpm/next@15.6.0-canary.31_babel-plugin-react-compiler@19.1.0-rc.3_react-dom@19.1.1_react@19.1.1__react@19.1.1/node_modules/next/src/server/route-modules/app-page/vendored/contexts/app-router-context.ts","turbopack:///[project]/node_modules/.pnpm/next@15.6.0-canary.31_babel-plugin-react-compiler@19.1.0-rc.3_react-dom@19.1.1_react@19.1.1__react@19.1.1/node_modules/next/src/server/route-modules/app-page/vendored/ssr/react-dom.ts","turbopack:///[project]/node_modules/.pnpm/next@15.6.0-canary.31_babel-plugin-react-compiler@19.1.0-rc.3_react-dom@19.1.1_react@19.1.1__react@19.1.1/node_modules/next/src/server/route-modules/app-page/vendored/contexts/hooks-client-context.ts","turbopack:///[project]/node_modules/.pnpm/next@15.6.0-canary.31_babel-plugin-react-compiler@19.1.0-rc.3_react-dom@19.1.1_react@19.1.1__react@19.1.1/node_modules/next/src/server/route-modules/app-page/vendored/contexts/server-inserted-html.ts","turbopack:///[project]/node_modules/.pnpm/next@15.6.0-canary.31_babel-plugin-react-compiler@19.1.0-rc.3_react-dom@19.1.1_react@19.1.1__react@19.1.1/node_modules/next/src/client/components/handle-isr-error.tsx","turbopack:///[project]/node_modules/.pnpm/next@15.6.0-canary.31_babel-plugin-react-compiler@19.1.0-rc.3_react-dom@19.1.1_react@19.1.1__react@19.1.1/node_modules/next/src/client/components/builtin/global-error.tsx"],"sourcesContent":["if (process.env.NEXT_RUNTIME === 'edge') {\n module.exports = require('next/dist/server/route-modules/app-page/module.js')\n} else {\n if (process.env.__NEXT_EXPERIMENTAL_REACT) {\n if (process.env.NODE_ENV === 'development') {\n if (process.env.TURBOPACK) {\n module.exports = require('next/dist/compiled/next-server/app-page-turbo-experimental.runtime.dev.js')\n } else {\n module.exports = require('next/dist/compiled/next-server/app-page-experimental.runtime.dev.js')\n }\n } else {\n if (process.env.TURBOPACK) {\n module.exports = require('next/dist/compiled/next-server/app-page-turbo-experimental.runtime.prod.js')\n } else {\n module.exports = require('next/dist/compiled/next-server/app-page-experimental.runtime.prod.js')\n }\n }\n } else {\n if (process.env.NODE_ENV === 'development') {\n if (process.env.TURBOPACK) {\n module.exports = require('next/dist/compiled/next-server/app-page-turbo.runtime.dev.js')\n } else {\n module.exports = require('next/dist/compiled/next-server/app-page.runtime.dev.js')\n }\n } else {\n if (process.env.TURBOPACK) {\n module.exports = require('next/dist/compiled/next-server/app-page-turbo.runtime.prod.js')\n } else {\n module.exports = require('next/dist/compiled/next-server/app-page.runtime.prod.js')\n }\n }\n }\n}\n","module.exports = (\n require('../../module.compiled') as typeof import('../../module.compiled')\n).vendored['react-ssr']!.ReactJsxRuntime\n","module.exports = (\n require('../../module.compiled') as typeof import('../../module.compiled')\n).vendored['react-ssr']!.React\n","module.exports = (\n require('../../module.compiled') as typeof import('../../module.compiled')\n).vendored['contexts'].AppRouterContext\n","module.exports = (\n require('../../module.compiled') as typeof import('../../module.compiled')\n).vendored['react-ssr']!.ReactDOM\n","module.exports = (\n require('../../module.compiled') as typeof import('../../module.compiled')\n).vendored['contexts'].HooksClientContext\n","module.exports = (\n require('../../module.compiled') as typeof import('../../module.compiled')\n).vendored['contexts'].ServerInsertedHtml\n","const workAsyncStorage =\n typeof window === 'undefined'\n ? (\n require('../../server/app-render/work-async-storage.external') as typeof import('../../server/app-render/work-async-storage.external')\n ).workAsyncStorage\n : undefined\n\n// if we are revalidating we want to re-throw the error so the\n// function crashes so we can maintain our previous cache\n// instead of caching the error page\nexport function HandleISRError({ error }: { error: any }) {\n if (workAsyncStorage) {\n const store = workAsyncStorage.getStore()\n if (store?.isStaticGeneration) {\n if (error) {\n console.error(error)\n }\n throw error\n }\n }\n\n return null\n}\n","'use client'\n\nimport { HandleISRError } from '../handle-isr-error'\n\nconst styles = {\n error: {\n // https://github.com/sindresorhus/modern-normalize/blob/main/modern-normalize.css#L38-L52\n fontFamily:\n 'system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"',\n height: '100vh',\n textAlign: 'center',\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n justifyContent: 'center',\n },\n text: {\n fontSize: '14px',\n fontWeight: 400,\n lineHeight: '28px',\n margin: '0 8px',\n },\n} as const\n\nexport type GlobalErrorComponent = React.ComponentType<{\n error: any\n}>\nfunction DefaultGlobalError({ error }: { error: any }) {\n const digest: string | undefined = error?.digest\n return (\n <html id=\"__next_error__\">\n <head></head>\n <body>\n <HandleISRError error={error} />\n <div style={styles.error}>\n <div>\n <h2 style={styles.text}>\n Application error: a {digest ? 'server' : 'client'}-side exception\n has occurred while loading {window.location.hostname} (see the{' '}\n {digest ? 'server logs' : 'browser console'} for more\n information).\n </h2>\n {digest ? <p style={styles.text}>{`Digest: ${digest}`}</p> : null}\n </div>\n </div>\n </body>\n </html>\n )\n}\n\n// Exported so that the import signature in the loaders can be identical to user\n// supplied custom global error signatures.\nexport default DefaultGlobalError\n"],"names":["process","env","NEXT_RUNTIME","module","exports","require","__NEXT_EXPERIMENTAL_REACT","NODE_ENV","TURBOPACK","vendored","ReactJsxRuntime","React","AppRouterContext","ReactDOM","HooksClientContext","ServerInsertedHtml","HandleISRError","workAsyncStorage","window","undefined","error","store","getStore","isStaticGeneration","console","styles","fontFamily","height","textAlign","display","flexDirection","alignItems","justifyContent","text","fontSize","fontWeight","lineHeight","margin","DefaultGlobalError","digest","html","id","head","body","div","style","h2","location","hostname","p"],"mappings":"2kCA0BQG,EAAOC,OAAO,CAAGC,EAAQ,CAAA,CAAA,IAAA,iCC1BjCF,EAAOC,OAAO,CACZC,EAAQ,CAAA,CAAA,IAAA,GACRI,QAAQ,CAAC,YAAY,CAAEC,eAAe,+BCFxCP,EAAOC,OAAO,CACZC,EAAQ,CAAA,CAAA,IAAA,GACRI,QAAQ,CAAC,YAAY,CAAEE,KAAK,8BCF9BR,EAAOC,OAAO,CACZC,EAAQ,CAAA,CAAA,IAAA,GACRI,QAAQ,CAAC,QAAW,CAACG,gBAAgB,+BCFvCT,EAAOC,OAAO,CACZC,EAAQ,CAAA,CAAA,IAAA,GACRI,QAAQ,CAAC,YAAY,CAAEI,QAAQ,+BCFjCV,EAAOC,OAAO,CACZC,EAAQ,CAAA,CAAA,IAAA,GACRI,QAAQ,CAAC,QAAW,CAACK,kBAAkB,+BCFzCX,EAAOC,OAAO,CACZC,EAAQ,CAAA,CAAA,IAAA,GACRI,QAAQ,CAAC,QAAW,CAACM,kBAAkB,wGCQzBC,iBAAAA,qCAAAA,KAVhB,IAAMC,EAGEZ,EAAQ,CAAA,CAAA,IAAA,GACRY,MAHN,OAAOC,GAGe,CAMjB,EALDC,KAJc,EASJH,EAAe,CAAyB,EAAzB,GAAA,OAAEI,CAAK,CAAkB,CAAzB,EAC7B,GAAIH,EAAkB,CACpB,IAAMI,EAAQJ,EAAiBK,QAAQ,GACvC,GAAID,MAAAA,EAAAA,KAAAA,EAAAA,EAAOE,kBAAkB,CAI3B,CAJ6B,KACzBH,GACFI,IADS,IACDJ,KAAK,CAACA,GAEVA,CAEV,CAEA,OAAO,IACT,8TC8BA,OAFA,AACA,GACA,qCAAA,GAD2C,uBAjDZ,CAAA,CAAA,IAAA,GAEzBK,EAAS,CACbL,EA6C8E,IA7CvE,CAELM,WACE,8FACFC,OAAQ,QACRC,UAAW,SACXC,QAAS,OACTC,cAAe,SACfC,WAAY,SACZC,eAAgB,QAClB,EACAC,KAAM,CACJC,SAAU,OACVC,WAAY,IACZC,WAAY,OACZC,OAAQ,OACV,CACF,EA8BA,EAzBA,SAASC,AAAmB,AAyBbA,CAzBsC,EAAzB,GAAA,OAAElB,CAAK,CAAkB,CAAzB,EACpBmB,EAA6BnB,QAAAA,KAAAA,EAAAA,EAAOmB,MAAM,CAChD,MACE,CADF,AACE,EAAA,EAAA,IAAA,EAACC,CADH,MACGA,CAAKC,GAAG,2BACP,CAAA,EAAA,EAAA,GAAA,EAACC,OAAAA,CAAAA,GACD,CAAA,EAAA,EAAA,IAAA,EAACC,OAAAA,WACC,CAAA,EAAA,EAAA,GAAA,EAAC3B,EAAAA,cAAc,CAAA,CAACI,MAAOA,IACvB,CAAA,EAAA,EAAA,GAAA,EAACwB,MAAAA,CAAIC,MAAOpB,EAAOL,KAAK,UACtB,CAAA,EAAA,EAAA,IAAA,EAACwB,CAAD,KAACA,WACC,CAAA,EAAA,EAAA,IAAA,EAACE,KAAAA,CAAGD,MAAOpB,EAAOQ,IAAI,WAAE,wBACAM,EAAS,SAAW,SAAS,8CACvBrB,OAAO6B,QAAQ,CAACC,QAAQ,CAAC,YAAU,IAC9DT,EAAS,cAAgB,kBAAkB,6BAG7CA,EAAS,CAAA,EAAA,EAAA,EAATA,CAAS,EAACU,IAAAA,CAAEJ,GAAZN,GAAmBd,EAAOQ,IAAI,UAAI,WAAUM,IAAgB,eAMzE","ignoreList":[0,1,2,3,4,5,6,7,8]}
@@ -1,3 +0,0 @@
1
- module.exports=[18622,(a,b,c)=>{b.exports=a.x("next/dist/compiled/next-server/app-page-turbo.runtime.prod.js",()=>require("next/dist/compiled/next-server/app-page-turbo.runtime.prod.js"))},56704,(a,b,c)=>{b.exports=a.x("next/dist/server/app-render/work-async-storage.external.js",()=>require("next/dist/server/app-render/work-async-storage.external.js"))},32319,(a,b,c)=>{b.exports=a.x("next/dist/server/app-render/work-unit-async-storage.external.js",()=>require("next/dist/server/app-render/work-unit-async-storage.external.js"))},20635,(a,b,c)=>{b.exports=a.x("next/dist/server/app-render/action-async-storage.external.js",()=>require("next/dist/server/app-render/action-async-storage.external.js"))},20768,(a,b,c)=>{"use strict";b.exports=a.r(18622)},68960,(a,b,c)=>{"use strict";b.exports=a.r(20768).vendored["react-ssr"].ReactJsxRuntime},77316,(a,b,c)=>{"use strict";b.exports=a.r(20768).vendored["react-ssr"].React},4764,(a,b,c)=>{"use strict";b.exports=a.r(20768).vendored.contexts.AppRouterContext},65558,(a,b,c)=>{"use strict";b.exports=a.r(20768).vendored["react-ssr"].ReactDOM},20841,(a,b,c)=>{"use strict";b.exports=a.r(20768).vendored.contexts.HooksClientContext},88519,(a,b,c)=>{"use strict";b.exports=a.r(20768).vendored.contexts.ServerInsertedHtml}];
2
-
3
- //# sourceMappingURL=%5Broot-of-the-server%5D__91510608._.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["turbopack:///[project]/node_modules/.pnpm/next@15.6.0-canary.31_babel-plugin-react-compiler@19.1.0-rc.3_react-dom@19.1.1_react@19.1.1__react@19.1.1/node_modules/next/src/server/route-modules/app-page/module.compiled.js","turbopack:///[project]/node_modules/.pnpm/next@15.6.0-canary.31_babel-plugin-react-compiler@19.1.0-rc.3_react-dom@19.1.1_react@19.1.1__react@19.1.1/node_modules/next/src/server/route-modules/app-page/vendored/ssr/react-jsx-runtime.ts","turbopack:///[project]/node_modules/.pnpm/next@15.6.0-canary.31_babel-plugin-react-compiler@19.1.0-rc.3_react-dom@19.1.1_react@19.1.1__react@19.1.1/node_modules/next/src/server/route-modules/app-page/vendored/ssr/react.ts","turbopack:///[project]/node_modules/.pnpm/next@15.6.0-canary.31_babel-plugin-react-compiler@19.1.0-rc.3_react-dom@19.1.1_react@19.1.1__react@19.1.1/node_modules/next/src/server/route-modules/app-page/vendored/contexts/app-router-context.ts","turbopack:///[project]/node_modules/.pnpm/next@15.6.0-canary.31_babel-plugin-react-compiler@19.1.0-rc.3_react-dom@19.1.1_react@19.1.1__react@19.1.1/node_modules/next/src/server/route-modules/app-page/vendored/ssr/react-dom.ts","turbopack:///[project]/node_modules/.pnpm/next@15.6.0-canary.31_babel-plugin-react-compiler@19.1.0-rc.3_react-dom@19.1.1_react@19.1.1__react@19.1.1/node_modules/next/src/server/route-modules/app-page/vendored/contexts/hooks-client-context.ts","turbopack:///[project]/node_modules/.pnpm/next@15.6.0-canary.31_babel-plugin-react-compiler@19.1.0-rc.3_react-dom@19.1.1_react@19.1.1__react@19.1.1/node_modules/next/src/server/route-modules/app-page/vendored/contexts/server-inserted-html.ts"],"sourcesContent":["if (process.env.NEXT_RUNTIME === 'edge') {\n module.exports = require('next/dist/server/route-modules/app-page/module.js')\n} else {\n if (process.env.__NEXT_EXPERIMENTAL_REACT) {\n if (process.env.NODE_ENV === 'development') {\n if (process.env.TURBOPACK) {\n module.exports = require('next/dist/compiled/next-server/app-page-turbo-experimental.runtime.dev.js')\n } else {\n module.exports = require('next/dist/compiled/next-server/app-page-experimental.runtime.dev.js')\n }\n } else {\n if (process.env.TURBOPACK) {\n module.exports = require('next/dist/compiled/next-server/app-page-turbo-experimental.runtime.prod.js')\n } else {\n module.exports = require('next/dist/compiled/next-server/app-page-experimental.runtime.prod.js')\n }\n }\n } else {\n if (process.env.NODE_ENV === 'development') {\n if (process.env.TURBOPACK) {\n module.exports = require('next/dist/compiled/next-server/app-page-turbo.runtime.dev.js')\n } else {\n module.exports = require('next/dist/compiled/next-server/app-page.runtime.dev.js')\n }\n } else {\n if (process.env.TURBOPACK) {\n module.exports = require('next/dist/compiled/next-server/app-page-turbo.runtime.prod.js')\n } else {\n module.exports = require('next/dist/compiled/next-server/app-page.runtime.prod.js')\n }\n }\n }\n}\n","module.exports = (\n require('../../module.compiled') as typeof import('../../module.compiled')\n).vendored['react-ssr']!.ReactJsxRuntime\n","module.exports = (\n require('../../module.compiled') as typeof import('../../module.compiled')\n).vendored['react-ssr']!.React\n","module.exports = (\n require('../../module.compiled') as typeof import('../../module.compiled')\n).vendored['contexts'].AppRouterContext\n","module.exports = (\n require('../../module.compiled') as typeof import('../../module.compiled')\n).vendored['react-ssr']!.ReactDOM\n","module.exports = (\n require('../../module.compiled') as typeof import('../../module.compiled')\n).vendored['contexts'].HooksClientContext\n","module.exports = (\n require('../../module.compiled') as typeof import('../../module.compiled')\n).vendored['contexts'].ServerInsertedHtml\n"],"names":["process","env","NEXT_RUNTIME","module","exports","require","__NEXT_EXPERIMENTAL_REACT","NODE_ENV","TURBOPACK","vendored","ReactJsxRuntime","React","AppRouterContext","ReactDOM","HooksClientContext","ServerInsertedHtml"],"mappings":"6tBA0BQG,EAAOC,OAAO,CAAGC,EAAQ,CAAA,CAAA,IAAA,iCC1BjCF,EAAOC,OAAO,CACZC,EAAQ,CAAA,CAAA,IAAA,GACRI,QAAQ,CAAC,YAAY,CAAEC,eAAe,+BCFxCP,EAAOC,OAAO,CACZC,EAAQ,CAAA,CAAA,IAAA,GACRI,QAAQ,CAAC,YAAY,CAAEE,KAAK,8BCF9BR,EAAOC,OAAO,CACZC,EAAQ,CAAA,CAAA,IAAA,GACRI,QAAQ,CAAC,QAAW,CAACG,gBAAgB,+BCFvCT,EAAOC,OAAO,CACZC,EAAQ,CAAA,CAAA,IAAA,GACRI,QAAQ,CAAC,YAAY,CAAEI,QAAQ,+BCFjCV,EAAOC,OAAO,CACZC,EAAQ,CAAA,CAAA,IAAA,GACRI,QAAQ,CAAC,QAAW,CAACK,kBAAkB,+BCFzCX,EAAOC,OAAO,CACZC,EAAQ,CAAA,CAAA,IAAA,GACRI,QAAQ,CAAC,QAAW,CAACM,kBAAkB","ignoreList":[0,1,2,3,4,5,6]}
@@ -1,3 +0,0 @@
1
- module.exports=[18622,(a,b,c)=>{b.exports=a.x("next/dist/compiled/next-server/app-page-turbo.runtime.prod.js",()=>require("next/dist/compiled/next-server/app-page-turbo.runtime.prod.js"))},20768,(a,b,c)=>{"use strict";b.exports=a.r(18622)},68960,(a,b,c)=>{"use strict";b.exports=a.r(20768).vendored["react-ssr"].ReactJsxRuntime},77316,(a,b,c)=>{"use strict";b.exports=a.r(20768).vendored["react-ssr"].React},87576,a=>{"use strict";var b=a.i(68960),c=a.i(77316);function d({params:a}){let{session:d}=(0,c.use)(a),[e,f]=(0,c.useState)([]),[g,h]=(0,c.useState)(0),[i,j]=(0,c.useState)(!1),[k,l]=(0,c.useState)(10),[m,n]=(0,c.useState)({width:1920,height:1080}),[o,p]=(0,c.useState)(null),[q,r]=(0,c.useState)([]);(0,c.useEffect)(()=>{fetch(`/api/screenshots/list?pattern=${d}`).then(a=>a.json()).then(a=>{let b=a.files.filter(a=>a.includes("jank-")&&a.includes(d)).sort((a,b)=>parseInt(a.match(/jank-(\d+)ms/)?.[1]||"0",10)-parseInt(b.match(/jank-(\d+)ms/)?.[1]||"0",10));if(f(b),b.length>0){let a=new Image;a.onload=()=>{n({width:a.naturalWidth,height:a.naturalHeight})},a.src=`/api/screenshots/${b[0]}`}}),fetch(`/api/jank/${d}`).then(a=>a.json()).then(a=>{r(a.clsMarkers||[])}).catch(()=>{r([])})},[d]),(0,c.useEffect)(()=>{if(!i||0===e.length)return;let a=setInterval(()=>{h(a=>a>=e.length-1?(j(!1),a):a+1)},1e3/k);return()=>clearInterval(a)},[i,e.length,k]);let[,s]=(0,c.useState)(0);if((0,c.useEffect)(()=>{let a=()=>s(a=>a+1);return window.addEventListener("resize",a),()=>window.removeEventListener("resize",a)},[]),0===e.length)return(0,b.jsx)("div",{className:"p-8",children:"Loading frames..."});let t=e[g],u=t?.match(/jank-(\d+)ms/)?.[1]||"0",v=parseInt(u,10),w=q.find(a=>100>Math.abs(a.timestamp-v)),x={};if(o&&w?.boundingBox){let a=o.parentElement?.getBoundingClientRect(),b=m.width,c=m.height;if(a){let d,e,f,g,h=a.width/a.height,i=b/c;h>i?(d=(e=a.height)*i,f=(a.width-d)/2,g=0):(e=(d=a.width)/i,f=0,g=(a.height-e)/2);let j=d/b;x={left:`${f+w.boundingBox.x*j}px`,top:`${g+w.boundingBox.y*j}px`,width:`${w.boundingBox.width*j}px`,height:`${w.boundingBox.height*j}px`}}}return(0,b.jsxs)("div",{className:"flex flex-col h-screen bg-black",children:[(0,b.jsxs)("div",{className:"flex-1 flex items-center justify-center relative overflow-hidden",children:[(0,b.jsx)("img",{ref:p,src:`/api/screenshots/${t}`,alt:`Frame ${g}`,className:"w-full h-full object-contain"}),w?.boundingBox&&o&&(0,b.jsx)("div",{className:"absolute border-2 border-red-500 pointer-events-none",style:x})]}),(0,b.jsxs)("div",{className:"bg-gray-900 text-white p-4 space-y-4",children:[(0,b.jsxs)("div",{className:"flex items-center gap-4",children:[(0,b.jsx)("button",{type:"button",onClick:()=>j(!i),className:"px-4 py-2 bg-blue-600 hover:bg-blue-700 rounded",children:i?"Pause":"Play"}),(0,b.jsx)("button",{type:"button",onClick:()=>h(Math.max(0,g-1)),disabled:0===g,className:"px-4 py-2 bg-gray-700 hover:bg-gray-600 rounded disabled:opacity-50",children:"Previous"}),(0,b.jsx)("button",{type:"button",onClick:()=>h(Math.min(e.length-1,g+1)),disabled:g===e.length-1,className:"px-4 py-2 bg-gray-700 hover:bg-gray-600 rounded disabled:opacity-50",children:"Next"}),(0,b.jsxs)("span",{className:"flex-1 text-center",children:["Frame ",g+1," / ",e.length," (",u,"ms)"]}),(0,b.jsxs)("label",{className:"flex items-center gap-2",children:["Speed:",(0,b.jsx)("input",{type:"range",min:"1",max:"30",value:k,onChange:a=>l(Number(a.target.value)),className:"w-32"}),(0,b.jsxs)("span",{className:"w-12",children:[k," fps"]})]})]}),(0,b.jsxs)("div",{className:"relative w-full",children:[(0,b.jsx)("input",{type:"range",min:"0",max:e.length-1,value:g,onChange:a=>h(Number(a.target.value)),className:"w-full"}),q.map(a=>{let c=e.findIndex(b=>parseInt(b.match(/jank-(\d+)ms/)?.[1]||"0",10)>=a.timestamp);if(-1===c)return null;let d=c/(e.length-1)*100;return(0,b.jsxs)("div",{className:"absolute top-0 h-full pointer-events-none",style:{left:`${d}%`},children:[(0,b.jsx)("div",{className:"w-0.5 h-full bg-red-500"}),(0,b.jsx)("div",{className:"absolute -top-6 left-0 -translate-x-1/2 bg-red-500 text-white text-xs px-2 py-0.5 rounded whitespace-nowrap",children:a.clsScore?(0,b.jsxs)(b.Fragment,{children:["CLS ",a.clsScore.toFixed(4)," @ ",a.timestamp,"ms",a.element&&(0,b.jsxs)("span",{className:"ml-1 opacity-75",children:["<",a.element.toLowerCase(),">"]})]}):`CLS ${a.timestamp}ms`})]},a.timestamp)})]})]})]})}a.s(["default",()=>d])}];
2
-
3
- //# sourceMappingURL=%5Broot-of-the-server%5D__e1bc1b8a._.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["turbopack:///[project]/node_modules/.pnpm/next@15.6.0-canary.31_babel-plugin-react-compiler@19.1.0-rc.3_react-dom@19.1.1_react@19.1.1__react@19.1.1/node_modules/next/src/server/route-modules/app-page/module.compiled.js","turbopack:///[project]/node_modules/.pnpm/next@15.6.0-canary.31_babel-plugin-react-compiler@19.1.0-rc.3_react-dom@19.1.1_react@19.1.1__react@19.1.1/node_modules/next/src/server/route-modules/app-page/vendored/ssr/react-jsx-runtime.ts","turbopack:///[project]/node_modules/.pnpm/next@15.6.0-canary.31_babel-plugin-react-compiler@19.1.0-rc.3_react-dom@19.1.1_react@19.1.1__react@19.1.1/node_modules/next/src/server/route-modules/app-page/vendored/ssr/react.ts","turbopack:///[project]/mcp-server/app/video/[session]/page.tsx"],"sourcesContent":["if (process.env.NEXT_RUNTIME === 'edge') {\n module.exports = require('next/dist/server/route-modules/app-page/module.js')\n} else {\n if (process.env.__NEXT_EXPERIMENTAL_REACT) {\n if (process.env.NODE_ENV === 'development') {\n if (process.env.TURBOPACK) {\n module.exports = require('next/dist/compiled/next-server/app-page-turbo-experimental.runtime.dev.js')\n } else {\n module.exports = require('next/dist/compiled/next-server/app-page-experimental.runtime.dev.js')\n }\n } else {\n if (process.env.TURBOPACK) {\n module.exports = require('next/dist/compiled/next-server/app-page-turbo-experimental.runtime.prod.js')\n } else {\n module.exports = require('next/dist/compiled/next-server/app-page-experimental.runtime.prod.js')\n }\n }\n } else {\n if (process.env.NODE_ENV === 'development') {\n if (process.env.TURBOPACK) {\n module.exports = require('next/dist/compiled/next-server/app-page-turbo.runtime.dev.js')\n } else {\n module.exports = require('next/dist/compiled/next-server/app-page.runtime.dev.js')\n }\n } else {\n if (process.env.TURBOPACK) {\n module.exports = require('next/dist/compiled/next-server/app-page-turbo.runtime.prod.js')\n } else {\n module.exports = require('next/dist/compiled/next-server/app-page.runtime.prod.js')\n }\n }\n }\n}\n","module.exports = (\n require('../../module.compiled') as typeof import('../../module.compiled')\n).vendored['react-ssr']!.ReactJsxRuntime\n","module.exports = (\n require('../../module.compiled') as typeof import('../../module.compiled')\n).vendored['react-ssr']!.React\n","\"use client\"\n\nimport { use, useEffect, useState } from \"react\"\n\nexport default function VideoPlayer({ params }: { params: Promise<{ session: string }> }) {\n const { session } = use(params)\n const [frames, setFrames] = useState<string[]>([])\n const [currentFrame, setCurrentFrame] = useState(0)\n const [isPlaying, setIsPlaying] = useState(false)\n const [fps, setFps] = useState(10)\n const [screenshotDimensions, setScreenshotDimensions] = useState<{ width: number; height: number }>({\n width: 1920,\n height: 1080\n })\n const [imgRef, setImgRef] = useState<HTMLImageElement | null>(null)\n const [clsMarkers, setClsMarkers] = useState<\n Array<{\n timestamp: number\n boundingBox: { x: number; y: number; width: number; height: number } | null\n clsScore?: number\n element?: string\n }>\n >([])\n\n useEffect(() => {\n // Parse session timestamp to find matching screenshots\n // Format: 2025-10-05T23-57-XX-jank-XXms.png\n fetch(`/api/screenshots/list?pattern=${session}`)\n .then((r) => r.json())\n .then((data) => {\n const jankFrames = data.files\n .filter((f: string) => f.includes(\"jank-\") && f.includes(session))\n .sort((a: string, b: string) => {\n const aMs = parseInt(a.match(/jank-(\\d+)ms/)?.[1] || \"0\", 10)\n const bMs = parseInt(b.match(/jank-(\\d+)ms/)?.[1] || \"0\", 10)\n return aMs - bMs\n })\n setFrames(jankFrames)\n\n // Load first frame to get dimensions\n if (jankFrames.length > 0) {\n const img = new Image()\n img.onload = () => {\n setScreenshotDimensions({ width: img.naturalWidth, height: img.naturalHeight })\n }\n img.src = `/api/screenshots/${jankFrames[0]}`\n }\n })\n\n // Fetch CLS markers from jank detection API\n fetch(`/api/jank/${session}`)\n .then((r) => r.json())\n .then((data) => {\n setClsMarkers(data.clsMarkers || [])\n })\n .catch(() => {\n setClsMarkers([])\n })\n }, [session])\n\n useEffect(() => {\n if (!isPlaying || frames.length === 0) return\n\n const interval = setInterval(() => {\n setCurrentFrame((prev) => {\n if (prev >= frames.length - 1) {\n setIsPlaying(false)\n return prev\n }\n return prev + 1\n })\n }, 1000 / fps)\n\n return () => clearInterval(interval)\n }, [isPlaying, frames.length, fps])\n\n // Force re-render on window resize to recalculate bounding box position\n const [, forceUpdate] = useState(0)\n useEffect(() => {\n const handleResize = () => forceUpdate((n) => n + 1)\n window.addEventListener(\"resize\", handleResize)\n return () => window.removeEventListener(\"resize\", handleResize)\n }, [])\n\n if (frames.length === 0) {\n return <div className=\"p-8\">Loading frames...</div>\n }\n\n const currentFrameFile = frames[currentFrame]\n const frameMs = currentFrameFile?.match(/jank-(\\d+)ms/)?.[1] || \"0\"\n const currentFrameMs = parseInt(frameMs, 10)\n const clsAtFrame = clsMarkers.find((marker) => Math.abs(marker.timestamp - currentFrameMs) < 100)\n\n // Calculate the rendered image dimensions and position (accounting for object-contain)\n let imgStyle: React.CSSProperties = {}\n if (imgRef && clsAtFrame?.boundingBox) {\n const containerRect = imgRef.parentElement?.getBoundingClientRect()\n const imgNaturalWidth = screenshotDimensions.width\n const imgNaturalHeight = screenshotDimensions.height\n\n if (containerRect) {\n // Calculate how the image is scaled by object-contain\n const containerAspect = containerRect.width / containerRect.height\n const imageAspect = imgNaturalWidth / imgNaturalHeight\n\n let renderedWidth: number, renderedHeight: number, offsetX: number, offsetY: number\n\n if (containerAspect > imageAspect) {\n // Container is wider - image is constrained by height\n renderedHeight = containerRect.height\n renderedWidth = renderedHeight * imageAspect\n offsetX = (containerRect.width - renderedWidth) / 2\n offsetY = 0\n } else {\n // Container is taller - image is constrained by width\n renderedWidth = containerRect.width\n renderedHeight = renderedWidth / imageAspect\n offsetX = 0\n offsetY = (containerRect.height - renderedHeight) / 2\n }\n\n // Calculate bounding box position relative to rendered image\n const scale = renderedWidth / imgNaturalWidth\n imgStyle = {\n left: `${offsetX + clsAtFrame.boundingBox.x * scale}px`,\n top: `${offsetY + clsAtFrame.boundingBox.y * scale}px`,\n width: `${clsAtFrame.boundingBox.width * scale}px`,\n height: `${clsAtFrame.boundingBox.height * scale}px`\n }\n }\n }\n\n return (\n <div className=\"flex flex-col h-screen bg-black\">\n <div className=\"flex-1 flex items-center justify-center relative overflow-hidden\">\n {/* eslint-disable-next-line @next/next/no-img-element */}\n <img\n ref={setImgRef}\n src={`/api/screenshots/${currentFrameFile}`}\n alt={`Frame ${currentFrame}`}\n className=\"w-full h-full object-contain\"\n />\n {clsAtFrame?.boundingBox && imgRef && (\n <div className=\"absolute border-2 border-red-500 pointer-events-none\" style={imgStyle} />\n )}\n </div>\n\n <div className=\"bg-gray-900 text-white p-4 space-y-4\">\n <div className=\"flex items-center gap-4\">\n <button\n type=\"button\"\n onClick={() => setIsPlaying(!isPlaying)}\n className=\"px-4 py-2 bg-blue-600 hover:bg-blue-700 rounded\"\n >\n {isPlaying ? \"Pause\" : \"Play\"}\n </button>\n\n <button\n type=\"button\"\n onClick={() => setCurrentFrame(Math.max(0, currentFrame - 1))}\n disabled={currentFrame === 0}\n className=\"px-4 py-2 bg-gray-700 hover:bg-gray-600 rounded disabled:opacity-50\"\n >\n Previous\n </button>\n\n <button\n type=\"button\"\n onClick={() => setCurrentFrame(Math.min(frames.length - 1, currentFrame + 1))}\n disabled={currentFrame === frames.length - 1}\n className=\"px-4 py-2 bg-gray-700 hover:bg-gray-600 rounded disabled:opacity-50\"\n >\n Next\n </button>\n\n <span className=\"flex-1 text-center\">\n Frame {currentFrame + 1} / {frames.length} ({frameMs}ms)\n </span>\n\n <label className=\"flex items-center gap-2\">\n Speed:\n <input\n type=\"range\"\n min=\"1\"\n max=\"30\"\n value={fps}\n onChange={(e) => setFps(Number(e.target.value))}\n className=\"w-32\"\n />\n <span className=\"w-12\">{fps} fps</span>\n </label>\n </div>\n\n <div className=\"relative w-full\">\n <input\n type=\"range\"\n min=\"0\"\n max={frames.length - 1}\n value={currentFrame}\n onChange={(e) => setCurrentFrame(Number(e.target.value))}\n className=\"w-full\"\n />\n {/* CLS markers on timeline */}\n {clsMarkers.map((marker) => {\n const frameIndex = frames.findIndex((f) => {\n const frameMs = parseInt(f.match(/jank-(\\d+)ms/)?.[1] || \"0\", 10)\n return frameMs >= marker.timestamp\n })\n if (frameIndex === -1) return null\n const position = (frameIndex / (frames.length - 1)) * 100\n return (\n <div\n key={marker.timestamp}\n className=\"absolute top-0 h-full pointer-events-none\"\n style={{ left: `${position}%` }}\n >\n <div className=\"w-0.5 h-full bg-red-500\" />\n <div className=\"absolute -top-6 left-0 -translate-x-1/2 bg-red-500 text-white text-xs px-2 py-0.5 rounded whitespace-nowrap\">\n {marker.clsScore ? (\n <>\n CLS {marker.clsScore.toFixed(4)} @ {marker.timestamp}ms\n {marker.element && (\n <span className=\"ml-1 opacity-75\">&lt;{marker.element.toLowerCase()}&gt;</span>\n )}\n </>\n ) : (\n `CLS ${marker.timestamp}ms`\n )}\n </div>\n </div>\n )\n })}\n </div>\n </div>\n </div>\n )\n}\n"],"names":["process","env","NEXT_RUNTIME","module","exports","require","__NEXT_EXPERIMENTAL_REACT","NODE_ENV","TURBOPACK","vendored","ReactJsxRuntime","React"],"mappings":"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","ignoreList":[0,1,2]}
@@ -1,3 +0,0 @@
1
- module.exports=[18622,(a,b,c)=>{b.exports=a.x("next/dist/compiled/next-server/app-page-turbo.runtime.prod.js",()=>require("next/dist/compiled/next-server/app-page-turbo.runtime.prod.js"))},20768,(a,b,c)=>{"use strict";b.exports=a.r(18622)},68960,(a,b,c)=>{"use strict";b.exports=a.r(20768).vendored["react-ssr"].ReactJsxRuntime},77316,(a,b,c)=>{"use strict";b.exports=a.r(20768).vendored["react-ssr"].React},4764,(a,b,c)=>{"use strict";b.exports=a.r(20768).vendored.contexts.AppRouterContext}];
2
-
3
- //# sourceMappingURL=%5Broot-of-the-server%5D__fb40854a._.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["turbopack:///[project]/node_modules/.pnpm/next@15.6.0-canary.31_babel-plugin-react-compiler@19.1.0-rc.3_react-dom@19.1.1_react@19.1.1__react@19.1.1/node_modules/next/src/server/route-modules/app-page/module.compiled.js","turbopack:///[project]/node_modules/.pnpm/next@15.6.0-canary.31_babel-plugin-react-compiler@19.1.0-rc.3_react-dom@19.1.1_react@19.1.1__react@19.1.1/node_modules/next/src/server/route-modules/app-page/vendored/ssr/react-jsx-runtime.ts","turbopack:///[project]/node_modules/.pnpm/next@15.6.0-canary.31_babel-plugin-react-compiler@19.1.0-rc.3_react-dom@19.1.1_react@19.1.1__react@19.1.1/node_modules/next/src/server/route-modules/app-page/vendored/ssr/react.ts","turbopack:///[project]/node_modules/.pnpm/next@15.6.0-canary.31_babel-plugin-react-compiler@19.1.0-rc.3_react-dom@19.1.1_react@19.1.1__react@19.1.1/node_modules/next/src/server/route-modules/app-page/vendored/contexts/app-router-context.ts"],"sourcesContent":["if (process.env.NEXT_RUNTIME === 'edge') {\n module.exports = require('next/dist/server/route-modules/app-page/module.js')\n} else {\n if (process.env.__NEXT_EXPERIMENTAL_REACT) {\n if (process.env.NODE_ENV === 'development') {\n if (process.env.TURBOPACK) {\n module.exports = require('next/dist/compiled/next-server/app-page-turbo-experimental.runtime.dev.js')\n } else {\n module.exports = require('next/dist/compiled/next-server/app-page-experimental.runtime.dev.js')\n }\n } else {\n if (process.env.TURBOPACK) {\n module.exports = require('next/dist/compiled/next-server/app-page-turbo-experimental.runtime.prod.js')\n } else {\n module.exports = require('next/dist/compiled/next-server/app-page-experimental.runtime.prod.js')\n }\n }\n } else {\n if (process.env.NODE_ENV === 'development') {\n if (process.env.TURBOPACK) {\n module.exports = require('next/dist/compiled/next-server/app-page-turbo.runtime.dev.js')\n } else {\n module.exports = require('next/dist/compiled/next-server/app-page.runtime.dev.js')\n }\n } else {\n if (process.env.TURBOPACK) {\n module.exports = require('next/dist/compiled/next-server/app-page-turbo.runtime.prod.js')\n } else {\n module.exports = require('next/dist/compiled/next-server/app-page.runtime.prod.js')\n }\n }\n }\n}\n","module.exports = (\n require('../../module.compiled') as typeof import('../../module.compiled')\n).vendored['react-ssr']!.ReactJsxRuntime\n","module.exports = (\n require('../../module.compiled') as typeof import('../../module.compiled')\n).vendored['react-ssr']!.React\n","module.exports = (\n require('../../module.compiled') as typeof import('../../module.compiled')\n).vendored['contexts'].AppRouterContext\n"],"names":["process","env","NEXT_RUNTIME","module","exports","require","__NEXT_EXPERIMENTAL_REACT","NODE_ENV","TURBOPACK","vendored","ReactJsxRuntime","React","AppRouterContext"],"mappings":"yNA0BQG,GAAOC,OAAO,CAAGC,EAAQ,CAAA,CAAA,IAAA,iCC1BjCF,EAAOC,OAAO,CACZC,EAAQ,CAAA,CAAA,IAAA,GACRI,QAAQ,CAAC,YAAY,CAAEC,eAAe,+BCFxCP,EAAOC,OAAO,CACZC,EAAQ,CAAA,CAAA,IAAA,GACRI,QAAQ,CAAC,YAAY,CAAEE,KAAK,8BCF9BR,EAAOC,OAAO,CACZC,EAAQ,CAAA,CAAA,IAAA,GACRI,QAAQ,CAAC,QAAW,CAACG,gBAAgB","ignoreList":[0,1,2,3]}
@@ -1,3 +0,0 @@
1
- module.exports=[41148,(a,b,c)=>{"use strict";Object.defineProperty(c,"__esModule",{value:!0}),Object.defineProperty(c,"warnOnce",{enumerable:!0,get:function(){return d}});let d=a=>{}},3988,(a,b,c)=>{"use strict";function d(a){if("function"!=typeof WeakMap)return null;var b=new WeakMap,c=new WeakMap;return(d=function(a){return a?c:b})(a)}c._=function(a,b){if(!b&&a&&a.__esModule)return a;if(null===a||"object"!=typeof a&&"function"!=typeof a)return{default:a};var c=d(b);if(c&&c.has(a))return c.get(a);var e={__proto__:null},f=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var g in a)if("default"!==g&&Object.prototype.hasOwnProperty.call(a,g)){var h=f?Object.getOwnPropertyDescriptor(a,g):null;h&&(h.get||h.set)?Object.defineProperty(e,g,h):e[g]=a[g]}return e.default=a,c&&c.set(a,e),e}},86664,(a,b,c)=>{"use strict";Object.defineProperty(c,"__esModule",{value:!0}),Object.defineProperty(c,"useMergedRef",{enumerable:!0,get:function(){return e}});let d=a.r(77316);function e(a,b){let c=(0,d.useRef)(null),e=(0,d.useRef)(null);return(0,d.useCallback)(d=>{if(null===d){let a=c.current;a&&(c.current=null,a());let b=e.current;b&&(e.current=null,b())}else a&&(c.current=f(a,d)),b&&(e.current=f(b,d))},[a,b])}function f(a,b){if("function"!=typeof a)return a.current=b,()=>{a.current=null};{let c=a(b);return"function"==typeof c?c:()=>a(null)}}("function"==typeof c.default||"object"==typeof c.default&&null!==c.default)&&void 0===c.default.__esModule&&(Object.defineProperty(c.default,"__esModule",{value:!0}),Object.assign(c.default,c),b.exports=c.default)},75040,(a,b,c)=>{"use strict";Object.defineProperty(c,"__esModule",{value:!0}),Object.defineProperty(c,"InvariantError",{enumerable:!0,get:function(){return d}});class d extends Error{constructor(a,b){super("Invariant: "+(a.endsWith(".")?a:a+".")+" This is a bug in Next.js.",b),this.name="InvariantError"}}},87896,37825,a=>{"use strict";var b=a.i(68960),c=a.i(77316);let d=a=>{let b=a.replace(/^([A-Z])|[\s-_]+(\w)/g,(a,b,c)=>c?c.toUpperCase():b.toLowerCase());return b.charAt(0).toUpperCase()+b.slice(1)},e=(...a)=>a.filter((a,b,c)=>!!a&&""!==a.trim()&&c.indexOf(a)===b).join(" ").trim();var f={xmlns:"http://www.w3.org/2000/svg",width:24,height:24,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"};let g=(0,c.forwardRef)(({color:a="currentColor",size:b=24,strokeWidth:d=2,absoluteStrokeWidth:g,className:h="",children:i,iconNode:j,...k},l)=>(0,c.createElement)("svg",{ref:l,...f,width:b,height:b,stroke:a,strokeWidth:g?24*Number(d)/Number(b):d,className:e("lucide",h),...!i&&!(a=>{for(let b in a)if(b.startsWith("aria-")||"role"===b||"title"===b)return!0})(k)&&{"aria-hidden":"true"},...k},[...j.map(([a,b])=>(0,c.createElement)(a,b)),...Array.isArray(i)?i:[i]])),h=(a,b)=>{let f=(0,c.forwardRef)(({className:f,...h},i)=>(0,c.createElement)(g,{ref:i,iconNode:b,className:e(`lucide-${d(a).replace(/([a-z0-9])([A-Z])/g,"$1-$2").toLowerCase()}`,`lucide-${a}`,f),...h}));return f.displayName=d(a),f},i=h("moon",[["path",{d:"M20.985 12.486a9 9 0 1 1-9.473-9.472c.405-.022.617.46.402.803a6 6 0 0 0 8.268 8.268c.344-.215.825-.004.803.401",key:"kfwtm"}]]),j=h("sun",[["circle",{cx:"12",cy:"12",r:"4",key:"4exip2"}],["path",{d:"M12 2v2",key:"tus03m"}],["path",{d:"M12 20v2",key:"1lh1kg"}],["path",{d:"m4.93 4.93 1.41 1.41",key:"149t6j"}],["path",{d:"m17.66 17.66 1.41 1.41",key:"ptbguv"}],["path",{d:"M2 12h2",key:"1t8f8n"}],["path",{d:"M20 12h2",key:"1q8mjw"}],["path",{d:"m6.34 17.66-1.41 1.41",key:"1m8zz5"}],["path",{d:"m19.07 4.93-1.41 1.41",key:"1shlcs"}]]);function k(a,b){if("function"==typeof a)return a(b);null!=a&&(a.current=b)}var l=function(a){let d=function(a){let b=c.forwardRef((a,b)=>{let{children:d,...e}=a;if(c.isValidElement(d)){var f;let a,g,h=(f=d,(g=(a=Object.getOwnPropertyDescriptor(f.props,"ref")?.get)&&"isReactWarning"in a&&a.isReactWarning)?f.ref:(g=(a=Object.getOwnPropertyDescriptor(f,"ref")?.get)&&"isReactWarning"in a&&a.isReactWarning)?f.props.ref:f.props.ref||f.ref),i=function(a,b){let c={...b};for(let d in b){let e=a[d],f=b[d];/^on[A-Z]/.test(d)?e&&f?c[d]=(...a)=>{let b=f(...a);return e(...a),b}:e&&(c[d]=e):"style"===d?c[d]={...e,...f}:"className"===d&&(c[d]=[e,f].filter(Boolean).join(" "))}return{...a,...c}}(e,d.props);return d.type!==c.Fragment&&(i.ref=b?function(...a){return b=>{let c=!1,d=a.map(a=>{let d=k(a,b);return c||"function"!=typeof d||(c=!0),d});if(c)return()=>{for(let b=0;b<d.length;b++){let c=d[b];"function"==typeof c?c():k(a[b],null)}}}}(b,h):h),c.cloneElement(d,i)}return c.Children.count(d)>1?c.Children.only(null):null});return b.displayName=`${a}.SlotClone`,b}(a),e=c.forwardRef((a,e)=>{let{children:f,...g}=a,h=c.Children.toArray(f),i=h.find(n);if(i){let a=i.props.children,f=h.map(b=>b!==i?b:c.Children.count(a)>1?c.Children.only(null):c.isValidElement(a)?a.props.children:null);return(0,b.jsx)(d,{...g,ref:e,children:c.isValidElement(a)?c.cloneElement(a,void 0,f):null})}return(0,b.jsx)(d,{...g,ref:e,children:f})});return e.displayName=`${a}.Slot`,e}("Slot"),m=Symbol("radix.slottable");function n(a){return c.isValidElement(a)&&"function"==typeof a.type&&"__radixId"in a.type&&a.type.__radixId===m}function o(){for(var a,b,c=0,d="",e=arguments.length;c<e;c++)(a=arguments[c])&&(b=function a(b){var c,d,e="";if("string"==typeof b||"number"==typeof b)e+=b;else if("object"==typeof b)if(Array.isArray(b)){var f=b.length;for(c=0;c<f;c++)b[c]&&(d=a(b[c]))&&(e&&(e+=" "),e+=d)}else for(d in b)b[d]&&(e&&(e+=" "),e+=d);return e}(a))&&(d&&(d+=" "),d+=b);return d}let p=a=>"boolean"==typeof a?`${a}`:0===a?"0":a,q=(a,b)=>{if(0===a.length)return b.classGroupId;let c=a[0],d=b.nextPart.get(c),e=d?q(a.slice(1),d):void 0;if(e)return e;if(0===b.validators.length)return;let f=a.join("-");return b.validators.find(({validator:a})=>a(f))?.classGroupId},r=/^\[(.+)\]$/,s=(a,b,c,d)=>{a.forEach(a=>{if("string"==typeof a){(""===a?b:t(b,a)).classGroupId=c;return}if("function"==typeof a)return u(a)?void s(a(d),b,c,d):void b.validators.push({validator:a,classGroupId:c});Object.entries(a).forEach(([a,e])=>{s(e,t(b,a),c,d)})})},t=(a,b)=>{let c=a;return b.split("-").forEach(a=>{c.nextPart.has(a)||c.nextPart.set(a,{nextPart:new Map,validators:[]}),c=c.nextPart.get(a)}),c},u=a=>a.isThemeGetter,v=(a,b)=>b?a.map(([a,c])=>[a,c.map(a=>"string"==typeof a?b+a:"object"==typeof a?Object.fromEntries(Object.entries(a).map(([a,c])=>[b+a,c])):a)]):a,w=a=>{if(a.length<=1)return a;let b=[],c=[];return a.forEach(a=>{"["===a[0]?(b.push(...c.sort(),a),c=[]):c.push(a)}),b.push(...c.sort()),b},x=/\s+/;function y(){let a,b,c=0,d="";for(;c<arguments.length;)(a=arguments[c++])&&(b=z(a))&&(d&&(d+=" "),d+=b);return d}let z=a=>{let b;if("string"==typeof a)return a;let c="";for(let d=0;d<a.length;d++)a[d]&&(b=z(a[d]))&&(c&&(c+=" "),c+=b);return c},A=a=>{let b=b=>b[a]||[];return b.isThemeGetter=!0,b},B=/^\[(?:([a-z-]+):)?(.+)\]$/i,C=/^\d+\/\d+$/,D=new Set(["px","full","screen"]),E=/^(\d+(\.\d+)?)?(xs|sm|md|lg|xl)$/,F=/\d+(%|px|r?em|[sdl]?v([hwib]|min|max)|pt|pc|in|cm|mm|cap|ch|ex|r?lh|cq(w|h|i|b|min|max))|\b(calc|min|max|clamp)\(.+\)|^0$/,G=/^(rgba?|hsla?|hwb|(ok)?(lab|lch))\(.+\)$/,H=/^(inset_)?-?((\d+)?\.?(\d+)[a-z]+|0)_-?((\d+)?\.?(\d+)[a-z]+|0)/,I=/^(url|image|image-set|cross-fade|element|(repeating-)?(linear|radial|conic)-gradient)\(.+\)$/,J=a=>L(a)||D.has(a)||C.test(a),K=a=>Y(a,"length",Z),L=a=>!!a&&!Number.isNaN(Number(a)),M=a=>Y(a,"number",L),N=a=>!!a&&Number.isInteger(Number(a)),O=a=>a.endsWith("%")&&L(a.slice(0,-1)),P=a=>B.test(a),Q=a=>E.test(a),R=new Set(["length","size","percentage"]),S=a=>Y(a,R,$),T=a=>Y(a,"position",$),U=new Set(["image","url"]),V=a=>Y(a,U,aa),W=a=>Y(a,"",_),X=()=>!0,Y=(a,b,c)=>{let d=B.exec(a);return!!d&&(d[1]?"string"==typeof b?d[1]===b:b.has(d[1]):c(d[2]))},Z=a=>F.test(a)&&!G.test(a),$=()=>!1,_=a=>H.test(a),aa=a=>I.test(a);Symbol.toStringTag;let ab=function(a,...b){let c,d,e,f=function(h){let i;return d=(c={cache:(a=>{if(a<1)return{get:()=>void 0,set:()=>{}};let b=0,c=new Map,d=new Map,e=(e,f)=>{c.set(e,f),++b>a&&(b=0,d=c,c=new Map)};return{get(a){let b=c.get(a);return void 0!==b?b:void 0!==(b=d.get(a))?(e(a,b),b):void 0},set(a,b){c.has(a)?c.set(a,b):e(a,b)}}})((i=b.reduce((a,b)=>b(a),a())).cacheSize),parseClassName:(a=>{let{separator:b,experimentalParseClassName:c}=a,d=1===b.length,e=b[0],f=b.length,g=a=>{let c,g=[],h=0,i=0;for(let j=0;j<a.length;j++){let k=a[j];if(0===h){if(k===e&&(d||a.slice(j,j+f)===b)){g.push(a.slice(i,j)),i=j+f;continue}if("/"===k){c=j;continue}}"["===k?h++:"]"===k&&h--}let j=0===g.length?a:a.substring(i),k=j.startsWith("!"),l=k?j.substring(1):j;return{modifiers:g,hasImportantModifier:k,baseClassName:l,maybePostfixModifierPosition:c&&c>i?c-i:void 0}};return c?a=>c({className:a,parseClassName:g}):g})(i),...(a=>{let b=(a=>{let{theme:b,prefix:c}=a,d={nextPart:new Map,validators:[]};return v(Object.entries(a.classGroups),c).forEach(([a,c])=>{s(c,d,a,b)}),d})(a),{conflictingClassGroups:c,conflictingClassGroupModifiers:d}=a;return{getClassGroupId:a=>{let c=a.split("-");return""===c[0]&&1!==c.length&&c.shift(),q(c,b)||(a=>{if(r.test(a)){let b=r.exec(a)[1],c=b?.substring(0,b.indexOf(":"));if(c)return"arbitrary.."+c}})(a)},getConflictingClassGroupIds:(a,b)=>{let e=c[a]||[];return b&&d[a]?[...e,...d[a]]:e}}})(i)}).cache.get,e=c.cache.set,f=g,g(h)};function g(a){let b=d(a);if(b)return b;let f=((a,b)=>{let{parseClassName:c,getClassGroupId:d,getConflictingClassGroupIds:e}=b,f=[],g=a.trim().split(x),h="";for(let a=g.length-1;a>=0;a-=1){let b=g[a],{modifiers:i,hasImportantModifier:j,baseClassName:k,maybePostfixModifierPosition:l}=c(b),m=!!l,n=d(m?k.substring(0,l):k);if(!n){if(!m||!(n=d(k))){h=b+(h.length>0?" "+h:h);continue}m=!1}let o=w(i).join(":"),p=j?o+"!":o,q=p+n;if(f.includes(q))continue;f.push(q);let r=e(n,m);for(let a=0;a<r.length;++a){let b=r[a];f.push(p+b)}h=b+(h.length>0?" "+h:h)}return h})(a,c);return e(a,f),f}return function(){return f(y.apply(null,arguments))}}(()=>{let a=A("colors"),b=A("spacing"),c=A("blur"),d=A("brightness"),e=A("borderColor"),f=A("borderRadius"),g=A("borderSpacing"),h=A("borderWidth"),i=A("contrast"),j=A("grayscale"),k=A("hueRotate"),l=A("invert"),m=A("gap"),n=A("gradientColorStops"),o=A("gradientColorStopPositions"),p=A("inset"),q=A("margin"),r=A("opacity"),s=A("padding"),t=A("saturate"),u=A("scale"),v=A("sepia"),w=A("skew"),x=A("space"),y=A("translate"),z=()=>["auto","contain","none"],B=()=>["auto","hidden","clip","visible","scroll"],C=()=>["auto",P,b],D=()=>[P,b],E=()=>["",J,K],F=()=>["auto",L,P],G=()=>["bottom","center","left","left-bottom","left-top","right","right-bottom","right-top","top"],H=()=>["solid","dashed","dotted","double","none"],I=()=>["normal","multiply","screen","overlay","darken","lighten","color-dodge","color-burn","hard-light","soft-light","difference","exclusion","hue","saturation","color","luminosity"],R=()=>["start","end","center","between","around","evenly","stretch"],U=()=>["","0",P],Y=()=>["auto","avoid","all","avoid-page","page","left","right","column"],Z=()=>[L,P];return{cacheSize:500,separator:":",theme:{colors:[X],spacing:[J,K],blur:["none","",Q,P],brightness:Z(),borderColor:[a],borderRadius:["none","","full",Q,P],borderSpacing:D(),borderWidth:E(),contrast:Z(),grayscale:U(),hueRotate:Z(),invert:U(),gap:D(),gradientColorStops:[a],gradientColorStopPositions:[O,K],inset:C(),margin:C(),opacity:Z(),padding:D(),saturate:Z(),scale:Z(),sepia:U(),skew:Z(),space:D(),translate:D()},classGroups:{aspect:[{aspect:["auto","square","video",P]}],container:["container"],columns:[{columns:[Q]}],"break-after":[{"break-after":Y()}],"break-before":[{"break-before":Y()}],"break-inside":[{"break-inside":["auto","avoid","avoid-page","avoid-column"]}],"box-decoration":[{"box-decoration":["slice","clone"]}],box:[{box:["border","content"]}],display:["block","inline-block","inline","flex","inline-flex","table","inline-table","table-caption","table-cell","table-column","table-column-group","table-footer-group","table-header-group","table-row-group","table-row","flow-root","grid","inline-grid","contents","list-item","hidden"],float:[{float:["right","left","none","start","end"]}],clear:[{clear:["left","right","both","none","start","end"]}],isolation:["isolate","isolation-auto"],"object-fit":[{object:["contain","cover","fill","none","scale-down"]}],"object-position":[{object:[...G(),P]}],overflow:[{overflow:B()}],"overflow-x":[{"overflow-x":B()}],"overflow-y":[{"overflow-y":B()}],overscroll:[{overscroll:z()}],"overscroll-x":[{"overscroll-x":z()}],"overscroll-y":[{"overscroll-y":z()}],position:["static","fixed","absolute","relative","sticky"],inset:[{inset:[p]}],"inset-x":[{"inset-x":[p]}],"inset-y":[{"inset-y":[p]}],start:[{start:[p]}],end:[{end:[p]}],top:[{top:[p]}],right:[{right:[p]}],bottom:[{bottom:[p]}],left:[{left:[p]}],visibility:["visible","invisible","collapse"],z:[{z:["auto",N,P]}],basis:[{basis:C()}],"flex-direction":[{flex:["row","row-reverse","col","col-reverse"]}],"flex-wrap":[{flex:["wrap","wrap-reverse","nowrap"]}],flex:[{flex:["1","auto","initial","none",P]}],grow:[{grow:U()}],shrink:[{shrink:U()}],order:[{order:["first","last","none",N,P]}],"grid-cols":[{"grid-cols":[X]}],"col-start-end":[{col:["auto",{span:["full",N,P]},P]}],"col-start":[{"col-start":F()}],"col-end":[{"col-end":F()}],"grid-rows":[{"grid-rows":[X]}],"row-start-end":[{row:["auto",{span:[N,P]},P]}],"row-start":[{"row-start":F()}],"row-end":[{"row-end":F()}],"grid-flow":[{"grid-flow":["row","col","dense","row-dense","col-dense"]}],"auto-cols":[{"auto-cols":["auto","min","max","fr",P]}],"auto-rows":[{"auto-rows":["auto","min","max","fr",P]}],gap:[{gap:[m]}],"gap-x":[{"gap-x":[m]}],"gap-y":[{"gap-y":[m]}],"justify-content":[{justify:["normal",...R()]}],"justify-items":[{"justify-items":["start","end","center","stretch"]}],"justify-self":[{"justify-self":["auto","start","end","center","stretch"]}],"align-content":[{content:["normal",...R(),"baseline"]}],"align-items":[{items:["start","end","center","baseline","stretch"]}],"align-self":[{self:["auto","start","end","center","stretch","baseline"]}],"place-content":[{"place-content":[...R(),"baseline"]}],"place-items":[{"place-items":["start","end","center","baseline","stretch"]}],"place-self":[{"place-self":["auto","start","end","center","stretch"]}],p:[{p:[s]}],px:[{px:[s]}],py:[{py:[s]}],ps:[{ps:[s]}],pe:[{pe:[s]}],pt:[{pt:[s]}],pr:[{pr:[s]}],pb:[{pb:[s]}],pl:[{pl:[s]}],m:[{m:[q]}],mx:[{mx:[q]}],my:[{my:[q]}],ms:[{ms:[q]}],me:[{me:[q]}],mt:[{mt:[q]}],mr:[{mr:[q]}],mb:[{mb:[q]}],ml:[{ml:[q]}],"space-x":[{"space-x":[x]}],"space-x-reverse":["space-x-reverse"],"space-y":[{"space-y":[x]}],"space-y-reverse":["space-y-reverse"],w:[{w:["auto","min","max","fit","svw","lvw","dvw",P,b]}],"min-w":[{"min-w":[P,b,"min","max","fit"]}],"max-w":[{"max-w":[P,b,"none","full","min","max","fit","prose",{screen:[Q]},Q]}],h:[{h:[P,b,"auto","min","max","fit","svh","lvh","dvh"]}],"min-h":[{"min-h":[P,b,"min","max","fit","svh","lvh","dvh"]}],"max-h":[{"max-h":[P,b,"min","max","fit","svh","lvh","dvh"]}],size:[{size:[P,b,"auto","min","max","fit"]}],"font-size":[{text:["base",Q,K]}],"font-smoothing":["antialiased","subpixel-antialiased"],"font-style":["italic","not-italic"],"font-weight":[{font:["thin","extralight","light","normal","medium","semibold","bold","extrabold","black",M]}],"font-family":[{font:[X]}],"fvn-normal":["normal-nums"],"fvn-ordinal":["ordinal"],"fvn-slashed-zero":["slashed-zero"],"fvn-figure":["lining-nums","oldstyle-nums"],"fvn-spacing":["proportional-nums","tabular-nums"],"fvn-fraction":["diagonal-fractions","stacked-fractions"],tracking:[{tracking:["tighter","tight","normal","wide","wider","widest",P]}],"line-clamp":[{"line-clamp":["none",L,M]}],leading:[{leading:["none","tight","snug","normal","relaxed","loose",J,P]}],"list-image":[{"list-image":["none",P]}],"list-style-type":[{list:["none","disc","decimal",P]}],"list-style-position":[{list:["inside","outside"]}],"placeholder-color":[{placeholder:[a]}],"placeholder-opacity":[{"placeholder-opacity":[r]}],"text-alignment":[{text:["left","center","right","justify","start","end"]}],"text-color":[{text:[a]}],"text-opacity":[{"text-opacity":[r]}],"text-decoration":["underline","overline","line-through","no-underline"],"text-decoration-style":[{decoration:[...H(),"wavy"]}],"text-decoration-thickness":[{decoration:["auto","from-font",J,K]}],"underline-offset":[{"underline-offset":["auto",J,P]}],"text-decoration-color":[{decoration:[a]}],"text-transform":["uppercase","lowercase","capitalize","normal-case"],"text-overflow":["truncate","text-ellipsis","text-clip"],"text-wrap":[{text:["wrap","nowrap","balance","pretty"]}],indent:[{indent:D()}],"vertical-align":[{align:["baseline","top","middle","bottom","text-top","text-bottom","sub","super",P]}],whitespace:[{whitespace:["normal","nowrap","pre","pre-line","pre-wrap","break-spaces"]}],break:[{break:["normal","words","all","keep"]}],hyphens:[{hyphens:["none","manual","auto"]}],content:[{content:["none",P]}],"bg-attachment":[{bg:["fixed","local","scroll"]}],"bg-clip":[{"bg-clip":["border","padding","content","text"]}],"bg-opacity":[{"bg-opacity":[r]}],"bg-origin":[{"bg-origin":["border","padding","content"]}],"bg-position":[{bg:[...G(),T]}],"bg-repeat":[{bg:["no-repeat",{repeat:["","x","y","round","space"]}]}],"bg-size":[{bg:["auto","cover","contain",S]}],"bg-image":[{bg:["none",{"gradient-to":["t","tr","r","br","b","bl","l","tl"]},V]}],"bg-color":[{bg:[a]}],"gradient-from-pos":[{from:[o]}],"gradient-via-pos":[{via:[o]}],"gradient-to-pos":[{to:[o]}],"gradient-from":[{from:[n]}],"gradient-via":[{via:[n]}],"gradient-to":[{to:[n]}],rounded:[{rounded:[f]}],"rounded-s":[{"rounded-s":[f]}],"rounded-e":[{"rounded-e":[f]}],"rounded-t":[{"rounded-t":[f]}],"rounded-r":[{"rounded-r":[f]}],"rounded-b":[{"rounded-b":[f]}],"rounded-l":[{"rounded-l":[f]}],"rounded-ss":[{"rounded-ss":[f]}],"rounded-se":[{"rounded-se":[f]}],"rounded-ee":[{"rounded-ee":[f]}],"rounded-es":[{"rounded-es":[f]}],"rounded-tl":[{"rounded-tl":[f]}],"rounded-tr":[{"rounded-tr":[f]}],"rounded-br":[{"rounded-br":[f]}],"rounded-bl":[{"rounded-bl":[f]}],"border-w":[{border:[h]}],"border-w-x":[{"border-x":[h]}],"border-w-y":[{"border-y":[h]}],"border-w-s":[{"border-s":[h]}],"border-w-e":[{"border-e":[h]}],"border-w-t":[{"border-t":[h]}],"border-w-r":[{"border-r":[h]}],"border-w-b":[{"border-b":[h]}],"border-w-l":[{"border-l":[h]}],"border-opacity":[{"border-opacity":[r]}],"border-style":[{border:[...H(),"hidden"]}],"divide-x":[{"divide-x":[h]}],"divide-x-reverse":["divide-x-reverse"],"divide-y":[{"divide-y":[h]}],"divide-y-reverse":["divide-y-reverse"],"divide-opacity":[{"divide-opacity":[r]}],"divide-style":[{divide:H()}],"border-color":[{border:[e]}],"border-color-x":[{"border-x":[e]}],"border-color-y":[{"border-y":[e]}],"border-color-s":[{"border-s":[e]}],"border-color-e":[{"border-e":[e]}],"border-color-t":[{"border-t":[e]}],"border-color-r":[{"border-r":[e]}],"border-color-b":[{"border-b":[e]}],"border-color-l":[{"border-l":[e]}],"divide-color":[{divide:[e]}],"outline-style":[{outline:["",...H()]}],"outline-offset":[{"outline-offset":[J,P]}],"outline-w":[{outline:[J,K]}],"outline-color":[{outline:[a]}],"ring-w":[{ring:E()}],"ring-w-inset":["ring-inset"],"ring-color":[{ring:[a]}],"ring-opacity":[{"ring-opacity":[r]}],"ring-offset-w":[{"ring-offset":[J,K]}],"ring-offset-color":[{"ring-offset":[a]}],shadow:[{shadow:["","inner","none",Q,W]}],"shadow-color":[{shadow:[X]}],opacity:[{opacity:[r]}],"mix-blend":[{"mix-blend":[...I(),"plus-lighter","plus-darker"]}],"bg-blend":[{"bg-blend":I()}],filter:[{filter:["","none"]}],blur:[{blur:[c]}],brightness:[{brightness:[d]}],contrast:[{contrast:[i]}],"drop-shadow":[{"drop-shadow":["","none",Q,P]}],grayscale:[{grayscale:[j]}],"hue-rotate":[{"hue-rotate":[k]}],invert:[{invert:[l]}],saturate:[{saturate:[t]}],sepia:[{sepia:[v]}],"backdrop-filter":[{"backdrop-filter":["","none"]}],"backdrop-blur":[{"backdrop-blur":[c]}],"backdrop-brightness":[{"backdrop-brightness":[d]}],"backdrop-contrast":[{"backdrop-contrast":[i]}],"backdrop-grayscale":[{"backdrop-grayscale":[j]}],"backdrop-hue-rotate":[{"backdrop-hue-rotate":[k]}],"backdrop-invert":[{"backdrop-invert":[l]}],"backdrop-opacity":[{"backdrop-opacity":[r]}],"backdrop-saturate":[{"backdrop-saturate":[t]}],"backdrop-sepia":[{"backdrop-sepia":[v]}],"border-collapse":[{border:["collapse","separate"]}],"border-spacing":[{"border-spacing":[g]}],"border-spacing-x":[{"border-spacing-x":[g]}],"border-spacing-y":[{"border-spacing-y":[g]}],"table-layout":[{table:["auto","fixed"]}],caption:[{caption:["top","bottom"]}],transition:[{transition:["none","all","","colors","opacity","shadow","transform",P]}],duration:[{duration:Z()}],ease:[{ease:["linear","in","out","in-out",P]}],delay:[{delay:Z()}],animate:[{animate:["none","spin","ping","pulse","bounce",P]}],transform:[{transform:["","gpu","none"]}],scale:[{scale:[u]}],"scale-x":[{"scale-x":[u]}],"scale-y":[{"scale-y":[u]}],rotate:[{rotate:[N,P]}],"translate-x":[{"translate-x":[y]}],"translate-y":[{"translate-y":[y]}],"skew-x":[{"skew-x":[w]}],"skew-y":[{"skew-y":[w]}],"transform-origin":[{origin:["center","top","top-right","right","bottom-right","bottom","bottom-left","left","top-left",P]}],accent:[{accent:["auto",a]}],appearance:[{appearance:["none","auto"]}],cursor:[{cursor:["auto","default","pointer","wait","text","move","help","not-allowed","none","context-menu","progress","cell","crosshair","vertical-text","alias","copy","no-drop","grab","grabbing","all-scroll","col-resize","row-resize","n-resize","e-resize","s-resize","w-resize","ne-resize","nw-resize","se-resize","sw-resize","ew-resize","ns-resize","nesw-resize","nwse-resize","zoom-in","zoom-out",P]}],"caret-color":[{caret:[a]}],"pointer-events":[{"pointer-events":["none","auto"]}],resize:[{resize:["none","y","x",""]}],"scroll-behavior":[{scroll:["auto","smooth"]}],"scroll-m":[{"scroll-m":D()}],"scroll-mx":[{"scroll-mx":D()}],"scroll-my":[{"scroll-my":D()}],"scroll-ms":[{"scroll-ms":D()}],"scroll-me":[{"scroll-me":D()}],"scroll-mt":[{"scroll-mt":D()}],"scroll-mr":[{"scroll-mr":D()}],"scroll-mb":[{"scroll-mb":D()}],"scroll-ml":[{"scroll-ml":D()}],"scroll-p":[{"scroll-p":D()}],"scroll-px":[{"scroll-px":D()}],"scroll-py":[{"scroll-py":D()}],"scroll-ps":[{"scroll-ps":D()}],"scroll-pe":[{"scroll-pe":D()}],"scroll-pt":[{"scroll-pt":D()}],"scroll-pr":[{"scroll-pr":D()}],"scroll-pb":[{"scroll-pb":D()}],"scroll-pl":[{"scroll-pl":D()}],"snap-align":[{snap:["start","end","center","align-none"]}],"snap-stop":[{snap:["normal","always"]}],"snap-type":[{snap:["none","x","y","both"]}],"snap-strictness":[{snap:["mandatory","proximity"]}],touch:[{touch:["auto","none","manipulation"]}],"touch-x":[{"touch-pan":["x","left","right"]}],"touch-y":[{"touch-pan":["y","up","down"]}],"touch-pz":["touch-pinch-zoom"],select:[{select:["none","text","all","auto"]}],"will-change":[{"will-change":["auto","scroll","contents","transform",P]}],fill:[{fill:[a,"none"]}],"stroke-w":[{stroke:[J,K,M]}],stroke:[{stroke:[a,"none"]}],sr:["sr-only","not-sr-only"],"forced-color-adjust":[{"forced-color-adjust":["auto","none"]}]},conflictingClassGroups:{overflow:["overflow-x","overflow-y"],overscroll:["overscroll-x","overscroll-y"],inset:["inset-x","inset-y","start","end","top","right","bottom","left"],"inset-x":["right","left"],"inset-y":["top","bottom"],flex:["basis","grow","shrink"],gap:["gap-x","gap-y"],p:["px","py","ps","pe","pt","pr","pb","pl"],px:["pr","pl"],py:["pt","pb"],m:["mx","my","ms","me","mt","mr","mb","ml"],mx:["mr","ml"],my:["mt","mb"],size:["w","h"],"font-size":["leading"],"fvn-normal":["fvn-ordinal","fvn-slashed-zero","fvn-figure","fvn-spacing","fvn-fraction"],"fvn-ordinal":["fvn-normal"],"fvn-slashed-zero":["fvn-normal"],"fvn-figure":["fvn-normal"],"fvn-spacing":["fvn-normal"],"fvn-fraction":["fvn-normal"],"line-clamp":["display","overflow"],rounded:["rounded-s","rounded-e","rounded-t","rounded-r","rounded-b","rounded-l","rounded-ss","rounded-se","rounded-ee","rounded-es","rounded-tl","rounded-tr","rounded-br","rounded-bl"],"rounded-s":["rounded-ss","rounded-es"],"rounded-e":["rounded-se","rounded-ee"],"rounded-t":["rounded-tl","rounded-tr"],"rounded-r":["rounded-tr","rounded-br"],"rounded-b":["rounded-br","rounded-bl"],"rounded-l":["rounded-tl","rounded-bl"],"border-spacing":["border-spacing-x","border-spacing-y"],"border-w":["border-w-s","border-w-e","border-w-t","border-w-r","border-w-b","border-w-l"],"border-w-x":["border-w-r","border-w-l"],"border-w-y":["border-w-t","border-w-b"],"border-color":["border-color-s","border-color-e","border-color-t","border-color-r","border-color-b","border-color-l"],"border-color-x":["border-color-r","border-color-l"],"border-color-y":["border-color-t","border-color-b"],"scroll-m":["scroll-mx","scroll-my","scroll-ms","scroll-me","scroll-mt","scroll-mr","scroll-mb","scroll-ml"],"scroll-mx":["scroll-mr","scroll-ml"],"scroll-my":["scroll-mt","scroll-mb"],"scroll-p":["scroll-px","scroll-py","scroll-ps","scroll-pe","scroll-pt","scroll-pr","scroll-pb","scroll-pl"],"scroll-px":["scroll-pr","scroll-pl"],"scroll-py":["scroll-pt","scroll-pb"],touch:["touch-x","touch-y","touch-pz"],"touch-x":["touch"],"touch-y":["touch"],"touch-pz":["touch"]},conflictingClassGroupModifiers:{"font-size":["leading"]}}}),ac=((a,b)=>c=>{var d;if((null==b?void 0:b.variants)==null)return o(a,null==c?void 0:c.class,null==c?void 0:c.className);let{variants:e,defaultVariants:f}=b,g=Object.keys(e).map(a=>{let b=null==c?void 0:c[a],d=null==f?void 0:f[a];if(null===b)return null;let g=p(b)||p(d);return e[a][g]}),h=c&&Object.entries(c).reduce((a,b)=>{let[c,d]=b;return void 0===d||(a[c]=d),a},{});return o(a,g,null==b||null==(d=b.compoundVariants)?void 0:d.reduce((a,b)=>{let{class:c,className:d,...e}=b;return Object.entries(e).every(a=>{let[b,c]=a;return Array.isArray(c)?c.includes({...f,...h}[b]):({...f,...h})[b]===c})?[...a,c,d]:a},[]),null==c?void 0:c.class,null==c?void 0:c.className)})("inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-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",{variants:{variant:{default:"bg-primary text-primary-foreground shadow-xs hover:bg-primary/90",destructive:"bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",outline:"border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50",secondary:"bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80",ghost:"hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",link:"text-primary underline-offset-4 hover:underline"},size:{default:"h-9 px-4 py-2 has-[>svg]:px-3",sm:"h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5",lg:"h-10 rounded-md px-6 has-[>svg]:px-4",icon:"size-9"}},defaultVariants:{variant:"default",size:"default"}});function ad({className:a,variant:c,size:d,asChild:e=!1,...f}){return(0,b.jsx)(e?l:"button",{"data-slot":"button",className:function(...a){return ab(o(a))}(ac({variant:c,size:d,className:a})),...f})}function ae({darkMode:a,setDarkMode:c,className:d}){return(0,b.jsx)(ad,{variant:"ghost",size:"icon",onClick:()=>c(!a),className:d,"aria-label":a?"Switch to light mode":"Switch to dark mode",children:a?(0,b.jsx)(j,{className:"h-5 w-5 transition-all"}):(0,b.jsx)(i,{className:"h-5 w-5 transition-all"})})}function af(){let[a,b]=(0,c.useState)(()=>!1);return(0,c.useEffect)(()=>{localStorage.setItem("dev3000-dark-mode",JSON.stringify(a)),a?document.documentElement.classList.add("dark"):document.documentElement.classList.remove("dark")},[a]),(0,c.useEffect)(()=>{let a=window.matchMedia("(prefers-color-scheme: dark)"),c=a=>{null===localStorage.getItem("dev3000-dark-mode")&&b(a.matches)};return a.addEventListener("change",c),()=>a.removeEventListener("change",c)},[]),[a,b]}a.s(["DarkModeToggle",()=>ae],87896),a.s(["useDarkMode",()=>af],37825)}];
2
-
3
- //# sourceMappingURL=_62451611._.js.map