@moontra/moonui-pro 2.20.1 → 2.20.3

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 (162) hide show
  1. package/dist/index.d.ts +691 -261
  2. package/dist/index.mjs +7418 -4934
  3. package/package.json +11 -5
  4. package/plugin/index.d.ts +86 -0
  5. package/plugin/index.js +308 -0
  6. package/scripts/postbuild.js +27 -0
  7. package/scripts/postinstall.js +176 -23
  8. package/src/__tests__/use-intersection-observer.test.tsx +0 -216
  9. package/src/__tests__/use-local-storage.test.tsx +0 -174
  10. package/src/__tests__/use-pro-access.test.tsx +0 -183
  11. package/src/components/advanced-chart/advanced-chart.test.tsx +0 -281
  12. package/src/components/advanced-chart/index.tsx +0 -1242
  13. package/src/components/advanced-forms/index.tsx +0 -426
  14. package/src/components/animated-button/index.tsx +0 -385
  15. package/src/components/calendar/event-dialog.tsx +0 -372
  16. package/src/components/calendar/index.tsx +0 -1073
  17. package/src/components/calendar-pro/index.tsx +0 -1697
  18. package/src/components/color-picker/index.tsx +0 -432
  19. package/src/components/credit-card-input/index.tsx +0 -406
  20. package/src/components/dashboard/dashboard-grid.tsx +0 -462
  21. package/src/components/dashboard/demo.tsx +0 -425
  22. package/src/components/dashboard/index.tsx +0 -1046
  23. package/src/components/dashboard/time-range-picker.tsx +0 -336
  24. package/src/components/dashboard/types.ts +0 -222
  25. package/src/components/dashboard/widgets/activity-feed.tsx +0 -344
  26. package/src/components/dashboard/widgets/chart-widget.tsx +0 -418
  27. package/src/components/dashboard/widgets/metric-card.tsx +0 -343
  28. package/src/components/data-table/data-table-bulk-actions.tsx +0 -204
  29. package/src/components/data-table/data-table-column-toggle.tsx +0 -169
  30. package/src/components/data-table/data-table-export.ts +0 -156
  31. package/src/components/data-table/data-table-filter-drawer.tsx +0 -448
  32. package/src/components/data-table/data-table.test.tsx +0 -187
  33. package/src/components/data-table/index.tsx +0 -845
  34. package/src/components/draggable-list/index.tsx +0 -100
  35. package/src/components/enhanced/badge.tsx +0 -191
  36. package/src/components/enhanced/button.tsx +0 -362
  37. package/src/components/enhanced/card.tsx +0 -266
  38. package/src/components/enhanced/dialog.tsx +0 -246
  39. package/src/components/enhanced/index.ts +0 -4
  40. package/src/components/error-boundary/index.tsx +0 -109
  41. package/src/components/file-upload/file-upload.test.tsx +0 -243
  42. package/src/components/file-upload/index.tsx +0 -1660
  43. package/src/components/floating-action-button/index.tsx +0 -206
  44. package/src/components/form-wizard/form-wizard-context.tsx +0 -307
  45. package/src/components/form-wizard/form-wizard-navigation.tsx +0 -118
  46. package/src/components/form-wizard/form-wizard-progress.tsx +0 -298
  47. package/src/components/form-wizard/form-wizard-step.tsx +0 -111
  48. package/src/components/form-wizard/index.tsx +0 -102
  49. package/src/components/form-wizard/types.ts +0 -76
  50. package/src/components/gesture-drawer/index.tsx +0 -551
  51. package/src/components/github-stars/github-api.ts +0 -426
  52. package/src/components/github-stars/hooks.ts +0 -516
  53. package/src/components/github-stars/index.tsx +0 -375
  54. package/src/components/github-stars/types.ts +0 -148
  55. package/src/components/github-stars/variants.tsx +0 -513
  56. package/src/components/health-check/index.tsx +0 -439
  57. package/src/components/hover-card-3d/index.tsx +0 -530
  58. package/src/components/index.ts +0 -128
  59. package/src/components/internal/index.ts +0 -78
  60. package/src/components/kanban/add-card-modal.tsx +0 -502
  61. package/src/components/kanban/card-detail-modal.tsx +0 -761
  62. package/src/components/kanban/index.ts +0 -13
  63. package/src/components/kanban/kanban.tsx +0 -1684
  64. package/src/components/kanban/types.ts +0 -168
  65. package/src/components/lazy-component/index.tsx +0 -823
  66. package/src/components/license-error/index.tsx +0 -29
  67. package/src/components/magnetic-button/index.tsx +0 -167
  68. package/src/components/memory-efficient-data/index.tsx +0 -1016
  69. package/src/components/moonui-quiz-form/index.tsx +0 -817
  70. package/src/components/optimized-image/index.tsx +0 -425
  71. package/src/components/performance-debugger/index.tsx +0 -589
  72. package/src/components/performance-monitor/index.tsx +0 -794
  73. package/src/components/phone-number-input/index.tsx +0 -338
  74. package/src/components/pinch-zoom/index.tsx +0 -566
  75. package/src/components/quiz-form/index.tsx +0 -479
  76. package/src/components/rich-text-editor/index-old-backup.tsx +0 -437
  77. package/src/components/rich-text-editor/index.tsx +0 -2324
  78. package/src/components/rich-text-editor/slash-commands-extension.ts +0 -220
  79. package/src/components/rich-text-editor/slash-commands.css +0 -35
  80. package/src/components/rich-text-editor/table-styles.css +0 -65
  81. package/src/components/sidebar/index.tsx +0 -865
  82. package/src/components/spotlight-card/index.tsx +0 -191
  83. package/src/components/swipeable-card/index.tsx +0 -100
  84. package/src/components/timeline/index.tsx +0 -1148
  85. package/src/components/ui/accordion.tsx +0 -73
  86. package/src/components/ui/alert-dialog.tsx +0 -141
  87. package/src/components/ui/alert.tsx +0 -141
  88. package/src/components/ui/aspect-ratio.tsx +0 -245
  89. package/src/components/ui/avatar.tsx +0 -153
  90. package/src/components/ui/badge.tsx +0 -228
  91. package/src/components/ui/breadcrumb.tsx +0 -214
  92. package/src/components/ui/button.tsx +0 -222
  93. package/src/components/ui/calendar.tsx +0 -387
  94. package/src/components/ui/card.tsx +0 -214
  95. package/src/components/ui/checkbox.tsx +0 -259
  96. package/src/components/ui/collapsible.tsx +0 -135
  97. package/src/components/ui/color-picker.tsx +0 -97
  98. package/src/components/ui/command.tsx +0 -225
  99. package/src/components/ui/dialog.tsx +0 -334
  100. package/src/components/ui/dropdown-menu.tsx +0 -218
  101. package/src/components/ui/gesture-drawer.tsx +0 -11
  102. package/src/components/ui/hover-card.tsx +0 -29
  103. package/src/components/ui/index.ts +0 -190
  104. package/src/components/ui/input.tsx +0 -222
  105. package/src/components/ui/label.tsx +0 -29
  106. package/src/components/ui/lightbox.tsx +0 -606
  107. package/src/components/ui/magnetic-button.tsx +0 -129
  108. package/src/components/ui/media-gallery.tsx +0 -612
  109. package/src/components/ui/pagination.tsx +0 -123
  110. package/src/components/ui/popover.tsx +0 -185
  111. package/src/components/ui/progress.tsx +0 -30
  112. package/src/components/ui/radio-group.tsx +0 -257
  113. package/src/components/ui/scroll-area.tsx +0 -47
  114. package/src/components/ui/select.tsx +0 -374
  115. package/src/components/ui/separator.tsx +0 -145
  116. package/src/components/ui/sheet.tsx +0 -139
  117. package/src/components/ui/skeleton.tsx +0 -20
  118. package/src/components/ui/slider.tsx +0 -354
  119. package/src/components/ui/spotlight-card.tsx +0 -119
  120. package/src/components/ui/switch.tsx +0 -86
  121. package/src/components/ui/table.tsx +0 -329
  122. package/src/components/ui/tabs.tsx +0 -198
  123. package/src/components/ui/textarea.tsx +0 -28
  124. package/src/components/ui/toast.tsx +0 -317
  125. package/src/components/ui/toggle.tsx +0 -119
  126. package/src/components/ui/tooltip.tsx +0 -151
  127. package/src/components/virtual-list/index.tsx +0 -668
  128. package/src/hooks/use-chart.ts +0 -205
  129. package/src/hooks/use-data-table.ts +0 -182
  130. package/src/hooks/use-docs-pro-access.ts +0 -13
  131. package/src/hooks/use-license-check.ts +0 -65
  132. package/src/hooks/use-subscription.ts +0 -19
  133. package/src/hooks/use-toast.ts +0 -15
  134. package/src/index.ts +0 -14
  135. package/src/lib/ai-providers.ts +0 -377
  136. package/src/lib/component-metadata.ts +0 -18
  137. package/src/lib/micro-interactions.ts +0 -255
  138. package/src/lib/paddle.ts +0 -17
  139. package/src/lib/utils.ts +0 -6
  140. package/src/patterns/login-form/index.tsx +0 -276
  141. package/src/patterns/login-form/types.ts +0 -67
  142. package/src/setupTests.ts +0 -41
  143. package/src/styles/advanced-chart.css +0 -239
  144. package/src/styles/calendar.css +0 -35
  145. package/src/styles/design-system.css +0 -363
  146. package/src/styles/index.css +0 -85
  147. package/src/styles/tailwind.css +0 -7
  148. package/src/styles/tokens.css +0 -455
  149. package/src/types/moonui.d.ts +0 -22
  150. package/src/types/next-auth.d.ts +0 -21
  151. package/src/use-intersection-observer.tsx +0 -154
  152. package/src/use-local-storage.tsx +0 -71
  153. package/src/use-paddle.ts +0 -138
  154. package/src/use-performance-optimizer.ts +0 -389
  155. package/src/use-pro-access.ts +0 -141
  156. package/src/use-scroll-animation.ts +0 -219
  157. package/src/use-subscription.ts +0 -37
  158. package/src/use-toast.ts +0 -32
  159. package/src/utils/chart-helpers.ts +0 -357
  160. package/src/utils/cn.ts +0 -6
  161. package/src/utils/data-processing.ts +0 -151
  162. package/src/utils/license-validator.tsx +0 -183
