@moontra/moonui-pro 2.0.22 → 2.1.0
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.
- package/dist/index.mjs +215 -214
- package/package.json +4 -2
- package/src/__tests__/use-intersection-observer.test.tsx +216 -0
- package/src/__tests__/use-local-storage.test.tsx +174 -0
- package/src/__tests__/use-pro-access.test.tsx +183 -0
- package/src/components/advanced-chart/advanced-chart.test.tsx +281 -0
- package/src/components/advanced-chart/index.tsx +412 -0
- package/src/components/advanced-forms/index.tsx +431 -0
- package/src/components/animated-button/index.tsx +202 -0
- package/src/components/calendar/event-dialog.tsx +372 -0
- package/src/components/calendar/index.tsx +557 -0
- package/src/components/color-picker/index.tsx +434 -0
- package/src/components/dashboard/index.tsx +334 -0
- package/src/components/data-table/data-table.test.tsx +187 -0
- package/src/components/data-table/index.tsx +368 -0
- package/src/components/draggable-list/index.tsx +100 -0
- package/src/components/enhanced/button.tsx +360 -0
- package/src/components/enhanced/card.tsx +272 -0
- package/src/components/enhanced/dialog.tsx +248 -0
- package/src/components/enhanced/index.ts +3 -0
- package/src/components/error-boundary/index.tsx +111 -0
- package/src/components/file-upload/file-upload.test.tsx +242 -0
- package/src/components/file-upload/index.tsx +362 -0
- package/src/components/floating-action-button/index.tsx +209 -0
- package/src/components/github-stars/index.tsx +414 -0
- package/src/components/health-check/index.tsx +441 -0
- package/src/components/hover-card-3d/index.tsx +170 -0
- package/src/components/index.ts +76 -0
- package/src/components/kanban/index.tsx +436 -0
- package/src/components/lazy-component/index.tsx +342 -0
- package/src/components/magnetic-button/index.tsx +170 -0
- package/src/components/memory-efficient-data/index.tsx +352 -0
- package/src/components/optimized-image/index.tsx +427 -0
- package/src/components/performance-debugger/index.tsx +591 -0
- package/src/components/performance-monitor/index.tsx +775 -0
- package/src/components/pinch-zoom/index.tsx +172 -0
- package/src/components/rich-text-editor/index-old-backup.tsx +443 -0
- package/src/components/rich-text-editor/index.tsx +1537 -0
- package/src/components/rich-text-editor/slash-commands-extension.ts +220 -0
- package/src/components/rich-text-editor/slash-commands.css +35 -0
- package/src/components/rich-text-editor/table-styles.css +65 -0
- package/src/components/spotlight-card/index.tsx +194 -0
- package/src/components/swipeable-card/index.tsx +100 -0
- package/src/components/timeline/index.tsx +333 -0
- package/src/components/ui/animated-button.tsx +185 -0
- package/src/components/ui/avatar.tsx +135 -0
- package/src/components/ui/badge.tsx +225 -0
- package/src/components/ui/button.tsx +221 -0
- package/src/components/ui/card.tsx +141 -0
- package/src/components/ui/checkbox.tsx +256 -0
- package/src/components/ui/color-picker.tsx +95 -0
- package/src/components/ui/dialog.tsx +332 -0
- package/src/components/ui/dropdown-menu.tsx +200 -0
- package/src/components/ui/hover-card-3d.tsx +103 -0
- package/src/components/ui/index.ts +33 -0
- package/src/components/ui/input.tsx +219 -0
- package/src/components/ui/label.tsx +26 -0
- package/src/components/ui/magnetic-button.tsx +129 -0
- package/src/components/ui/popover.tsx +183 -0
- package/src/components/ui/select.tsx +273 -0
- package/src/components/ui/separator.tsx +140 -0
- package/src/components/ui/slider.tsx +351 -0
- package/src/components/ui/spotlight-card.tsx +119 -0
- package/src/components/ui/switch.tsx +83 -0
- package/src/components/ui/tabs.tsx +195 -0
- package/src/components/ui/textarea.tsx +25 -0
- package/src/components/ui/toast.tsx +313 -0
- package/src/components/ui/tooltip.tsx +152 -0
- package/src/components/virtual-list/index.tsx +369 -0
- package/src/hooks/use-chart.ts +205 -0
- package/src/hooks/use-data-table.ts +182 -0
- package/src/hooks/use-docs-pro-access.ts +13 -0
- package/src/hooks/use-license-check.ts +65 -0
- package/src/hooks/use-subscription.ts +19 -0
- package/src/index.ts +14 -0
- package/src/lib/micro-interactions.ts +255 -0
- package/src/lib/utils.ts +6 -0
- package/src/patterns/login-form/index.tsx +276 -0
- package/src/patterns/login-form/types.ts +67 -0
- package/src/setupTests.ts +41 -0
- package/src/styles/design-system.css +365 -0
- package/src/styles/index.css +4 -0
- package/src/styles/tailwind.css +6 -0
- package/src/styles/tokens.css +453 -0
- package/src/types/moonui.d.ts +22 -0
- package/src/use-intersection-observer.tsx +154 -0
- package/src/use-local-storage.tsx +71 -0
- package/src/use-paddle.ts +138 -0
- package/src/use-performance-optimizer.ts +379 -0
- package/src/use-pro-access.ts +141 -0
- package/src/use-scroll-animation.ts +221 -0
- package/src/use-subscription.ts +37 -0
- package/src/use-toast.ts +32 -0
- package/src/utils/chart-helpers.ts +257 -0
- package/src/utils/cn.ts +69 -0
- package/src/utils/data-processing.ts +151 -0
- package/src/utils/license-guard.tsx +177 -0
- package/src/utils/license-validator.tsx +183 -0
- package/src/utils/package-guard.ts +60 -0
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import React, { useMemo, useCallback, useState, useEffect, useRef } from 'react'
|
|
4
|
+
import { cn } from '../../lib/utils'
|
|
5
|
+
|
|
6
|
+
// Memory konfigürasyonu için tip tanımları
|
|
7
|
+
export interface MemoryConfig {
|
|
8
|
+
chunkSize?: number
|
|
9
|
+
maxMemoryItems?: number
|
|
10
|
+
cacheStrategy?: 'lru' | 'fifo' | 'lfu'
|
|
11
|
+
compression?: boolean
|
|
12
|
+
autoCleanup?: boolean
|
|
13
|
+
cleanupThreshold?: number
|
|
14
|
+
streamingMode?: boolean
|
|
15
|
+
enableAnalytics?: boolean
|
|
16
|
+
analyticsCallback?: (stats: MemoryStats) => void
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// Memory istatistikleri için tip tanımı
|
|
20
|
+
export interface MemoryStats {
|
|
21
|
+
memoryUsage: number
|
|
22
|
+
itemCount: number
|
|
23
|
+
cacheHitRate: number
|
|
24
|
+
compressionRatio?: number
|
|
25
|
+
lastCleanup?: number
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Ana component props
|
|
29
|
+
export interface MemoryEfficientDataProps<T = any> {
|
|
30
|
+
data: T[]
|
|
31
|
+
config?: MemoryConfig
|
|
32
|
+
renderItem: (item: T, index: number) => React.ReactNode
|
|
33
|
+
height?: number
|
|
34
|
+
onMemoryUpdate?: (stats: MemoryStats) => void
|
|
35
|
+
className?: string
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Cache node yapısı
|
|
39
|
+
interface CacheNode<T> {
|
|
40
|
+
data: T[]
|
|
41
|
+
timestamp: number
|
|
42
|
+
accessCount: number
|
|
43
|
+
compressed?: boolean
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Memory cache sınıfı
|
|
47
|
+
class MemoryCache<T> {
|
|
48
|
+
private cache = new Map<string, CacheNode<T>>()
|
|
49
|
+
private maxSize: number
|
|
50
|
+
private strategy: 'lru' | 'fifo' | 'lfu'
|
|
51
|
+
|
|
52
|
+
constructor(maxSize: number, strategy: 'lru' | 'fifo' | 'lfu' = 'lru') {
|
|
53
|
+
this.maxSize = maxSize
|
|
54
|
+
this.strategy = strategy
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
set(key: string, data: T[], compressed = false): void {
|
|
58
|
+
if (this.cache.size >= this.maxSize) {
|
|
59
|
+
this.evict()
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
this.cache.set(key, {
|
|
63
|
+
data,
|
|
64
|
+
timestamp: Date.now(),
|
|
65
|
+
accessCount: 0,
|
|
66
|
+
compressed
|
|
67
|
+
})
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
get(key: string): T[] | null {
|
|
71
|
+
const node = this.cache.get(key)
|
|
72
|
+
if (!node) return null
|
|
73
|
+
|
|
74
|
+
// Access count'ı artır (LFU için)
|
|
75
|
+
node.accessCount++
|
|
76
|
+
node.timestamp = Date.now() // LRU için timestamp güncelle
|
|
77
|
+
|
|
78
|
+
return node.data
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
private evict(): void {
|
|
82
|
+
if (this.cache.size === 0) return
|
|
83
|
+
|
|
84
|
+
let keyToDelete: string | null = null
|
|
85
|
+
|
|
86
|
+
switch (this.strategy) {
|
|
87
|
+
case 'lru':
|
|
88
|
+
// En eski erişileni sil
|
|
89
|
+
let oldestTime = Infinity
|
|
90
|
+
for (const [key, node] of this.cache) {
|
|
91
|
+
if (node.timestamp < oldestTime) {
|
|
92
|
+
oldestTime = node.timestamp
|
|
93
|
+
keyToDelete = key
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
break
|
|
97
|
+
|
|
98
|
+
case 'lfu':
|
|
99
|
+
// En az kullanılanı sil
|
|
100
|
+
let minAccess = Infinity
|
|
101
|
+
for (const [key, node] of this.cache) {
|
|
102
|
+
if (node.accessCount < minAccess) {
|
|
103
|
+
minAccess = node.accessCount
|
|
104
|
+
keyToDelete = key
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
break
|
|
108
|
+
|
|
109
|
+
case 'fifo':
|
|
110
|
+
// İlk gireni sil
|
|
111
|
+
keyToDelete = this.cache.keys().next().value
|
|
112
|
+
break
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (keyToDelete) {
|
|
116
|
+
this.cache.delete(keyToDelete)
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
clear(): void {
|
|
121
|
+
this.cache.clear()
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
getStats(): { size: number; hitRate: number } {
|
|
125
|
+
return {
|
|
126
|
+
size: this.cache.size,
|
|
127
|
+
hitRate: 0.95 // Basit bir mock değer
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Ana Memory Efficient Data Component
|
|
133
|
+
export function MemoryEfficientData<T = any>({
|
|
134
|
+
data,
|
|
135
|
+
config = {},
|
|
136
|
+
renderItem,
|
|
137
|
+
height = 400,
|
|
138
|
+
onMemoryUpdate,
|
|
139
|
+
className
|
|
140
|
+
}: MemoryEfficientDataProps<T>) {
|
|
141
|
+
const {
|
|
142
|
+
chunkSize = 1000,
|
|
143
|
+
maxMemoryItems = 10000,
|
|
144
|
+
cacheStrategy = 'lru',
|
|
145
|
+
compression = false,
|
|
146
|
+
autoCleanup = true,
|
|
147
|
+
cleanupThreshold = 0.8,
|
|
148
|
+
streamingMode = false,
|
|
149
|
+
enableAnalytics = false,
|
|
150
|
+
analyticsCallback
|
|
151
|
+
} = config
|
|
152
|
+
|
|
153
|
+
// State yönetimi
|
|
154
|
+
const [visibleRange, setVisibleRange] = useState({ start: 0, end: Math.min(chunkSize, data.length) })
|
|
155
|
+
const [memoryStats, setMemoryStats] = useState<MemoryStats>({
|
|
156
|
+
memoryUsage: 0,
|
|
157
|
+
itemCount: 0,
|
|
158
|
+
cacheHitRate: 0.95
|
|
159
|
+
})
|
|
160
|
+
|
|
161
|
+
// Refs
|
|
162
|
+
const containerRef = useRef<HTMLDivElement>(null)
|
|
163
|
+
const cacheRef = useRef(new MemoryCache<T>(Math.floor(maxMemoryItems / chunkSize), cacheStrategy))
|
|
164
|
+
const scrollTimeoutRef = useRef<NodeJS.Timeout>()
|
|
165
|
+
|
|
166
|
+
// Visible data'yı memoize et
|
|
167
|
+
const visibleData = useMemo(() => {
|
|
168
|
+
const start = visibleRange.start
|
|
169
|
+
const end = Math.min(visibleRange.end, data.length)
|
|
170
|
+
|
|
171
|
+
// Cache'den kontrol et
|
|
172
|
+
const cacheKey = `${start}-${end}`
|
|
173
|
+
const cachedData = cacheRef.current.get(cacheKey)
|
|
174
|
+
|
|
175
|
+
if (cachedData && cachedData.length === (end - start)) {
|
|
176
|
+
return cachedData
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// Yeni data slice'ını oluştur
|
|
180
|
+
const newData = data.slice(start, end)
|
|
181
|
+
|
|
182
|
+
// Cache'e kaydet
|
|
183
|
+
cacheRef.current.set(cacheKey, newData, compression)
|
|
184
|
+
|
|
185
|
+
return newData
|
|
186
|
+
}, [data, visibleRange, compression])
|
|
187
|
+
|
|
188
|
+
// Scroll handler
|
|
189
|
+
const handleScroll = useCallback((e: React.UIEvent<HTMLDivElement>) => {
|
|
190
|
+
const scrollTop = e.currentTarget.scrollTop
|
|
191
|
+
const containerHeight = e.currentTarget.clientHeight
|
|
192
|
+
|
|
193
|
+
// Tahmini item yüksekliği (temel implementasyon)
|
|
194
|
+
const estimatedItemHeight = 60
|
|
195
|
+
const startIndex = Math.floor(scrollTop / estimatedItemHeight)
|
|
196
|
+
const visibleCount = Math.ceil(containerHeight / estimatedItemHeight)
|
|
197
|
+
|
|
198
|
+
// Buffer ekle
|
|
199
|
+
const bufferSize = Math.floor(visibleCount * 0.5)
|
|
200
|
+
const newStart = Math.max(0, startIndex - bufferSize)
|
|
201
|
+
const newEnd = Math.min(data.length, startIndex + visibleCount + bufferSize)
|
|
202
|
+
|
|
203
|
+
// Throttle scroll updates
|
|
204
|
+
if (scrollTimeoutRef.current) {
|
|
205
|
+
clearTimeout(scrollTimeoutRef.current)
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
scrollTimeoutRef.current = setTimeout(() => {
|
|
209
|
+
setVisibleRange({ start: newStart, end: newEnd })
|
|
210
|
+
}, 16) // ~60fps
|
|
211
|
+
}, [data.length])
|
|
212
|
+
|
|
213
|
+
// Memory statistics'i güncelle
|
|
214
|
+
useEffect(() => {
|
|
215
|
+
const cacheStats = cacheRef.current.getStats()
|
|
216
|
+
const newStats: MemoryStats = {
|
|
217
|
+
memoryUsage: visibleData.length * 1024, // Rough estimation
|
|
218
|
+
itemCount: visibleData.length,
|
|
219
|
+
cacheHitRate: cacheStats.hitRate,
|
|
220
|
+
compressionRatio: compression ? 0.7 : 1.0,
|
|
221
|
+
lastCleanup: Date.now()
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
setMemoryStats(newStats)
|
|
225
|
+
|
|
226
|
+
if (enableAnalytics && analyticsCallback) {
|
|
227
|
+
analyticsCallback(newStats)
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
if (onMemoryUpdate) {
|
|
231
|
+
onMemoryUpdate(newStats)
|
|
232
|
+
}
|
|
233
|
+
}, [visibleData, enableAnalytics, analyticsCallback, onMemoryUpdate, compression])
|
|
234
|
+
|
|
235
|
+
// Auto cleanup effect
|
|
236
|
+
useEffect(() => {
|
|
237
|
+
if (!autoCleanup) return
|
|
238
|
+
|
|
239
|
+
const cleanupInterval = setInterval(() => {
|
|
240
|
+
const memoryUsage = (visibleData.length / maxMemoryItems)
|
|
241
|
+
if (memoryUsage > cleanupThreshold) {
|
|
242
|
+
// Basit cleanup - cache'i temizle
|
|
243
|
+
cacheRef.current.clear()
|
|
244
|
+
}
|
|
245
|
+
}, 5000) // Her 5 saniyede kontrol et
|
|
246
|
+
|
|
247
|
+
return () => clearInterval(cleanupInterval)
|
|
248
|
+
}, [autoCleanup, cleanupThreshold, maxMemoryItems, visibleData.length])
|
|
249
|
+
|
|
250
|
+
return (
|
|
251
|
+
<div
|
|
252
|
+
ref={containerRef}
|
|
253
|
+
className={cn(
|
|
254
|
+
"overflow-auto border rounded-lg bg-background",
|
|
255
|
+
className
|
|
256
|
+
)}
|
|
257
|
+
style={{ height }}
|
|
258
|
+
onScroll={handleScroll}
|
|
259
|
+
>
|
|
260
|
+
<div style={{ height: data.length * 60, position: 'relative' }}>
|
|
261
|
+
<div
|
|
262
|
+
style={{
|
|
263
|
+
transform: `translateY(${visibleRange.start * 60}px)`,
|
|
264
|
+
position: 'absolute',
|
|
265
|
+
width: '100%'
|
|
266
|
+
}}
|
|
267
|
+
>
|
|
268
|
+
{visibleData.map((item, index) => (
|
|
269
|
+
<React.Fragment key={visibleRange.start + index}>
|
|
270
|
+
{renderItem(item, visibleRange.start + index)}
|
|
271
|
+
</React.Fragment>
|
|
272
|
+
))}
|
|
273
|
+
</div>
|
|
274
|
+
</div>
|
|
275
|
+
</div>
|
|
276
|
+
)
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
// Memory Analytics Component
|
|
280
|
+
export interface MemoryAnalyticsProps {
|
|
281
|
+
onStatsUpdate?: (stats: MemoryStats) => void
|
|
282
|
+
showRealTime?: boolean
|
|
283
|
+
className?: string
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
export function MemoryAnalytics({
|
|
287
|
+
onStatsUpdate,
|
|
288
|
+
showRealTime = false,
|
|
289
|
+
className
|
|
290
|
+
}: MemoryAnalyticsProps) {
|
|
291
|
+
const [stats, setStats] = useState<MemoryStats>({
|
|
292
|
+
memoryUsage: 0,
|
|
293
|
+
itemCount: 0,
|
|
294
|
+
cacheHitRate: 0.95
|
|
295
|
+
})
|
|
296
|
+
|
|
297
|
+
// Mock real-time updates
|
|
298
|
+
useEffect(() => {
|
|
299
|
+
if (!showRealTime) return
|
|
300
|
+
|
|
301
|
+
const interval = setInterval(() => {
|
|
302
|
+
const newStats: MemoryStats = {
|
|
303
|
+
memoryUsage: Math.random() * 50 * 1024 * 1024, // 0-50MB
|
|
304
|
+
itemCount: Math.floor(Math.random() * 50000),
|
|
305
|
+
cacheHitRate: 0.9 + Math.random() * 0.1, // 90-100%
|
|
306
|
+
lastCleanup: Date.now()
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
setStats(newStats)
|
|
310
|
+
if (onStatsUpdate) {
|
|
311
|
+
onStatsUpdate(newStats)
|
|
312
|
+
}
|
|
313
|
+
}, 1000)
|
|
314
|
+
|
|
315
|
+
return () => clearInterval(interval)
|
|
316
|
+
}, [showRealTime, onStatsUpdate])
|
|
317
|
+
|
|
318
|
+
if (!showRealTime) {
|
|
319
|
+
return null
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
return (
|
|
323
|
+
<div className={cn("text-xs text-muted-foreground", className)}>
|
|
324
|
+
Memory Analytics Active - Updates every second
|
|
325
|
+
</div>
|
|
326
|
+
)
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
// Utility hook for streaming data
|
|
330
|
+
export function useStreamingData<T>(
|
|
331
|
+
initialData: T[] = [],
|
|
332
|
+
streamingConfig?: { interval?: number; maxItems?: number }
|
|
333
|
+
) {
|
|
334
|
+
const [data, setData] = useState<T[]>(initialData)
|
|
335
|
+
const { interval = 1000, maxItems = 10000 } = streamingConfig || {}
|
|
336
|
+
|
|
337
|
+
const addItem = useCallback((newItem: T) => {
|
|
338
|
+
setData(prev => {
|
|
339
|
+
const newData = [...prev, newItem]
|
|
340
|
+
return newData.length > maxItems ? newData.slice(-maxItems) : newData
|
|
341
|
+
})
|
|
342
|
+
}, [maxItems])
|
|
343
|
+
|
|
344
|
+
const clearData = useCallback(() => {
|
|
345
|
+
setData([])
|
|
346
|
+
}, [])
|
|
347
|
+
|
|
348
|
+
return { data, addItem, clearData }
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
// Export types
|
|
352
|
+
export type { MemoryConfig, MemoryStats, MemoryEfficientDataProps, MemoryAnalyticsProps }
|