@moontra/moonui-pro 2.18.5 → 2.19.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@moontra/moonui-pro",
3
- "version": "2.18.5",
3
+ "version": "2.19.0",
4
4
  "description": "Premium React components for MoonUI - Advanced UI library with 50+ pro components including performance, interactive, and gesture components",
5
5
  "type": "module",
6
6
  "main": "dist/index.mjs",
@@ -9,8 +9,8 @@ import { Card, CardContent } from "../ui/card"
9
9
  import { Button } from "../ui/button"
10
10
  import { useSubscription } from "../../hooks/use-subscription"
11
11
 
12
- const animatedButtonVariants = cva(
13
- "relative inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 overflow-hidden",
12
+ const moonUIAnimatedButtonProVariants = cva(
13
+ "relative inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium transition-all duration-200 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 overflow-hidden min-w-fit",
14
14
  {
15
15
  variants: {
16
16
  variant: {
@@ -20,68 +20,143 @@ const animatedButtonVariants = cva(
20
20
  secondary: "bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80",
21
21
  ghost: "hover:bg-accent hover:text-accent-foreground",
22
22
  link: "text-primary underline-offset-4 hover:underline",
23
+ gradient: "bg-gradient-to-r from-purple-600 to-pink-600 text-white hover:from-purple-700 hover:to-pink-700",
24
+ glow: "bg-primary text-primary-foreground shadow-lg hover:shadow-xl hover:shadow-primary/25",
23
25
  },
24
26
  size: {
25
27
  default: "h-9 px-4 py-2",
26
28
  sm: "h-8 rounded-md px-3 text-xs",
27
29
  lg: "h-10 rounded-md px-8",
28
- },
30
+ xl: "h-11 rounded-md px-6 text-base font-medium",
31
+ icon: "h-9 w-9",
32
+ }
29
33
  },
30
34
  defaultVariants: {
31
35
  variant: "default",
32
- size: "default",
36
+ size: "default"
33
37
  },
34
38
  }
35
39
  )
36
40
 
37
- interface AnimatedButtonProps
41
+ interface MoonUIAnimatedButtonProProps
38
42
  extends React.ButtonHTMLAttributes<HTMLButtonElement>,
39
- VariantProps<typeof animatedButtonVariants> {
43
+ VariantProps<typeof moonUIAnimatedButtonProVariants> {
40
44
  state?: "idle" | "loading" | "success" | "error"
41
45
  onStateChange?: (state: "idle" | "loading" | "success" | "error") => void
46
+ loadingText?: string
47
+ successText?: string
48
+ errorText?: string
49
+ ripple?: boolean
50
+ iconRotate?: boolean
51
+ shimmerSpeed?: "slow" | "normal" | "fast"
52
+ glowIntensity?: "low" | "medium" | "high"
53
+ showProgressBar?: boolean
54
+ autoResetDelay?: number
55
+ animation?: "none" | "bounce" | "pulse" | "shimmer" | "slide" | "scale" | "rotate" | "shake"
42
56
  }
43
57
 
44
- const AnimatedButtonInternal = React.forwardRef<HTMLButtonElement, AnimatedButtonProps>(
45
- ({ className, variant, size, state = "idle", onStateChange, children, onClick, ...props }, ref) => {
58
+ const MoonUIAnimatedButtonProInternal = React.forwardRef<HTMLButtonElement, MoonUIAnimatedButtonProProps>(
59
+ ({
60
+ className,
61
+ variant,
62
+ size,
63
+ animation = "none",
64
+ state = "idle",
65
+ onStateChange,
66
+ children,
67
+ onClick,
68
+ loadingText = "Loading...",
69
+ successText = "Success!",
70
+ errorText = "Error!",
71
+ ripple = false,
72
+ iconRotate = false,
73
+ shimmerSpeed = "normal",
74
+ glowIntensity = "medium",
75
+ showProgressBar = false,
76
+ autoResetDelay = 2000,
77
+ onDrag,
78
+ onDragEnd,
79
+ onDragStart,
80
+ onAnimationStart,
81
+ onAnimationEnd,
82
+ ...props
83
+ }, ref) => {
46
84
  const [internalState, setInternalState] = useState<"idle" | "loading" | "success" | "error">("idle")
85
+ const [ripples, setRipples] = useState<Array<{x: number, y: number, id: number}>>([])
86
+ const [progress, setProgress] = useState(0)
87
+ const [isHovered, setIsHovered] = useState(false)
47
88
  const currentState = state !== "idle" ? state : internalState
48
89
 
49
90
  const handleClick = async (e: React.MouseEvent<HTMLButtonElement>) => {
50
91
  if (currentState === "loading") return
51
92
 
93
+ // Ripple effect
94
+ if (ripple) {
95
+ const rect = e.currentTarget.getBoundingClientRect()
96
+ const x = e.clientX - rect.left
97
+ const y = e.clientY - rect.top
98
+ const id = Date.now()
99
+
100
+ setRipples([...ripples, { x, y, id }])
101
+ setTimeout(() => {
102
+ setRipples(prev => prev.filter(r => r.id !== id))
103
+ }, 600)
104
+ }
105
+
52
106
  setInternalState("loading")
53
107
  onStateChange?.("loading")
108
+ setProgress(0)
109
+
110
+ // Simulate progress
111
+ if (showProgressBar) {
112
+ const progressInterval = setInterval(() => {
113
+ setProgress(prev => {
114
+ if (prev >= 90) {
115
+ clearInterval(progressInterval)
116
+ return 90
117
+ }
118
+ return prev + 10
119
+ })
120
+ }, 200)
121
+ }
54
122
 
55
123
  if (onClick) {
56
124
  try {
57
125
  await onClick(e)
126
+ setProgress(100)
58
127
  setInternalState("success")
59
128
  onStateChange?.("success")
60
129
 
61
130
  setTimeout(() => {
62
131
  setInternalState("idle")
63
132
  onStateChange?.("idle")
64
- }, 2000)
133
+ setProgress(0)
134
+ }, autoResetDelay)
65
135
  } catch (error) {
136
+ setProgress(0)
66
137
  setInternalState("error")
67
138
  onStateChange?.("error")
68
139
 
69
140
  setTimeout(() => {
70
141
  setInternalState("idle")
71
142
  onStateChange?.("idle")
72
- }, 2000)
143
+ }, autoResetDelay)
73
144
  }
74
145
  }
75
146
  }
76
147
 
77
148
  const getIcon = () => {
149
+ const iconClass = cn("h-4 w-4", {
150
+ "animate-spin": currentState === "loading" || (iconRotate && currentState !== "idle"),
151
+ })
152
+
78
153
  switch (currentState) {
79
154
  case "loading":
80
- return <Loader2 className="h-4 w-4 animate-spin" />
155
+ return <Loader2 className={iconClass} />
81
156
  case "success":
82
- return <Check className="h-4 w-4" />
157
+ return <Check className={cn(iconClass, "animate-scale-in")} />
83
158
  case "error":
84
- return <X className="h-4 w-4" />
159
+ return <X className={cn(iconClass, "animate-shake")} />
85
160
  default:
86
161
  return null
87
162
  }
@@ -98,42 +173,140 @@ const AnimatedButtonInternal = React.forwardRef<HTMLButtonElement, AnimatedButto
98
173
  }
99
174
  }
100
175
 
176
+ const getShimmerSpeed = () => {
177
+ switch (shimmerSpeed) {
178
+ case "slow":
179
+ return "duration-1500"
180
+ case "fast":
181
+ return "duration-500"
182
+ default:
183
+ return "duration-1000"
184
+ }
185
+ }
186
+
187
+ const getGlowIntensity = () => {
188
+ switch (glowIntensity) {
189
+ case "low":
190
+ return "shadow-lg"
191
+ case "high":
192
+ return "shadow-2xl"
193
+ default:
194
+ return "shadow-xl"
195
+ }
196
+ }
197
+
198
+
199
+ // whileHover direkt olarak kullanılacak
200
+ let whileHoverAnimation: any = undefined
201
+ let whileTapAnimation: any = undefined
202
+
203
+ // Animation specific hover states
204
+ if (animation === "bounce") {
205
+ whileHoverAnimation = {
206
+ y: [0, -10, 0],
207
+ transition: {
208
+ duration: 0.6,
209
+ repeat: Infinity,
210
+ repeatType: "loop"
211
+ }
212
+ }
213
+ } else if (animation === "pulse") {
214
+ whileHoverAnimation = {
215
+ scale: [1, 1.1, 1],
216
+ transition: {
217
+ duration: 1,
218
+ repeat: Infinity,
219
+ repeatType: "loop"
220
+ }
221
+ }
222
+ } else if (animation === "shake") {
223
+ // Shake için CSS animation kullanacağız
224
+ whileHoverAnimation = undefined
225
+ } else if (animation === "rotate") {
226
+ whileHoverAnimation = {
227
+ rotate: 10,
228
+ transition: { type: "spring", stiffness: 300 }
229
+ }
230
+ } else if (animation === "scale") {
231
+ whileHoverAnimation = { scale: 1.05 }
232
+ whileTapAnimation = { scale: 0.95 }
233
+ } else if (animation === "slide") {
234
+ whileHoverAnimation = { y: -4 }
235
+ }
236
+
101
237
  return (
102
- <button
103
- className={cn(animatedButtonVariants({ variant, size }), className)}
238
+ <motion.button
239
+ {...props}
240
+ className={cn(
241
+ moonUIAnimatedButtonProVariants({ variant, size }),
242
+ variant === "glow" && getGlowIntensity(),
243
+ animation === "shake" && isHovered && "animate-shake",
244
+ className
245
+ )}
104
246
  ref={ref}
105
247
  onClick={handleClick}
106
248
  disabled={currentState === "loading" || props.disabled}
107
- {...props}
249
+ onMouseEnter={() => setIsHovered(true)}
250
+ onMouseLeave={() => setIsHovered(false)}
251
+ whileHover={whileHoverAnimation}
252
+ whileTap={whileTapAnimation}
108
253
  >
109
- <motion.div
110
- className="flex items-center gap-2"
111
- animate={{
112
- width: currentState !== "idle" ? "auto" : "100%"
113
- }}
114
- transition={{ duration: 0.2 }}
115
- >
254
+ {/* Progress Bar */}
255
+ {showProgressBar && currentState === "loading" && (
116
256
  <motion.div
117
- animate={{
118
- scale: currentState !== "idle" ? 1 : 0,
119
- width: currentState !== "idle" ? "auto" : 0
120
- }}
121
- transition={{ duration: 0.2 }}
122
- className="flex items-center"
123
- >
124
- {getIcon()}
125
- </motion.div>
126
-
127
- <motion.span
128
- animate={{
129
- opacity: currentState === "idle" ? 1 : 0,
130
- x: currentState !== "idle" ? -20 : 0
257
+ className="absolute bottom-0 left-0 h-1 bg-primary-foreground/20 rounded-full"
258
+ initial={{ width: 0 }}
259
+ animate={{ width: `${progress}%` }}
260
+ transition={{ duration: 0.3 }}
261
+ />
262
+ )}
263
+
264
+ {/* Shimmer Effect */}
265
+ {animation === "shimmer" && (
266
+ <motion.div
267
+ className="absolute inset-0 bg-gradient-to-r from-transparent via-white/20 to-transparent"
268
+ initial={{ x: "-100%" }}
269
+ animate={{ x: "100%" }}
270
+ transition={{
271
+ duration: shimmerSpeed === "slow" ? 1.5 : shimmerSpeed === "fast" ? 0.5 : 1,
272
+ repeat: Infinity,
273
+ repeatDelay: 1
131
274
  }}
132
- transition={{ duration: 0.2 }}
133
- >
134
- {children}
135
- </motion.span>
136
- </motion.div>
275
+ />
276
+ )}
277
+
278
+ {/* Content */}
279
+ <div className="relative flex items-center justify-center gap-2 z-10">
280
+ {/* Icon variant için özel düzenleme */}
281
+ {size === "icon" ? (
282
+ // Icon size için sadece icon göster
283
+ currentState === "idle" ? (
284
+ children
285
+ ) : (
286
+ getIcon()
287
+ )
288
+ ) : (
289
+ // Diğer boyutlar için normal akış
290
+ <>
291
+ {currentState === "idle" ? (
292
+ <>
293
+ {React.isValidElement(children) && React.cloneElement(children as React.ReactElement)}
294
+ {typeof children === 'string' && children}
295
+ {React.isValidElement(children) || typeof children === 'string' ? null : children}
296
+ </>
297
+ ) : (
298
+ <>
299
+ {getIcon()}
300
+ <span className="ml-2">
301
+ {currentState === "loading" && loadingText}
302
+ {currentState === "success" && successText}
303
+ {currentState === "error" && errorText}
304
+ </span>
305
+ </>
306
+ )}
307
+ </>
308
+ )}
309
+ </div>
137
310
 
138
311
  {/* Background animation */}
139
312
  <motion.div
@@ -144,27 +317,41 @@ const AnimatedButtonInternal = React.forwardRef<HTMLButtonElement, AnimatedButto
144
317
  initial={{ scale: 0, opacity: 0 }}
145
318
  animate={{
146
319
  scale: currentState === "success" || currentState === "error" ? 1 : 0,
147
- opacity: currentState === "success" || currentState === "error" ? 1 : 0
320
+ opacity: currentState === "success" || currentState === "error" ? 0.2 : 0
148
321
  }}
149
322
  transition={{ duration: 0.3 }}
150
- style={{ zIndex: -1 }}
323
+ style={{ zIndex: 0 }}
151
324
  />
152
- </button>
325
+
326
+ {/* Ripple Effect */}
327
+ {ripples.map(ripple => (
328
+ <span
329
+ key={ripple.id}
330
+ className="absolute bg-primary/20 rounded-full animate-ripple pointer-events-none"
331
+ style={{
332
+ left: ripple.x - 10,
333
+ top: ripple.y - 10,
334
+ width: 20,
335
+ height: 20,
336
+ }}
337
+ />
338
+ ))}
339
+ </motion.button>
153
340
  )
154
341
  }
155
342
  )
156
343
 
157
- AnimatedButtonInternal.displayName = "AnimatedButtonInternal"
344
+ MoonUIAnimatedButtonProInternal.displayName = "MoonUIAnimatedButtonProInternal"
158
345
 
159
- export const AnimatedButton = React.forwardRef<HTMLButtonElement, AnimatedButtonProps>(
160
- ({ className, ...props }, ref) => {
346
+ export const MoonUIAnimatedButtonPro = React.forwardRef<HTMLButtonElement, MoonUIAnimatedButtonProProps>(
347
+ (props, ref) => {
161
348
  // Pro package - always show component
162
349
  const { hasProAccess, isLoading } = useSubscription()
163
350
 
164
351
  // Show upgrade prompt if no pro access
165
352
  if (!isLoading && !hasProAccess) {
166
353
  return (
167
- <Card className={cn("w-fit", className)}>
354
+ <Card className={cn("w-fit", props.className)}>
168
355
  <CardContent className="py-6 text-center">
169
356
  <div className="space-y-4">
170
357
  <div className="rounded-full bg-purple-100 dark:bg-purple-900/30 p-3 w-fit mx-auto">
@@ -188,11 +375,11 @@ export const AnimatedButton = React.forwardRef<HTMLButtonElement, AnimatedButton
188
375
  )
189
376
  }
190
377
 
191
- return <AnimatedButtonInternal className={className} ref={ref} {...props} />
378
+ return <MoonUIAnimatedButtonProInternal {...props} ref={ref} />
192
379
  }
193
380
  )
194
381
 
195
- AnimatedButton.displayName = "AnimatedButton"
382
+ MoonUIAnimatedButtonPro.displayName = "MoonUIAnimatedButtonPro"
196
383
 
197
- export { animatedButtonVariants }
198
- export type { AnimatedButtonProps }
384
+ export { moonUIAnimatedButtonProVariants }
385
+ export type { MoonUIAnimatedButtonProProps }
@@ -12,8 +12,8 @@ const isDocsMode = () => {
12
12
 
13
13
  // Get cache duration based on mode
14
14
  const getCacheDuration = (defaultDuration: number) => {
15
- // Docs modunda cache süresini 30 dakikaya çıkar
16
- return isDocsMode() ? 1800000 : defaultDuration // 30 dakika : default
15
+ // Increase cache duration to 30 minutes in docs mode
16
+ return isDocsMode() ? 1800000 : defaultDuration // 30 minutes : default
17
17
  }
18
18
 
19
19
  // Language colors
@@ -134,7 +134,7 @@ export async function fetchUserRepositories(
134
134
  cache.set(cacheKey, {
135
135
  data: repos,
136
136
  timestamp: Date.now(),
137
- expiresAt: Date.now() + getCacheDuration(300000), // Docs modunda 30 dakika
137
+ expiresAt: Date.now() + getCacheDuration(300000), // 30 minutes in docs mode
138
138
  })
139
139
 
140
140
  return repos
@@ -159,7 +159,7 @@ export async function fetchRepository(
159
159
  cache.set(cacheKey, {
160
160
  data: repository,
161
161
  timestamp: Date.now(),
162
- expiresAt: Date.now() + getCacheDuration(300000), // Docs modunda 30 dakika
162
+ expiresAt: Date.now() + getCacheDuration(300000), // 30 minutes in docs mode
163
163
  })
164
164
 
165
165
  return repository
@@ -193,7 +193,7 @@ export async function fetchContributorsCount(
193
193
  cache.set(cacheKey, {
194
194
  data: count,
195
195
  timestamp: Date.now(),
196
- expiresAt: Date.now() + getCacheDuration(3600000), // Docs modunda 30 dakika
196
+ expiresAt: Date.now() + getCacheDuration(3600000), // 30 minutes in docs mode
197
197
  })
198
198
  return count
199
199
  }
@@ -206,7 +206,7 @@ export async function fetchContributorsCount(
206
206
  cache.set(cacheKey, {
207
207
  data: count,
208
208
  timestamp: Date.now(),
209
- expiresAt: Date.now() + getCacheDuration(3600000), // Docs modunda 30 dakika
209
+ expiresAt: Date.now() + getCacheDuration(3600000), // 30 minutes in docs mode
210
210
  })
211
211
 
212
212
  return count
@@ -246,7 +246,7 @@ export async function fetchStarHistory(
246
246
  cache.set(cacheKey, {
247
247
  data: history,
248
248
  timestamp: Date.now(),
249
- expiresAt: Date.now() + getCacheDuration(3600000), // Docs modunda 30 dakika
249
+ expiresAt: Date.now() + getCacheDuration(3600000), // 30 minutes in docs mode
250
250
  })
251
251
 
252
252
  return history
@@ -29,7 +29,7 @@ interface UseGitHubDataOptions {
29
29
  onDataUpdate?: (stats: GitHubStats) => void
30
30
  onMilestoneReached?: (milestone: Milestone) => void
31
31
  milestones?: number[]
32
- // Docs mode optimizasyonları için
32
+ // For docs mode optimizations
33
33
  docsMode?: boolean
34
34
  mockDataFallback?: boolean
35
35
  forceMockData?: boolean // Force mock data instead of API
@@ -52,12 +52,12 @@ export function useGitHubData({
52
52
  mockDataFallback = true,
53
53
  forceMockData = false,
54
54
  }: UseGitHubDataOptions) {
55
- // Docs mode tespiti
55
+ // Docs mode detection
56
56
  const isDocsMode = docsMode || (typeof window !== "undefined" &&
57
57
  (window.location.pathname.includes("/docs/") ||
58
58
  window.location.pathname.includes("/components/")))
59
59
 
60
- // Docs modunda autoRefresh'i devre dışı bırak
60
+ // Disable autoRefresh in docs mode
61
61
  const effectiveAutoRefresh = isDocsMode ? false : autoRefresh
62
62
  const [repos, setRepos] = useState<GitHubRepository[]>([])
63
63
  const [stats, setStats] = useState<GitHubStats | null>(null)
@@ -69,11 +69,11 @@ export function useGitHubData({
69
69
  const refreshTimeoutRef = useRef<NodeJS.Timeout>()
70
70
  const previousStarsRef = useRef<Map<string, number>>(new Map())
71
71
  const errorCountRef = useRef<number>(0) // Hata sayısını takip et
72
- const maxErrorCount = isDocsMode ? 1 : 2 // Docs modunda daha az deneme
72
+ const maxErrorCount = isDocsMode ? 1 : 2 // Fewer retries in docs mode
73
73
  const hasInitialFetchedRef = useRef(false) // İlk fetch yapıldı mı?
74
74
  const docsDataCacheRef = useRef<GitHubRepository[] | null>(null) // Docs mode cache
75
75
 
76
- // checkMilestones fonksiyonunu ref olarak sakla - bu şekilde her render'da yeniden oluşturulmaz
76
+ // Store checkMilestones function as ref - this way it won't be recreated on every render
77
77
  const milestonesRef = useRef(milestones)
78
78
  const onMilestoneReachedRef = useRef(onMilestoneReached)
79
79
 
@@ -135,7 +135,7 @@ export function useGitHubData({
135
135
  if (errorCountRef.current >= maxErrorCount) {
136
136
  console.warn("Maximum error count reached. Stopping requests.")
137
137
 
138
- // Docs modunda ve mockDataFallback aktifse mock data göster
138
+ // Show mock data if in docs mode and mockDataFallback is active
139
139
  if (isDocsMode && mockDataFallback) {
140
140
  const mockData = getMockGitHubData(username, repository, repositories)
141
141
  setRepos(mockData)
@@ -150,7 +150,7 @@ export function useGitHubData({
150
150
  return
151
151
  }
152
152
 
153
- // Gerekli bilgiler yoksa istek yapma
153
+ // Don't make requests if required info is missing
154
154
  const hasValidInput =
155
155
  (username && repository) || // Tek repository modu
156
156
  (username && repositories && repositories.length > 0) || // Çoklu repository modu
@@ -269,10 +269,10 @@ export function useGitHubData({
269
269
  }
270
270
 
271
271
  setLastUpdated(new Date())
272
- // Başarılı olduğunda hata sayacını sıfırla
272
+ // Reset error counter on success
273
273
  errorCountRef.current = 0
274
274
 
275
- // Docs modunda başarılı veriyi cache'le
275
+ // Cache successful data in docs mode
276
276
  if (isDocsMode) {
277
277
  hasInitialFetchedRef.current = true
278
278
  docsDataCacheRef.current = enhancedRepos
@@ -285,7 +285,7 @@ export function useGitHubData({
285
285
  errorCountRef.current += 1
286
286
  console.error(`GitHub API error (${errorCountRef.current}/${maxErrorCount}):`, errorMessage)
287
287
 
288
- // Docs modunda ve mockDataFallback aktifse mock data göster
288
+ // Show mock data if in docs mode and mockDataFallback is active
289
289
  if (isDocsMode && mockDataFallback && !hasInitialFetchedRef.current) {
290
290
  console.warn("[Docs Mode] API failed, using mock data")
291
291
  const mockData = getMockGitHubData(username, repository, repositories)
@@ -304,11 +304,11 @@ export function useGitHubData({
304
304
  }, [
305
305
  username,
306
306
  repository,
307
- repositories?.join(','), // Array'i string'e çevir ki referans değişmesin
307
+ repositories?.join(','), // Convert array to string to keep reference stable
308
308
  token,
309
309
  sortBy,
310
310
  maxItems,
311
- checkMilestones, // Artık stable
311
+ checkMilestones, // Now stable
312
312
  onDataUpdate,
313
313
  onError,
314
314
  isDocsMode,
@@ -318,7 +318,7 @@ export function useGitHubData({
318
318
 
319
319
  // Initial fetch
320
320
  useEffect(() => {
321
- // Sadece geçerli input varsa fetch yap
321
+ // Only fetch if there's valid input
322
322
  const hasValidInput =
323
323
  (username && repository) ||
324
324
  (username && repositories && repositories.length > 0) ||
@@ -334,7 +334,7 @@ export function useGitHubData({
334
334
 
335
335
  // Auto-refresh
336
336
  useEffect(() => {
337
- // Docs modunda auto-refresh'i tamamen devre dışı bırak
337
+ // Completely disable auto-refresh in docs mode
338
338
  if (!effectiveAutoRefresh) return
339
339
 
340
340
  const scheduleRefresh = () => {
@@ -354,7 +354,7 @@ export function useGitHubData({
354
354
  }, [effectiveAutoRefresh, refreshInterval, fetchData])
355
355
 
356
356
  const refresh = useCallback(() => {
357
- // Docs modunda refresh'i sınırla
357
+ // Limit refresh in docs mode
358
358
  if (isDocsMode && hasInitialFetchedRef.current) {
359
359
  console.warn("[Docs Mode] Refresh disabled after initial fetch")
360
360
  return Promise.resolve()
@@ -74,10 +74,10 @@ const GitHubStarsInternal: React.FC<GitHubStarsProps> = ({
74
74
  (window.location.pathname.includes("/docs/") ||
75
75
  window.location.pathname.includes("/components/"))
76
76
 
77
- // Docs modunda bazı özellikleri override et
77
+ // Override some features in docs mode
78
78
  const effectiveAutoRefresh = isDocsMode ? false : autoRefresh
79
79
  const effectiveNotifications = isDocsMode ? false : enableNotifications
80
- const effectiveRefreshInterval = isDocsMode ? 3600000 : refreshInterval // Docs modunda 1 saat
80
+ const effectiveRefreshInterval = isDocsMode ? 3600000 : refreshInterval // 1 hour in docs mode
81
81
  const { notify } = useGitHubNotifications(effectiveNotifications)
82
82
 
83
83
  // onMilestoneReached callback'ini memoize et
@@ -123,7 +123,7 @@ const GitHubStarsInternal: React.FC<GitHubStarsProps> = ({
123
123
  onMilestoneReached: handleMilestoneReached,
124
124
  milestones,
125
125
  docsMode: isDocsMode, // Docs mode flag'ini gönder
126
- mockDataFallback: true, // Docs modunda mock data kullan
126
+ mockDataFallback: true, // Use mock data in docs mode
127
127
  forceMockData: useMockData, // Force mock data if true
128
128
  })
129
129
 
@@ -317,7 +317,7 @@ const GitHubStarsInternal: React.FC<GitHubStarsProps> = ({
317
317
  >
318
318
  {renderVariant()}
319
319
 
320
- {/* Rate limit warning - Docs modunda gösterme */}
320
+ {/* Rate limit warning - Don't show in docs mode */}
321
321
  {!isDocsMode && rateLimitInfo && rateLimitInfo.remaining < 10 && (
322
322
  <div className="mt-4 p-3 bg-yellow-50 dark:bg-yellow-900/20 rounded-md text-sm">
323
323
  <p className="text-yellow-800 dark:text-yellow-200">
@@ -327,10 +327,10 @@ const GitHubStarsInternal: React.FC<GitHubStarsProps> = ({
327
327
  </div>
328
328
  )}
329
329
 
330
- {/* Docs mode indicator - sadece development modunda göster */}
330
+ {/* Docs mode indicator - only show in development mode */}
331
331
  {isDocsMode && process.env.NODE_ENV === "development" && (
332
332
  <div className="mt-2 text-xs text-muted-foreground text-center">
333
- 📚 Docs Mode: API istekleri optimize edildi
333
+ 📚 Docs Mode: API requests optimized
334
334
  </div>
335
335
  )}
336
336
  </motion.div>
@@ -4,7 +4,11 @@
4
4
  export * from "./ui"
5
5
 
6
6
  // Animated Button
7
- export * from "./animated-button"
7
+ export {
8
+ MoonUIAnimatedButtonPro,
9
+ moonUIAnimatedButtonProVariants,
10
+ type MoonUIAnimatedButtonProProps
11
+ } from "./animated-button"
8
12
 
9
13
  // Error Boundary
10
14
  export * from "./error-boundary"