@@ -1,794 +0,0 @@
1
- "use client"
2
-
3
- import React, { useState, useEffect, useRef, useCallback } from "react"
4
- import { motion, AnimatePresence } from "framer-motion"
5
- import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "../ui/card"
6
- import { Button } from "../ui/button"
7
- import { MoonUIBadgePro as Badge } from "../ui/badge"
8
- import { Tabs, TabsContent, TabsList, TabsTrigger } from "../ui/tabs"
9
- import { cn } from "../../lib/utils"
10
- import {
11
- Activity,
12
- Monitor,
13
- Cpu,
14
- MemoryStick,
15
- Network,
16
- HardDrive,
17
- Zap,
18
- Eye,
19
- EyeOff,
20
- BarChart3,
21
- TrendingUp,
22
- TrendingDown,
23
- AlertTriangle,
24
- CheckCircle,
25
- RefreshCw,
26
- Download,
27
- Lock,
28
- Sparkles,
29
- Timer,
30
- Gauge
31
- } from "lucide-react"
32
- import { useSubscription } from "../../hooks/use-subscription"
33
-
34
- interface PerformanceMetrics {
35
- cpu: {
36
- usage: number
37
- cores: number
38
- temperature?: number
39
- }
40
- memory: {
41
- used: number
42
- total: number
43
- available: number
44
- percentage: number
45
- }
46
- disk: {
47
- used: number
48
- total: number
49
- free: number
50
- percentage: number
51
- }
52
- network: {
53
- download: number
54
- upload: number
55
- latency: number
56
- }
57
- system: {
58
- uptime: number
59
- loadAverage: number[]
60
- processes: number
61
- }
62
- browser?: {
63
- jsHeapUsed: number
64
- jsHeapTotal: number
65
- jsHeapLimit: number
66
- }
67
- }
68
-
69
- interface PerformanceAlert {
70
- id: string
71
- type: "warning" | "critical" | "info"
72
- metric: string
73
- message: string
74
- value: number
75
- threshold: number
76
- timestamp: Date
77
- }
78
-
79
- interface PerformanceMonitorProps {
80
- autoRefresh?: boolean
81
- refreshInterval?: number
82
- showAlerts?: boolean
83
- alertThresholds?: {
84
- cpu: number
85
- memory: number
86
- disk: number
87
- network: number
88
- }
89
- showCharts?: boolean
90
- chartDuration?: number
91
- maxDataPoints?: number
92
- onAlert?: (alert: PerformanceAlert) => void
93
- onMetricsUpdate?: (metrics: PerformanceMetrics) => void
94
- className?: string
95
- }
96
-
97
- const PerformanceMonitorInternal: React.FC<PerformanceMonitorProps> = ({
98
- autoRefresh = true,
99
- refreshInterval = 5000,
100
- showAlerts = true,
101
- alertThresholds = {
102
- cpu: 80,
103
- memory: 85,
104
- disk: 90,
105
- network: 1000
106
- },
107
- showCharts = true,
108
- chartDuration = 300000, // 5 minutes
109
- maxDataPoints = 60,
110
- onAlert,
111
- onMetricsUpdate,
112
- className
113
- }) => {
114
- const [metrics, setMetrics] = useState<PerformanceMetrics | null>(null)
115
- const [history, setHistory] = useState<{ timestamp: number; metrics: PerformanceMetrics }[]>([])
116
- const [alerts, setAlerts] = useState<PerformanceAlert[]>([])
117
- const [isVisible, setIsVisible] = useState(true)
118
- const [isRefreshing, setIsRefreshing] = useState(false)
119
- const intervalRef = useRef<NodeJS.Timeout | undefined>(undefined)
120
-
121
- const generateMockMetrics = useCallback((): PerformanceMetrics => {
122
- const baseMetrics = metrics || {
123
- cpu: { usage: 25, cores: 8 },
124
- memory: { used: 4.2, total: 16, available: 11.8, percentage: 26 },
125
- disk: { used: 250, total: 500, free: 250, percentage: 50 },
126
- network: { download: 50, upload: 20, latency: 25 },
127
- system: { uptime: 86400, loadAverage: [1.2, 1.5, 1.8], processes: 120 }
128
- }
129
-
130
- // Simulate realistic variations
131
- const variance = 0.1
132
- return {
133
- cpu: {
134
- usage: Math.max(0, Math.min(100, baseMetrics.cpu.usage + (Math.random() - 0.5) * 20)),
135
- cores: baseMetrics.cpu.cores,
136
- temperature: 45 + Math.random() * 15
137
- },
138
- memory: {
139
- used: Math.max(0, baseMetrics.memory.used + (Math.random() - 0.5) * 2),
140
- total: baseMetrics.memory.total,
141
- available: baseMetrics.memory.total - baseMetrics.memory.used,
142
- percentage: Math.max(0, Math.min(100, baseMetrics.memory.percentage + (Math.random() - 0.5) * 10))
143
- },
144
- disk: {
145
- used: baseMetrics.disk.used + (Math.random() - 0.5) * 10,
146
- total: baseMetrics.disk.total,
147
- free: baseMetrics.disk.total - baseMetrics.disk.used,
148
- percentage: Math.max(0, Math.min(100, baseMetrics.disk.percentage + (Math.random() - 0.5) * 5))
149
- },
150
- network: {
151
- download: Math.max(0, baseMetrics.network.download + (Math.random() - 0.5) * 30),
152
- upload: Math.max(0, baseMetrics.network.upload + (Math.random() - 0.5) * 15),
153
- latency: Math.max(1, baseMetrics.network.latency + (Math.random() - 0.5) * 10)
154
- },
155
- system: {
156
- uptime: baseMetrics.system.uptime + refreshInterval / 1000,
157
- loadAverage: baseMetrics.system.loadAverage.map(load =>
158
- Math.max(0, load + (Math.random() - 0.5) * 0.2)
159
- ),
160
- processes: Math.max(50, baseMetrics.system.processes + Math.floor((Math.random() - 0.5) * 10))
161
- },
162
- browser: typeof window !== 'undefined' && 'memory' in performance ? {
163
- jsHeapUsed: (performance as any).memory.usedJSHeapSize / 1024 / 1024,
164
- jsHeapTotal: (performance as any).memory.totalJSHeapSize / 1024 / 1024,
165
- jsHeapLimit: (performance as any).memory.jsHeapSizeLimit / 1024 / 1024
166
- } : undefined
167
- }
168
- }, [metrics, refreshInterval])
169
-
170
- const checkAlerts = useCallback((newMetrics: PerformanceMetrics) => {
171
- const newAlerts: PerformanceAlert[] = []
172
- const now = new Date()
173
-
174
- // CPU Alert
175
- if (newMetrics.cpu.usage > alertThresholds.cpu) {
176
- newAlerts.push({
177
- id: `cpu-${Date.now()}`,
178
- type: newMetrics.cpu.usage > 95 ? "critical" : "warning",
179
- metric: "CPU",
180
- message: `CPU usage is ${newMetrics.cpu.usage.toFixed(1)}%`,
181
- value: newMetrics.cpu.usage,
182
- threshold: alertThresholds.cpu,
183
- timestamp: now
184
- })
185
- }
186
-
187
- // Memory Alert
188
- if (newMetrics.memory.percentage > alertThresholds.memory) {
189
- newAlerts.push({
190
- id: `memory-${Date.now()}`,
191
- type: newMetrics.memory.percentage > 95 ? "critical" : "warning",
192
- metric: "Memory",
193
- message: `Memory usage is ${newMetrics.memory.percentage.toFixed(1)}%`,
194
- value: newMetrics.memory.percentage,
195
- threshold: alertThresholds.memory,
196
- timestamp: now
197
- })
198
- }
199
-
200
- // Disk Alert
201
- if (newMetrics.disk.percentage > alertThresholds.disk) {
202
- newAlerts.push({
203
- id: `disk-${Date.now()}`,
204
- type: newMetrics.disk.percentage > 98 ? "critical" : "warning",
205
- metric: "Disk",
206
- message: `Disk usage is ${newMetrics.disk.percentage.toFixed(1)}%`,
207
- value: newMetrics.disk.percentage,
208
- threshold: alertThresholds.disk,
209
- timestamp: now
210
- })
211
- }
212
-
213
- // Network Latency Alert
214
- if (newMetrics.network.latency > alertThresholds.network) {
215
- newAlerts.push({
216
- id: `network-${Date.now()}`,
217
- type: "warning",
218
- metric: "Network",
219
- message: `High network latency: ${newMetrics.network.latency.toFixed(0)}ms`,
220
- value: newMetrics.network.latency,
221
- threshold: alertThresholds.network,
222
- timestamp: now
223
- })
224
- }
225
-
226
- if (newAlerts.length > 0) {
227
- setAlerts(prev => [...newAlerts, ...prev].slice(0, 20))
228
- newAlerts.forEach(alert => onAlert?.(alert))
229
- }
230
- }, [alertThresholds, onAlert])
231
-
232
- const updateMetrics = useCallback(async () => {
233
- setIsRefreshing(true)
234
-
235
- try {
236
- const newMetrics = generateMockMetrics()
237
- setMetrics(newMetrics)
238
-
239
- // Update history
240
- setHistory(prev => {
241
- const newHistory = [
242
- { timestamp: Date.now(), metrics: newMetrics },
243
- ...prev.slice(0, maxDataPoints - 1)
244
- ]
245
- return newHistory
246
- })
247
-
248
- // Check for alerts
249
- if (showAlerts) {
250
- checkAlerts(newMetrics)
251
- }
252
-
253
- onMetricsUpdate?.(newMetrics)
254
- } catch (error) {
255
- console.error("Failed to update metrics:", error)
256
- } finally {
257
- setIsRefreshing(false)
258
- }
259
- }, [generateMockMetrics, maxDataPoints, showAlerts, checkAlerts, onMetricsUpdate])
260
-
261
- // Initial load
262
- useEffect(() => {
263
- updateMetrics()
264
- }, [])
265
-
266
- // Auto refresh
267
- useEffect(() => {
268
- if (!autoRefresh) return
269
-
270
- intervalRef.current = setInterval(updateMetrics, refreshInterval)
271
- return () => {
272
- if (intervalRef.current) {
273
- clearInterval(intervalRef.current)
274
- }
275
- }
276
- }, [autoRefresh, refreshInterval, updateMetrics])
277
-
278
- const formatBytes = (bytes: number, decimals = 1): string => {
279
- if (bytes === 0) return '0 B'
280
- const k = 1024
281
- const dm = decimals < 0 ? 0 : decimals
282
- const sizes = ['B', 'KB', 'MB', 'GB', 'TB']
283
- const i = Math.floor(Math.log(bytes) / Math.log(k))
284
- return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i]
285
- }
286
-
287
- const formatUptime = (seconds: number): string => {
288
- const days = Math.floor(seconds / 86400)
289
- const hours = Math.floor((seconds % 86400) / 3600)
290
- const minutes = Math.floor((seconds % 3600) / 60)
291
-
292
- if (days > 0) return `${days}d ${hours}h ${minutes}m`
293
- if (hours > 0) return `${hours}h ${minutes}m`
294
- return `${minutes}m`
295
- }
296
-
297
- const getStatusColor = (percentage: number, thresholds = [70, 85]): string => {
298
- if (percentage >= thresholds[1]) return "text-red-500"
299
- if (percentage >= thresholds[0]) return "text-yellow-500"
300
- return "text-green-500"
301
- }
302
-
303
- const exportMetrics = () => {
304
- const data = {
305
- timestamp: new Date().toISOString(),
306
- currentMetrics: metrics,
307
- history: history.slice(0, 20),
308
- alerts: alerts.slice(0, 10)
309
- }
310
-
311
- const blob = new Blob([JSON.stringify(data, null, 2)], {
312
- type: 'application/json'
313
- })
314
-
315
- const url = URL.createObjectURL(blob)
316
- const link = document.createElement('a')
317
- link.href = url
318
- link.download = `performance-metrics-${Date.now()}.json`
319
- document.body.appendChild(link)
320
- link.click()
321
- document.body.removeChild(link)
322
- URL.revokeObjectURL(url)
323
- }
324
-
325
- if (!isVisible) {
326
- return (
327
- <Button
328
- variant="outline"
329
- size="sm"
330
- onClick={() => setIsVisible(true)}
331
- className="fixed bottom-4 left-4 z-50"
332
- >
333
- <Monitor className="h-4 w-4 mr-2" />
334
- Performance
335
- </Button>
336
- )
337
- }
338
-
339
- if (!metrics) {
340
- return (
341
- <Card className={cn("w-full max-w-6xl", className)}>
342
- <CardContent className="p-6">
343
- <div className="text-center">
344
- <Activity className="h-12 w-12 animate-pulse mx-auto mb-4 text-muted-foreground" />
345
- <p className="text-muted-foreground">Loading performance metrics...</p>
346
- </div>
347
- </CardContent>
348
- </Card>
349
- )
350
- }
351
-
352
- return (
353
- <Card className={cn("w-full max-w-6xl", className)}>
354
- <CardHeader>
355
- <div className="flex items-center justify-between">
356
- <div>
357
- <CardTitle className="flex items-center gap-2">
358
- <Monitor className="h-5 w-5" />
359
- Performance Monitor
360
- </CardTitle>
361
- <CardDescription>
362
- Real-time system performance monitoring and alerts
363
- </CardDescription>
364
- </div>
365
-
366
- <div className="flex items-center gap-2">
367
- <Badge variant={autoRefresh ? "outline" : "secondary"} className="gap-1">
368
- {autoRefresh ? <Activity className="h-3 w-3 animate-pulse" /> : <Timer className="h-3 w-3" />}
369
- {autoRefresh ? "Live" : "Paused"}
370
- </Badge>
371
-
372
- {showAlerts && alerts.length > 0 && (
373
- <Badge variant="destructive" className="gap-1">
374
- <AlertTriangle className="h-3 w-3" />
375
- {alerts.length}
376
- </Badge>
377
- )}
378
-
379
- <Button
380
- variant="outline"
381
- size="sm"
382
- onClick={updateMetrics}
383
- disabled={isRefreshing}
384
- >
385
- <RefreshCw className={cn("h-4 w-4", isRefreshing && "animate-spin")} />
386
- </Button>
387
-
388
- <Button
389
- variant="outline"
390
- size="sm"
391
- onClick={exportMetrics}
392
- >
393
- <Download className="h-4 w-4" />
394
- </Button>
395
-
396
- <Button
397
- variant="ghost"
398
- size="sm"
399
- onClick={() => setIsVisible(false)}
400
- >
401
- <EyeOff className="h-4 w-4" />
402
- </Button>
403
- </div>
404
- </div>
405
- </CardHeader>
406
-
407
- <CardContent>
408
- <Tabs defaultValue="overview" className="w-full">
409
- <TabsList className="grid w-full grid-cols-4">
410
- <TabsTrigger value="overview">Overview</TabsTrigger>
411
- <TabsTrigger value="details">Details</TabsTrigger>
412
- <TabsTrigger value="alerts">Alerts</TabsTrigger>
413
- <TabsTrigger value="history">History</TabsTrigger>
414
- </TabsList>
415
-
416
- <TabsContent value="overview" className="space-y-6">
417
- {/* Key Metrics Grid */}
418
- <div className="grid grid-cols-2 md:grid-cols-4 gap-4">
419
- <Card>
420
- <CardContent className="p-4">
421
- <div className="flex items-center justify-between">
422
- <div className="flex items-center gap-2">
423
- <Cpu className="h-4 w-4 text-blue-500" />
424
- <span className="text-sm font-medium">CPU</span>
425
- </div>
426
- <span className={cn("font-bold", getStatusColor(metrics.cpu.usage))}>
427
- {metrics.cpu.usage.toFixed(1)}%
428
- </span>
429
- </div>
430
- <div className="h-2 mt-2 bg-secondary rounded-full overflow-hidden">
431
- <div
432
- className="h-full bg-primary transition-all duration-300 ease-out"
433
- style={{ width: `${metrics.cpu.usage}%` }}
434
- />
435
- </div>
436
- <div className="text-xs text-muted-foreground mt-1">
437
- {metrics.cpu.cores} cores {metrics.cpu.temperature && `• ${metrics.cpu.temperature.toFixed(0)}°C`}
438
- </div>
439
- </CardContent>
440
- </Card>
441
-
442
- <Card>
443
- <CardContent className="p-4">
444
- <div className="flex items-center justify-between">
445
- <div className="flex items-center gap-2">
446
- <MemoryStick className="h-4 w-4 text-green-500" />
447
- <span className="text-sm font-medium">Memory</span>
448
- </div>
449
- <span className={cn("font-bold", getStatusColor(metrics.memory.percentage))}>
450
- {metrics.memory.percentage.toFixed(1)}%
451
- </span>
452
- </div>
453
- <div className="h-2 mt-2 bg-secondary rounded-full overflow-hidden">
454
- <div
455
- className="h-full bg-primary transition-all duration-300 ease-out"
456
- style={{ width: `${metrics.memory.percentage}%` }}
457
- />
458
- </div>
459
- <div className="text-xs text-muted-foreground mt-1">
460
- {formatBytes(metrics.memory.used * 1024 * 1024 * 1024)} / {formatBytes(metrics.memory.total * 1024 * 1024 * 1024)}
461
- </div>
462
- </CardContent>
463
- </Card>
464
-
465
- <Card>
466
- <CardContent className="p-4">
467
- <div className="flex items-center justify-between">
468
- <div className="flex items-center gap-2">
469
- <HardDrive className="h-4 w-4 text-purple-500" />
470
- <span className="text-sm font-medium">Disk</span>
471
- </div>
472
- <span className={cn("font-bold", getStatusColor(metrics.disk.percentage, [80, 90]))}>
473
- {metrics.disk.percentage.toFixed(1)}%
474
- </span>
475
- </div>
476
- <div className="h-2 mt-2 bg-secondary rounded-full overflow-hidden">
477
- <div
478
- className="h-full bg-primary transition-all duration-300 ease-out"
479
- style={{ width: `${metrics.disk.percentage}%` }}
480
- />
481
- </div>
482
- <div className="text-xs text-muted-foreground mt-1">
483
- {formatBytes(metrics.disk.used * 1024 * 1024 * 1024)} / {formatBytes(metrics.disk.total * 1024 * 1024 * 1024)}
484
- </div>
485
- </CardContent>
486
- </Card>
487
-
488
- <Card>
489
- <CardContent className="p-4">
490
- <div className="flex items-center justify-between">
491
- <div className="flex items-center gap-2">
492
- <Network className="h-4 w-4 text-orange-500" />
493
- <span className="text-sm font-medium">Network</span>
494
- </div>
495
- <span className={cn("font-bold", getStatusColor(metrics.network.latency, [50, 100]))}>
496
- {metrics.network.latency.toFixed(0)}ms
497
- </span>
498
- </div>
499
- <div className="text-xs text-muted-foreground mt-2">
500
- ↓ {metrics.network.download.toFixed(0)} MB/s • ↑ {metrics.network.upload.toFixed(0)} MB/s
501
- </div>
502
- </CardContent>
503
- </Card>
504
- </div>
505
-
506
- {/* System Info */}
507
- <div className="grid grid-cols-1 md:grid-cols-2 gap-6">
508
- <Card>
509
- <CardHeader>
510
- <CardTitle className="text-base">System Information</CardTitle>
511
- </CardHeader>
512
- <CardContent className="space-y-3">
513
- <div className="flex justify-between text-sm">
514
- <span className="text-muted-foreground">Uptime:</span>
515
- <span className="font-medium">{formatUptime(metrics.system.uptime)}</span>
516
- </div>
517
- <div className="flex justify-between text-sm">
518
- <span className="text-muted-foreground">Processes:</span>
519
- <span className="font-medium">{metrics.system.processes}</span>
520
- </div>
521
- <div className="flex justify-between text-sm">
522
- <span className="text-muted-foreground">Load Average:</span>
523
- <span className="font-medium">
524
- {metrics.system.loadAverage.map(load => load.toFixed(2)).join(", ")}
525
- </span>
526
- </div>
527
- </CardContent>
528
- </Card>
529
-
530
- {metrics.browser && (
531
- <Card>
532
- <CardHeader>
533
- <CardTitle className="text-base">Browser Memory</CardTitle>
534
- </CardHeader>
535
- <CardContent className="space-y-3">
536
- <div className="flex justify-between text-sm">
537
- <span className="text-muted-foreground">JS Heap Used:</span>
538
- <span className="font-medium">{formatBytes(metrics.browser.jsHeapUsed * 1024 * 1024)}</span>
539
- </div>
540
- <div className="flex justify-between text-sm">
541
- <span className="text-muted-foreground">JS Heap Total:</span>
542
- <span className="font-medium">{formatBytes(metrics.browser.jsHeapTotal * 1024 * 1024)}</span>
543
- </div>
544
- <div className="flex justify-between text-sm">
545
- <span className="text-muted-foreground">JS Heap Limit:</span>
546
- <span className="font-medium">{formatBytes(metrics.browser.jsHeapLimit * 1024 * 1024)}</span>
547
- </div>
548
- </CardContent>
549
- </Card>
550
- )}
551
- </div>
552
- </TabsContent>
553
-
554
- <TabsContent value="details" className="space-y-4">
555
- <div className="grid grid-cols-1 md:grid-cols-2 gap-6">
556
- {/* Detailed CPU Info */}
557
- <Card>
558
- <CardHeader>
559
- <CardTitle className="text-base flex items-center gap-2">
560
- <Cpu className="h-4 w-4" />
561
- CPU Details
562
- </CardTitle>
563
- </CardHeader>
564
- <CardContent className="space-y-4">
565
- <div>
566
- <div className="flex justify-between text-sm mb-2">
567
- <span>Usage</span>
568
- <span className={getStatusColor(metrics.cpu.usage)}>{metrics.cpu.usage.toFixed(1)}%</span>
569
- </div>
570
- <div className="h-2 bg-secondary rounded-full overflow-hidden">
571
- <div
572
- className="h-full bg-primary transition-all duration-300 ease-out"
573
- style={{ width: `${metrics.cpu.usage}%` }}
574
- />
575
- </div>
576
- </div>
577
- <div className="grid grid-cols-2 gap-4 text-sm">
578
- <div>
579
- <span className="text-muted-foreground">Cores:</span>
580
- <span className="ml-2 font-medium">{metrics.cpu.cores}</span>
581
- </div>
582
- {metrics.cpu.temperature && (
583
- <div>
584
- <span className="text-muted-foreground">Temperature:</span>
585
- <span className="ml-2 font-medium">{metrics.cpu.temperature.toFixed(0)}°C</span>
586
- </div>
587
- )}
588
- </div>
589
- </CardContent>
590
- </Card>
591
-
592
- {/* Detailed Memory Info */}
593
- <Card>
594
- <CardHeader>
595
- <CardTitle className="text-base flex items-center gap-2">
596
- <MemoryStick className="h-4 w-4" />
597
- Memory Details
598
- </CardTitle>
599
- </CardHeader>
600
- <CardContent className="space-y-4">
601
- <div>
602
- <div className="flex justify-between text-sm mb-2">
603
- <span>Usage</span>
604
- <span className={getStatusColor(metrics.memory.percentage)}>{metrics.memory.percentage.toFixed(1)}%</span>
605
- </div>
606
- <div className="h-2 bg-secondary rounded-full overflow-hidden">
607
- <div
608
- className="h-full bg-primary transition-all duration-300 ease-out"
609
- style={{ width: `${metrics.memory.percentage}%` }}
610
- />
611
- </div>
612
- </div>
613
- <div className="space-y-2 text-sm">
614
- <div className="flex justify-between">
615
- <span className="text-muted-foreground">Used:</span>
616
- <span className="font-medium">{formatBytes(metrics.memory.used * 1024 * 1024 * 1024)}</span>
617
- </div>
618
- <div className="flex justify-between">
619
- <span className="text-muted-foreground">Available:</span>
620
- <span className="font-medium">{formatBytes(metrics.memory.available * 1024 * 1024 * 1024)}</span>
621
- </div>
622
- <div className="flex justify-between">
623
- <span className="text-muted-foreground">Total:</span>
624
- <span className="font-medium">{formatBytes(metrics.memory.total * 1024 * 1024 * 1024)}</span>
625
- </div>
626
- </div>
627
- </CardContent>
628
- </Card>
629
- </div>
630
- </TabsContent>
631
-
632
- <TabsContent value="alerts" className="space-y-4">
633
- <div className="flex items-center justify-between">
634
- <div className="text-sm text-muted-foreground">
635
- {alerts.length} alerts
636
- </div>
637
- <Button
638
- variant="outline"
639
- size="sm"
640
- onClick={() => setAlerts([])}
641
- disabled={alerts.length === 0}
642
- >
643
- Clear All
644
- </Button>
645
- </div>
646
-
647
- <div className="space-y-2 max-h-96 overflow-y-auto">
648
- <AnimatePresence>
649
- {alerts.map((alert, index) => (
650
- <motion.div
651
- key={alert.id}
652
- initial={{ opacity: 0, x: -20 }}
653
- animate={{ opacity: 1, x: 0 }}
654
- exit={{ opacity: 0, x: 20 }}
655
- transition={{ delay: index * 0.05 }}
656
- >
657
- <Card>
658
- <CardContent className="p-4">
659
- <div className="flex items-center justify-between">
660
- <div className="flex items-center gap-3">
661
- {alert.type === "critical" ? (
662
- <AlertTriangle className="h-4 w-4 text-red-500" />
663
- ) : alert.type === "warning" ? (
664
- <AlertTriangle className="h-4 w-4 text-yellow-500" />
665
- ) : (
666
- <CheckCircle className="h-4 w-4 text-blue-500" />
667
- )}
668
- <div>
669
- <div className="font-medium text-sm">{alert.metric}</div>
670
- <div className="text-sm text-muted-foreground">{alert.message}</div>
671
- </div>
672
- </div>
673
- <div className="text-right text-sm">
674
- <div className="font-medium">
675
- {alert.value.toFixed(1)}{alert.metric === "Network" ? "ms" : "%"}
676
- </div>
677
- <div className="text-xs text-muted-foreground">
678
- {alert.timestamp.toLocaleTimeString()}
679
- </div>
680
- </div>
681
- </div>
682
- </CardContent>
683
- </Card>
684
- </motion.div>
685
- ))}
686
- </AnimatePresence>
687
- </div>
688
-
689
- {alerts.length === 0 && (
690
- <div className="text-center py-8">
691
- <CheckCircle className="h-12 w-12 mx-auto mb-4 text-green-500" />
692
- <p className="text-muted-foreground">No alerts - System is running smoothly</p>
693
- </div>
694
- )}
695
- </TabsContent>
696
-
697
- <TabsContent value="history" className="space-y-4">
698
- <div className="text-sm text-muted-foreground">
699
- Last {history.length} data points ({Math.round(chartDuration / 60000)} minutes)
700
- </div>
701
-
702
- {showCharts && history.length > 1 && (
703
- <div className="grid grid-cols-1 md:grid-cols-2 gap-6">
704
- {/* Simple CPU History Chart */}
705
- <Card>
706
- <CardHeader>
707
- <CardTitle className="text-base">CPU Usage Trend</CardTitle>
708
- </CardHeader>
709
- <CardContent>
710
- <div className="h-32 flex items-end justify-between gap-1">
711
- {history.slice(-20).reverse().map((point, index) => (
712
- <div
713
- key={index}
714
- className="bg-blue-500 rounded-t min-w-[4px] flex-1 transition-all"
715
- style={{ height: `${(point.metrics.cpu.usage / 100) * 128}px` }}
716
- />
717
- ))}
718
- </div>
719
- <div className="text-xs text-muted-foreground mt-2 text-center">
720
- Last 20 readings
721
- </div>
722
- </CardContent>
723
- </Card>
724
-
725
- {/* Simple Memory History Chart */}
726
- <Card>
727
- <CardHeader>
728
- <CardTitle className="text-base">Memory Usage Trend</CardTitle>
729
- </CardHeader>
730
- <CardContent>
731
- <div className="h-32 flex items-end justify-between gap-1">
732
- {history.slice(-20).reverse().map((point, index) => (
733
- <div
734
- key={index}
735
- className="bg-green-500 rounded-t min-w-[4px] flex-1 transition-all"
736
- style={{ height: `${(point.metrics.memory.percentage / 100) * 128}px` }}
737
- />
738
- ))}
739
- </div>
740
- <div className="text-xs text-muted-foreground mt-2 text-center">
741
- Last 20 readings
742
- </div>
743
- </CardContent>
744
- </Card>
745
- </div>
746
- )}
747
-
748
- {history.length === 0 && (
749
- <div className="text-center py-8">
750
- <BarChart3 className="h-12 w-12 mx-auto mb-4 text-muted-foreground" />
751
- <p className="text-muted-foreground">No historical data available</p>
752
- </div>
753
- )}
754
- </TabsContent>
755
- </Tabs>
756
- </CardContent>
757
- </Card>
758
- )
759
- }
760
-
761
- export const PerformanceMonitor: React.FC<PerformanceMonitorProps> = ({ className, ...props }) => {
762
- const { hasProAccess, isLoading } = useSubscription()
763
-
764
- // If no pro access, show upgrade prompt
765
- if (!isLoading && !hasProAccess) {
766
- return (
767
- <Card className={cn("w-fit", className)}>
768
- <CardContent className="py-6 text-center">
769
- <div className="space-y-4">
770
- <div className="rounded-full bg-purple-100 dark:bg-purple-900/30 p-3 w-fit mx-auto">
771
- <Lock className="h-6 w-6 text-purple-600 dark:text-purple-400" />
772
- </div>
773
- <div>
774
- <h3 className="font-semibold text-sm mb-2">Pro Feature</h3>
775
- <p className="text-muted-foreground text-xs mb-4">
776
- Performance Monitor is available exclusively to MoonUI Pro subscribers.
777
- </p>
778
- <a href="/pricing">
779
- <Button size="sm">
780
- <Sparkles className="mr-2 h-4 w-4" />
781
- Upgrade to Pro
782
- </Button>
783
- </a>
784
- </div>
785
- </div>
786
- </CardContent>
787
- </Card>
788
- )
789
- }
790
-
791
- return <PerformanceMonitorInternal className={className} {...props} />
792
- }
793
-
794
- export type { PerformanceMetrics, PerformanceAlert, PerformanceMonitorProps }